Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OpenHarmony OS support #164

Merged
merged 2 commits into from May 15, 2024
Merged

Conversation

jschwe
Copy link
Contributor

@jschwe jschwe commented Apr 12, 2024

Add support for the OpenHarmony operating system, which is a tier-2 target in Rust starting with
Rust 1.78.
On OpenHarmony ArkUI is used to develop
applications. ArkUI provides the XComponent
type, which allows native code (e.g. Rust) to use
EGL / OpenGL ES to render directly to a native
window.

src/ohos.rs Outdated
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct OhosNdkWindowHandle {
pub xcomponent: NonNull<c_void>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you create EGLDisplay what you pass to it? I'd assume the xcomponent, but not a native_window? Or how does it work?

src/ohos.rs Outdated
Comment on lines 50 to 66
pub xcomponent: NonNull<c_void>,
pub native_window: NonNull<c_void>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you could link to documentation about these?

And can you get one from the other? If so, then I'd strongly prefer that we only store one of these pointers.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please link documentation. This would be an entirely new target.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some documentation to the module, including links to the relevant OpenHarmony documentation pages.

And can you get one from the other? If so, then I'd strongly prefer that we only store one of these pointers.

Not as far as I know. The native window and the xcomponent belong together, and are received via a callback when the XComponent is created.

@jschwe
Copy link
Contributor Author

jschwe commented Apr 17, 2024

Sorry for the slow reply.

I believe I was mistaken with my previous statement that the xcomponent pointer is also required - at least for my usecase of getting servo running on OpenHarmony, the APIs provided by OHNativeWindow seem to be sufficient.
I adjusted my PR and removed the XComponent, but since I'm not familiar with UIs and what exactly RawWindowHandles can be used for on other systems, let me give a short introduction and link the relevant documentation.

The latest version of the XComponent Guidelines available in English, seems to be Native XComponent Guidelines 4.0 (English).
On the master branch there currently is only the Chinese version, but version 4.0 is quite recent too.

To summarize the workflow (with the C++ examples in the documentation):

  1. The UI is defined in TypeScript code (ArkUI / ArkTS)
  2. The XComponent with the surface type can be used to get a native EGL surface
  3. Native code can receive a callback OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window) when the XComponent is created.
  4. The documentation suggests determining eglDisplay via eglGetDisplay(EGL_DEFAULT_DISPLAY). In servo I've been using egl.GetCurrentDisplay(); (same way as the native android servo app)
  5. The void* window (OHNativeWindow / EGLNativeWindowType) argument to OnSurfaceCreatedCB, is the eglWindow needed to create an eglSurface with eglCreateWindowSurface(eglDisplay_, eglConfig_, eglWindow_, NULL)

The API provided by OHNativeWindow is quite low level, and missing the following APIs compared
to the XComponent it belongs to:

  • Get the offset of the XComponent relative to the upper left of the screen.
  • Touch / Mouse / Key events
  • Registering new Callbacks for the XComponent
  • Set expected frame rate

I'm currently leaning towards it being fine if the OhosNdkWindowHandle would not allow usage of such APIs, but
I'm also not very familiar how raw-window-handle is used in practice (besides servo), so I'm very open to feedback.

Add support for the [OpenHarmony] operating system,
which is a [tier-2 target] in Rust starting with
Rust 1.79.
On OpenHarmony [ArkUI] is used to develop
applications. ArkUI provides the [XComponent]
type, which allows native code (e.g. Rust) to use
EGL / OpenGL ES to render directly to a native
window.

[tier-2 target]: https://doc.rust-lang.org/nightly/rustc/platform-support/openharmony.html
[OpenHarmony]: https://gitee.com/openharmony/docs/blob/master/en/OpenHarmony-Overview.md
[ArkUI]: https://gitee.com/openharmony/docs/blob/master/en/application-dev/ui/arkui-overview.md
[XComponent]: https://gitee.com/openharmony/docs/blob/master/en/application-dev/ui/arkts-common-components-xcomponent.md
@madsmtm
Copy link
Member

madsmtm commented May 7, 2024

I spent a few minutes trying to read the docs, and I still have no idea what an "XComponent" actually is? As in, what does it correspond to visually? Is it the top-level window itself? Or can components be nested like subsurfaces/subviews? If I tried to do some GUI development in OpenHarmony, and I wanted to place a button on the screen somewhere, would that button be a "subclass" (or similar) of XComponent, of OHNativeWindow, or of something entirely different?

@jschwe
Copy link
Contributor Author

jschwe commented May 7, 2024

On OpenHarmony ArkTS is the usual language apps including their UI are written in. ArkTS is a flavor of typescript, which adds some restrictions, like forcing initialization of variables and requiring that all types are known at compile time (i.e. any is forbidden). Additionally, ArkTS adds builtins for UI components (example).

The ArkTS XComponent can be used in the ArkTS UI code to obtain a surface, that the native C++ (or in our case Rust) code can render to using OpenGL. The size and position of the XComponent is determined by the ArkTS UI layout.

In this example the ArkTS UI definition is simply one Textbox (which is used as a URL bar) and beneath that an XComponent, which servo renders to using OpenGL.

Column() {
  TextInput(My_url_bar)
  XComponent()
}

See also Introduction to ArkUI

If I tried to do some GUI development in OpenHarmony, and I wanted to place a button on the screen somewhere, would that button be a "subclass" (or similar) of XComponent, of OHNativeWindow, or of something entirely different?

You would use the ArkTS Button builtin. The XComponent (surface type) is used when rendering directly from native code via OpenGL.

@madsmtm
Copy link
Member

madsmtm commented May 7, 2024

Can you query the size of the surface from just OHNativeWindow?

@jschwe
Copy link
Contributor Author

jschwe commented May 8, 2024

Yes, one can use OH_NativeWindow_NativeWindowHandleOpt(window, GET_BUFFER_GEOMETRY, height, width).

Obtaining the geometry of the local window buffer.
Variable arguments in the function: [Output] int32_t *height and [Output] int32_t *width.

Copy link
Member

@madsmtm madsmtm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, then I think this makes sense as-is, and if we later find that the XComponent is actually needed, then we can always add an optional field.

src/lib.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
Co-authored-by: Mads Marquart <mads@marquart.dk>
@jschwe jschwe marked this pull request as ready for review May 9, 2024 09:24
@jschwe jschwe changed the title Draft: Add OpenHarmony OS support Add OpenHarmony OS support May 10, 2024
@jschwe
Copy link
Contributor Author

jschwe commented May 15, 2024

Is there anything I still need to do before this can be merged? Should I squash?

@Lokathor
Copy link
Contributor

I can squash-merge

@Lokathor Lokathor merged commit d0aa91c into rust-windowing:master May 15, 2024
4 checks passed
@jschwe jschwe deleted the jschwender/ohos branch May 15, 2024 18:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants