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 support #4117

Draft
wants to merge 27 commits into
base: v0.30.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
b2f03f8
feat: add ohos for v0.30.x
richerfu Dec 29, 2024
18c0c5f
feat: adapte v0.30.x
richerfu Dec 31, 2024
723deba
fix
richerfu Jan 4, 2025
cd14832
Show opengl
richerfu Jan 9, 2025
a6eb3a5
feat: add eventloop ext for openharmony
richerfu Jan 14, 2025
851b404
refactor: remove mutex and lock
richerfu Jan 18, 2025
23e469e
refactor: code cleanup & remove useless code & implenment user event
richerfu Jan 19, 2025
5442457
chore: remove some code
richerfu Jan 19, 2025
97a0cc8
Switch to version
richerfu Jan 24, 2025
2fecb94
feat: add exit implement
richerfu Feb 5, 2025
8363a49
windows: fix the event loop not waking on accessibility requests
mwcampbell Dec 23, 2024
55d4910
x11: add workaround for disabling IME on gnome
kchibisov Dec 23, 2024
8043a97
x11: fix cursor grab mode tracking on error
kchibisov Dec 31, 2024
a38074b
api: add `ActivationToken::{from,into}_raw`
kchibisov Dec 31, 2024
2a70f0f
Winit version 0.30.8
kchibisov Jan 3, 2025
2f48b14
Use wrapper type for CFUUID (#4032)
killercup Jan 17, 2025
138163e
wayland: clear IME preedit only when necessary
tomcur Jan 17, 2025
97edf32
Document that we require cargo +nightly fmt (#4105)
madsmtm Jan 31, 2025
a48fb43
x11: fix crash with uim
kchibisov Feb 3, 2025
1104a04
x11: fix modifiers replay
kchibisov Feb 5, 2025
aeb13e3
ios: fix timers
madsmtm Feb 6, 2025
ef53a0c
Winit version 0.30.9
kchibisov Feb 5, 2025
72a0bd3
Re-export macro
richerfu Feb 7, 2025
962bd36
fix: remove unreachable implenment
richerfu Feb 12, 2025
f68c03a
Update version
richerfu Feb 12, 2025
4fa887c
Update dependence
richerfu Feb 20, 2025
f456b64
chore: add code owner
richerfu Feb 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@
# Orbital (Redox OS)
/src/platform/orbital.rs @jackpot51
/src/platform_impl/orbital @jackpot51

# OpenHarmony
/src/platform/ohos.rs @richerfu @jschwe
/src/platform_impl/ohos @richerfu @jschwe
7 changes: 6 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,12 @@ jobs:

- name: Generate lockfile
# Also updates the crates.io index
run: cargo generate-lockfile && cargo update -p ahash --precise 0.8.7 && cargo update -p bumpalo --precise 3.14.0
run: |
cargo generate-lockfile
cargo update -p ahash --precise 0.8.7
cargo update -p bumpalo --precise 3.14.0
cargo update -p objc2-encode --precise 4.0.3
cargo update -p orbclient --precise 0.3.47

- name: Install GCC Multilib
if: (matrix.platform.os == 'ubuntu-latest') && contains(matrix.platform.target, 'i686')
Expand Down
5 changes: 5 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ All patches have to be sent on Github as [pull requests][prs]. To simplify your
life during review it's recommended to check the "give contributors write access
to the branch" checkbox.

We use unstable Rustfmt options across the project, so please run
`cargo +nightly fmt` before submitting your work. If you are unable to do so,
the maintainers can do it for you before merging, just state so in your pull
request description.

#### Handling review

During the review process certain events could require an action from your side,
Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "winit"
version = "0.30.7"
version = "0.30.9"
authors = [
"The winit contributors",
"Pierre Krieger <pierre.krieger1708@gmail.com>",
Expand Down Expand Up @@ -112,6 +112,10 @@ softbuffer = { version = "0.4.0", default-features = false, features = [
"wayland-dlopen",
] }

[target.'cfg(target_env = "ohos")'.dependencies]
openharmony-ability = { version = "0.0.4" }
openharmony-ability-derive = { version = "0.0.3" }

[target.'cfg(target_os = "android")'.dependencies]
android-activity = "0.6.0"
ndk = { version = "0.9.0", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

```toml
[dependencies]
winit = "0.30.7"
winit = "0.30.9"
```

## [Documentation](https://docs.rs/winit)
Expand Down
3 changes: 2 additions & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ fn main() {
// Setup cfg aliases.
cfg_aliases! {
// Systems.
ohos_platform: { target_env = "ohos" },
android_platform: { target_os = "android" },
web_platform: { all(target_family = "wasm", target_os = "unknown") },
macos_platform: { target_os = "macos" },
ios_platform: { target_os = "ios" },
windows_platform: { target_os = "windows" },
apple: { any(target_os = "ios", target_os = "macos") },
free_unix: { all(unix, not(apple), not(android_platform), not(target_os = "emscripten")) },
free_unix: { all(unix, not(apple), not(android_platform), not(target_os = "emscripten"), not(ohos_platform)) },
redox: { target_os = "redox" },

// Native displays.
Expand Down
24 changes: 24 additions & 0 deletions src/changelog/v0.30.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
## 0.30.9

### Changed

- On Wayland, no longer send an explicit clearing `Ime::Preedit` just prior to a new `Ime::Preedit`.

### Fixed

- On X11, fix crash with uim.
- On X11, fix modifiers for keys that were sent by the same X11 request.
- On iOS, fix high CPU usage even when using `ControlFlow::Wait`.

## 0.30.8

### Added

- `ActivationToken::from_raw` and `ActivationToken::into_raw`.
- On X11, add a workaround for disabling IME on GNOME.

### Fixed

- On Windows, fixed the event loop not waking on accessibility requests.
- On X11, fixed cursor grab mode state tracking on error.

## 0.30.7

### Fixed
Expand Down
4 changes: 2 additions & 2 deletions src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ impl<T> EventLoop<T> {
/// [`run_app`]: Self::run_app
#[inline]
#[deprecated = "use `EventLoop::run_app` instead"]
#[cfg(not(all(web_platform, target_feature = "exception-handling")))]
#[cfg(not(any(all(web_platform, target_feature = "exception-handling"), target_env = "ohos")))]
pub fn run<F>(self, event_handler: F) -> Result<(), EventLoopError>
where
F: FnMut(Event<T>, &ActiveEventLoop),
Expand Down Expand Up @@ -260,7 +260,7 @@ impl<T> EventLoop<T> {
/// [`run_app()`]: Self::run_app()
/// [^1]: `EventLoopExtWebSys::spawn_app()` is only available on Web.
#[inline]
#[cfg(not(all(web_platform, target_feature = "exception-handling")))]
#[cfg(not(any(all(web_platform, target_feature = "exception-handling"), target_env = "ohos")))]
pub fn run_app<A: ApplicationHandler<T>>(self, app: &mut A) -> Result<(), EventLoopError> {
self.event_loop.run(|event, event_loop| dispatch_event_for_app(app, event_loop, event))
}
Expand Down
8 changes: 7 additions & 1 deletion src/keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ pub enum NativeKey {
Unidentified,
/// An Android "keycode", which is similar to a "virtual-key code" on Windows.
Android(u32),
// An OpenHarmony "keycode".
Ohos(u32),
/// A macOS "scancode". There does not appear to be any direct analogue to either keysyms or
/// "virtual-key" codes in macOS, so we report the scancode instead.
MacOS(u16),
Expand All @@ -157,7 +159,7 @@ pub enum NativeKey {

impl std::fmt::Debug for NativeKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use NativeKey::{Android, MacOS, Unidentified, Web, Windows, Xkb};
use NativeKey::{Android, MacOS, Unidentified, Web, Windows, Xkb, Ohos};
let mut debug_tuple;
match self {
Unidentified => {
Expand All @@ -167,6 +169,10 @@ impl std::fmt::Debug for NativeKey {
debug_tuple = f.debug_tuple("Android");
debug_tuple.field(&format_args!("0x{code:04X}"));
},
Ohos(code) => {
debug_tuple = f.debug_tuple("Ohos");
debug_tuple.field(&format_args!("0x{code:04X}"));
}
MacOS(code) => {
debug_tuple = f.debug_tuple("MacOS");
debug_tuple.field(&format_args!("0x{code:04X}"));
Expand Down
2 changes: 1 addition & 1 deletion src/platform/android.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
//! If your application is currently based on `NativeActivity` via the `ndk-glue` crate and building
//! with `cargo apk`, then the minimal changes would be:
//! 1. Remove `ndk-glue` from your `Cargo.toml`
//! 2. Enable the `"android-native-activity"` feature for Winit: `winit = { version = "0.30.7",
//! 2. Enable the `"android-native-activity"` feature for Winit: `winit = { version = "0.30.9",
//! features = [ "android-native-activity" ] }`
//! 3. Add an `android_main` entrypoint (as above), instead of using the '`[ndk_glue::main]` proc
//! macro from `ndk-macros` (optionally add a dependency on `android_logger` and initialize
Expand Down
2 changes: 2 additions & 0 deletions src/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ pub mod web;
pub mod windows;
#[cfg(any(x11_platform, docsrs))]
pub mod x11;
#[cfg(any(ohos_platform, docsrs))]
pub mod ohos;

#[cfg(any(
windows_platform,
Expand Down
136 changes: 136 additions & 0 deletions src/platform/ohos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
//! # OpenHarmony
//!
//! The OpenHarmony backend builds on (and exposes types from) the [`ohos-rs`](https://docs.rs/ohos-rs/) crate.
//!
//! Native OpenHarmony applications need some form of "glue" crate that is responsible
//! for defining the main entry point for your Rust application as well as tracking
//! various life-cycle events and synchronizing with the main thread.
//!
//! Winit uses the [openharmony-ability](https://docs.rs/openharmony-ability/) as a
//! glue crate.
//!

use self::ability::{Configuration, OpenHarmonyApp, Rect};
use crate::application::ApplicationHandler;
use crate::event_loop::{self, ActiveEventLoop, EventLoop, EventLoopBuilder};
use crate::window::{Window, WindowAttributes};

/// Additional methods on [`EventLoop`] that are specific to OpenHarmony.
pub trait EventLoopExtOpenHarmony {
/// A type provided by the user that can be passed through `Event::UserEvent`.
type UserEvent: 'static;

/// Initializes the winit event loop.
/// Unlike [`run_app()`] this method return immediately.
/// [^1]: `run_app()` is _not_ available on OpnHarmony
fn spawn_app<A: ApplicationHandler<Self::UserEvent> + 'static>(self, app: A);

/// Get the [`OpenHarmonyApp`] which was used to create this event loop.
fn openharmony_app(&self) -> &OpenHarmonyApp;
}

impl<T> EventLoopExtOpenHarmony for EventLoop<T> {
type UserEvent = T;

fn spawn_app<A: ApplicationHandler<Self::UserEvent> + 'static>(self, app: A) {
let app = Box::leak(Box::new(app));
let event_looper = Box::leak(Box::new(self));

event_looper
.event_loop
.run(|event, event_loop| event_loop::dispatch_event_for_app(app, event_loop, event));
}

fn openharmony_app(&self) -> &OpenHarmonyApp {
&self.event_loop.openharmony_app
}
}

/// Additional methods on [`ActiveEventLoop`] that are specific to OpenHarmony.
pub trait ActiveEventLoopExtOpenHarmony {
/// Get the [`OpenHarmonyApp`] which was used to create this event loop.
fn openharmony_app(&self) -> &OpenHarmonyApp;
}

/// Additional methods on [`Window`] that are specific to OpenHarmony.
pub trait WindowExtOpenHarmony {
fn content_rect(&self) -> Rect;

fn config(&self) -> Configuration;
}

impl WindowExtOpenHarmony for Window {
fn content_rect(&self) -> Rect {
self.window.content_rect()
}

fn config(&self) -> Configuration {
self.window.config()
}
}

impl ActiveEventLoopExtOpenHarmony for ActiveEventLoop {
fn openharmony_app(&self) -> &OpenHarmonyApp {
&self.p.app
}
}

/// Additional methods on [`WindowAttributes`] that are specific to OpenHarmony.
pub trait WindowAttributesExtOpenHarmony {}

impl WindowAttributesExtOpenHarmony for WindowAttributes {}

pub trait EventLoopBuilderExtOpenHarmony {
/// Associates the [`OpenHarmonyApp`] that was passed to `openharmony-ability::ability` with the event loop
///
/// This must be called on OpenHarmony since the [`OpenHarmonyApp`] is not global state.
fn with_openharmony_app(&mut self, app: OpenHarmonyApp) -> &mut Self;
}

impl<T> EventLoopBuilderExtOpenHarmony for EventLoopBuilder<T> {
fn with_openharmony_app(&mut self, app: OpenHarmonyApp) -> &mut Self {
self.platform_specific.openharmony_app = Some(app);
self
}
}

/// Re-export of the `openharmony-ability` API
///
/// Winit re-exports the `openharmony-ability` API for convenience so that most
/// applications can rely on the Winit crate to resolve the required version of
/// `openharmony-ability` and avoid any chance of a conflict between Winit and the
/// application crate.
///
///
/// For compatibility applications should then import the [`OpenHarmonyApp`] type for
/// their `init(app: OpenHarmonyApp)` function and use `openharmony-ability-derive` to
/// implement entry like:
/// ```rust
/// #[cfg(target_env = "ohos")]
/// use winit::platform::ohos::ability::OpenHarmonyApp;
/// use openharmony_ability_derive::ability;
///
/// #[ability]
/// fn init(app: OpenHarmonyApp) {
/// // ...
/// }
/// ```
pub mod ability {
#[doc(no_inline)]
#[cfg(ohos_platform)]
pub use openharmony_ability::*;

#[doc(no_inline)]
#[cfg(ohos_platform)]
pub use openharmony_ability_derive::*;

#[cfg(not(ohos_platform))]
#[doc(hidden)]
pub struct Rect;
#[cfg(not(ohos_platform))]
#[doc(hidden)]
pub struct ConfigurationRef;
#[cfg(not(ohos_platform))]
#[doc(hidden)]
pub struct OpenHarmonyApp;
}
6 changes: 3 additions & 3 deletions src/platform/startup_notify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ impl EventLoopExtStartupNotify for ActiveEventLoop {
crate::platform_impl::ActiveEventLoop::X(_) => env::var(X11_VAR),
}
.ok()
.map(ActivationToken::_new)
.map(ActivationToken::from_raw)
}
}

Expand Down Expand Up @@ -94,6 +94,6 @@ pub fn reset_activation_token_env() {
///
/// This could be used before running daemon processes.
pub fn set_activation_token_env(token: ActivationToken) {
env::set_var(X11_VAR, &token._token);
env::set_var(WAYLAND_VAR, token._token);
env::set_var(X11_VAR, &token.token);
env::set_var(WAYLAND_VAR, token.token);
}
1 change: 1 addition & 0 deletions src/platform_impl/ios/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,7 @@ impl AppState {
(ControlFlow::Wait, ControlFlow::Wait) => {
let start = Instant::now();
self.set_state(AppStateImpl::Waiting { waiting_handler, start });
self.waker.stop()
},
(ControlFlow::WaitUntil(old_instant), ControlFlow::WaitUntil(new_instant))
if old_instant == new_instant =>
Expand Down
14 changes: 9 additions & 5 deletions src/platform_impl/linux/wayland/seat/text_input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,15 @@ impl Dispatch<ZwpTextInputV3, TextInputData, WinitState> for TextInputState {
None => return,
};

// Clear preedit at the start of `Done`.
state.events_sink.push_window_event(
WindowEvent::Ime(Ime::Preedit(String::new(), None)),
window_id,
);
// Clear preedit, unless all we'll be doing next is sending a new preedit.
if text_input_data.pending_commit.is_some()
|| text_input_data.pending_preedit.is_none()
{
state.events_sink.push_window_event(
WindowEvent::Ime(Ime::Preedit(String::new(), None)),
window_id,
);
}

// Send `Commit`.
if let Some(text) = text_input_data.pending_commit.take() {
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/linux/wayland/types/xdg_activation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ impl Dispatch<XdgActivationTokenV1, XdgActivationTokenData, WinitState> for XdgA
state.events_sink.push_window_event(
crate::event::WindowEvent::ActivationTokenDone {
serial: *serial,
token: ActivationToken::_new(token),
token: ActivationToken::from_raw(token),
},
*window_id,
);
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/linux/wayland/window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ impl Window {
if let (Some(xdg_activation), Some(token)) =
(xdg_activation.as_ref(), attributes.platform_specific.activation_token)
{
xdg_activation.activate(token._token, &surface);
xdg_activation.activate(token.token, &surface);
}

// XXX Do initial commit.
Expand Down
Loading
Loading