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

Winit version 0.30.9 #4114

Merged
merged 7 commits into from
Feb 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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
Copy link
Member

Choose a reason for hiding this comment

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

Makes no sense to include this change IMO

`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
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "winit"
version = "0.30.8"
version = "0.30.9"
authors = [
"The winit contributors",
"Pierre Krieger <[email protected]>",
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.8"
winit = "0.30.9"
```

## [Documentation](https://docs.rs/winit)
Expand Down
12 changes: 12 additions & 0 deletions src/changelog/v0.30.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## 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
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.8",
//! 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
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
13 changes: 7 additions & 6 deletions src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ pub struct EventProcessor {
pub active_window: Option<xproto::Window>,
/// Latest modifiers we've sent for the user to trigger change in event.
pub modifiers: Cell<ModifiersState>,
pub xfiltered_modifiers: VecDeque<c_ulong>,
// Track modifiers based on keycodes. NOTE: that serials generally don't work for tracking
// since they are not unique and could be duplicated in case of sequence of key events is
// delivered at near the same time.
pub xfiltered_modifiers: VecDeque<u8>,
pub xmodmap: util::ModifierKeymap,
pub is_composing: bool,
}
Expand Down Expand Up @@ -163,13 +166,11 @@ impl EventProcessor {
let xev: &XKeyEvent = xev.as_ref();
if self.xmodmap.is_modifier(xev.keycode as u8) {
// Don't grow the buffer past the `MAX_MOD_REPLAY_LEN`. This could happen
// when the modifiers are consumed entirely or serials are altered.
//
// Both cases shouldn't happen in well behaving clients.
// when the modifiers are consumed entirely.
if self.xfiltered_modifiers.len() == MAX_MOD_REPLAY_LEN {
self.xfiltered_modifiers.pop_back();
}
self.xfiltered_modifiers.push_front(xev.serial);
self.xfiltered_modifiers.push_front(xev.keycode as u8);
}
}

Expand Down Expand Up @@ -950,7 +951,7 @@ impl EventProcessor {
// itself are out of sync due to XkbState being delivered before XKeyEvent, since it's
// being replayed by the XIM, thus we should replay ourselves.
let replay = if let Some(position) =
self.xfiltered_modifiers.iter().rev().position(|&s| s == xev.serial)
self.xfiltered_modifiers.iter().rev().position(|&s| s == xev.keycode as u8)
{
// We don't have to replay modifiers pressed before the current event if some events
// were not forwarded to us, since their state is irrelevant.
Expand Down
8 changes: 2 additions & 6 deletions src/platform_impl/linux/x11/ime/callbacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,15 @@ unsafe fn replace_im(inner: *mut ImeInner) -> Result<(), ReplaceImError> {
let is_allowed =
old_context.as_ref().map(|old_context| old_context.is_allowed()).unwrap_or_default();

// We can't use the style from the old context here, since it may change on reload, so
// pick style from the new XIM based on the old state.
let style = if is_allowed { new_im.preedit_style } else { new_im.none_style };

let new_context = {
let result = unsafe {
ImeContext::new(
xconn,
new_im.im,
style,
&new_im,
*window,
spot,
(*inner).event_sender.clone(),
is_allowed,
)
};
if result.is_err() {
Expand Down
25 changes: 14 additions & 11 deletions src/platform_impl/linux/x11/ime/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ use std::{mem, ptr};

use x11_dl::xlib::{XIMCallback, XIMPreeditCaretCallbackStruct, XIMPreeditDrawCallbackStruct};

use crate::platform_impl::platform::x11::ime::input_method::{Style, XIMStyle};
use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventSender};

use super::{ffi, util, XConnection, XError};
use crate::platform_impl::platform::x11::ime::input_method::{InputMethod, Style, XIMStyle};
use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventSender};

/// IME creation error.
#[derive(Debug)]
Expand Down Expand Up @@ -184,7 +183,7 @@ struct ImeContextClientData {
pub struct ImeContext {
pub(crate) ic: ffi::XIC,
pub(crate) ic_spot: ffi::XPoint,
pub(crate) style: Style,
pub(crate) allowed: bool,
// Since the data is passed shared between X11 XIM callbacks, but couldn't be directly free
// from there we keep the pointer to automatically deallocate it.
_client_data: Box<ImeContextClientData>,
Expand All @@ -193,11 +192,11 @@ pub struct ImeContext {
impl ImeContext {
pub(crate) unsafe fn new(
xconn: &Arc<XConnection>,
im: ffi::XIM,
style: Style,
im: &InputMethod,
window: ffi::Window,
ic_spot: Option<ffi::XPoint>,
event_sender: ImeEventSender,
allowed: bool,
) -> Result<Self, ImeContextCreationError> {
let client_data = Box::into_raw(Box::new(ImeContextClientData {
window,
Expand All @@ -206,20 +205,24 @@ impl ImeContext {
cursor_pos: 0,
}));

let style = if allowed { im.preedit_style } else { im.none_style };

let ic = match style as _ {
Style::Preedit(style) => unsafe {
ImeContext::create_preedit_ic(
xconn,
im,
im.im,
style,
window,
client_data as ffi::XPointer,
)
},
Style::Nothing(style) => unsafe {
ImeContext::create_nothing_ic(xconn, im, style, window)
ImeContext::create_nothing_ic(xconn, im.im, style, window)
},
Style::None(style) => unsafe {
ImeContext::create_none_ic(xconn, im.im, style, window)
},
Style::None(style) => unsafe { ImeContext::create_none_ic(xconn, im, style, window) },
}
.ok_or(ImeContextCreationError::Null)?;

Expand All @@ -228,7 +231,7 @@ impl ImeContext {
let mut context = ImeContext {
ic,
ic_spot: ffi::XPoint { x: 0, y: 0 },
style,
allowed,
_client_data: unsafe { Box::from_raw(client_data) },
};

Expand Down Expand Up @@ -335,7 +338,7 @@ impl ImeContext {
}

pub fn is_allowed(&self) -> bool {
!matches!(self.style, Style::None(_))
self.allowed
}

// Set the spot for preedit text. Setting spot isn't working with libX11 when preedit callbacks
Expand Down
4 changes: 1 addition & 3 deletions src/platform_impl/linux/x11/ime/input_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,7 @@ impl InputMethod {
}

let preedit_style = preedit_style.unwrap_or_else(|| none_style.unwrap());
// Always initialize none style even when it's not advertised, since it seems to work
// regardless...
let none_style = none_style.unwrap_or(Style::None(XIM_NONE_STYLE));
let none_style = none_style.unwrap_or(preedit_style);

Some(InputMethod { im, _name: name, preedit_style, none_style })
}
Expand Down
27 changes: 6 additions & 21 deletions src/platform_impl/linux/x11/ime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,13 @@ use std::sync::Arc;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use tracing::debug;

use super::{ffi, util, XConnection, XError};

use self::callbacks::*;
use self::context::ImeContext;
pub use self::context::ImeContextCreationError;
use self::inner::{close_im, ImeInner};
use self::input_method::{PotentialInputMethods, Style};
use self::input_method::PotentialInputMethods;
use super::{ffi, util, XConnection, XError};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
Expand Down Expand Up @@ -114,39 +112,26 @@ impl Ime {
pub fn create_context(
&mut self,
window: ffi::Window,
with_preedit: bool,
with_ime: bool,
) -> Result<bool, ImeContextCreationError> {
let context = if self.is_destroyed() {
// Create empty entry in map, so that when IME is rebuilt, this window has a context.
None
} else {
let im = self.inner.im.as_ref().unwrap();
let style = if with_preedit { im.preedit_style } else { im.none_style };

let context = unsafe {
ImeContext::new(
&self.inner.xconn,
im.im,
style,
im,
window,
None,
self.inner.event_sender.clone(),
with_ime,
)?
};

// Check the state on the context, since it could fail to enable or disable preedit.
let event = if matches!(style, Style::None(_)) {
if with_preedit {
debug!("failed to create IME context with preedit support.")
}
ImeEvent::Disabled
} else {
if !with_preedit {
debug!("failed to create IME context without preedit support.")
}
ImeEvent::Enabled
};

let event = if context.is_allowed() { ImeEvent::Enabled } else { ImeEvent::Disabled };
self.inner.event_sender.send((window, event)).expect("Failed to send enabled event");

Some(context)
Expand Down
Loading
Loading