Move ModifiersChanged variant to WindowEvent

This commit is contained in:
Murarth
2020-01-08 20:22:38 -07:00
parent 09c4ed0694
commit ed348f231e
6 changed files with 109 additions and 63 deletions

View File

@@ -3,6 +3,7 @@
- On Windows, fix bug where `RedrawRequested` would only get emitted every other iteration of the event loop. - On Windows, fix bug where `RedrawRequested` would only get emitted every other iteration of the event loop.
- On X11, fix deadlock on window state when handling certain window events. - On X11, fix deadlock on window state when handling certain window events.
- `WindowBuilder` now implements `Default`. - `WindowBuilder` now implements `Default`.
- **Breaking:** Move `ModifiersChanged` variant from `DeviceEvent` to `WindowEvent`.
# 0.20.0 (2020-01-05) # 0.20.0 (2020-01-05)

View File

@@ -38,6 +38,7 @@ fn main() {
_ => (), _ => (),
} }
} }
WindowEvent::ModifiersChanged(m) => modifiers = m,
_ => (), _ => (),
}, },
Event::DeviceEvent { event, .. } => match event { Event::DeviceEvent { event, .. } => match event {
@@ -46,7 +47,6 @@ fn main() {
ElementState::Pressed => println!("mouse button {} pressed", button), ElementState::Pressed => println!("mouse button {} pressed", button),
ElementState::Released => println!("mouse button {} released", button), ElementState::Released => println!("mouse button {} released", button),
}, },
DeviceEvent::ModifiersChanged(m) => modifiers = m,
_ => (), _ => (),
}, },
_ => (), _ => (),

View File

@@ -235,6 +235,13 @@ pub enum WindowEvent<'a> {
is_synthetic: bool, is_synthetic: bool,
}, },
/// The keyboard modifiers have changed.
///
/// Platform-specific behavior:
/// - **Web**: This API is currently unimplemented on the web. This isn't by design - it's an
/// issue, and it should get fixed - but it's the current state of the API.
ModifiersChanged(ModifiersState),
/// The cursor has moved on the window. /// The cursor has moved on the window.
CursorMoved { CursorMoved {
device_id: DeviceId, device_id: DeviceId,
@@ -243,7 +250,7 @@ pub enum WindowEvent<'a> {
/// limited by the display area and it may have been transformed by the OS to implement effects such as cursor /// limited by the display area and it may have been transformed by the OS to implement effects such as cursor
/// acceleration, it should not be used to implement non-cursor-like interactions such as 3D camera control. /// acceleration, it should not be used to implement non-cursor-like interactions such as 3D camera control.
position: PhysicalPosition<i32>, position: PhysicalPosition<i32>,
#[deprecated = "Deprecated in favor of DeviceEvent::ModifiersChanged"] #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
modifiers: ModifiersState, modifiers: ModifiersState,
}, },
@@ -258,7 +265,7 @@ pub enum WindowEvent<'a> {
device_id: DeviceId, device_id: DeviceId,
delta: MouseScrollDelta, delta: MouseScrollDelta,
phase: TouchPhase, phase: TouchPhase,
#[deprecated = "Deprecated in favor of DeviceEvent::ModifiersChanged"] #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
modifiers: ModifiersState, modifiers: ModifiersState,
}, },
@@ -267,7 +274,7 @@ pub enum WindowEvent<'a> {
device_id: DeviceId, device_id: DeviceId,
state: ElementState, state: ElementState,
button: MouseButton, button: MouseButton,
#[deprecated = "Deprecated in favor of DeviceEvent::ModifiersChanged"] #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
modifiers: ModifiersState, modifiers: ModifiersState,
}, },
@@ -341,6 +348,7 @@ impl<'a> WindowEvent<'a> {
input, input,
is_synthetic, is_synthetic,
}), }),
ModifiersChanged(modifiers) => Some(ModifiersChanged(modifiers)),
#[allow(deprecated)] #[allow(deprecated)]
CursorMoved { CursorMoved {
device_id, device_id,
@@ -464,16 +472,6 @@ pub enum DeviceEvent {
Key(KeyboardInput), Key(KeyboardInput),
/// The keyboard modifiers have changed.
///
/// This is tracked internally to avoid tracking errors arising from modifier key state changes when events from
/// this device are not being delivered to the application, e.g. due to keyboard focus being elsewhere.
///
/// Platform-specific behavior:
/// - **Web**: This API is currently unimplemented on the web. This isn't by design - it's an
/// issue, and it should get fixed - but it's the current state of the API.
ModifiersChanged(ModifiersState),
Text { Text {
codepoint: char, codepoint: char,
}, },
@@ -502,7 +500,7 @@ pub struct KeyboardInput {
/// ///
/// This is tracked internally to avoid tracking errors arising from modifier key state changes when events from /// This is tracked internally to avoid tracking errors arising from modifier key state changes when events from
/// this device are not being delivered to the application, e.g. due to keyboard focus being elsewhere. /// this device are not being delivered to the application, e.g. due to keyboard focus being elsewhere.
#[deprecated = "Deprecated in favor of DeviceEvent::ModifiersChanged"] #[deprecated = "Deprecated in favor of WindowEvent::ModifiersChanged"]
pub modifiers: ModifiersState, pub modifiers: ModifiersState,
} }

View File

@@ -8,9 +8,7 @@ use smithay_client_toolkit::{
reexports::client::protocol::{wl_keyboard, wl_seat}, reexports::client::protocol::{wl_keyboard, wl_seat},
}; };
use crate::event::{ use crate::event::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent};
DeviceEvent, ElementState, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent,
};
pub fn init_keyboard( pub fn init_keyboard(
seat: &wl_seat::WlSeat, seat: &wl_seat::WlSeat,
@@ -33,9 +31,24 @@ pub fn init_keyboard(
let wid = make_wid(&surface); let wid = make_wid(&surface);
my_sink.send_window_event(WindowEvent::Focused(true), wid); my_sink.send_window_event(WindowEvent::Focused(true), wid);
*target.lock().unwrap() = Some(wid); *target.lock().unwrap() = Some(wid);
let modifiers = *modifiers_tracker.lock().unwrap();
if !modifiers.is_empty() {
my_sink.send_window_event(WindowEvent::ModifiersChanged(modifiers), wid);
}
} }
KbEvent::Leave { surface, .. } => { KbEvent::Leave { surface, .. } => {
let wid = make_wid(&surface); let wid = make_wid(&surface);
let modifiers = *modifiers_tracker.lock().unwrap();
if !modifiers.is_empty() {
my_sink.send_window_event(
WindowEvent::ModifiersChanged(ModifiersState::empty()),
wid,
);
}
my_sink.send_window_event(WindowEvent::Focused(false), wid); my_sink.send_window_event(WindowEvent::Focused(false), wid);
*target.lock().unwrap() = None; *target.lock().unwrap() = None;
} }
@@ -88,7 +101,9 @@ pub fn init_keyboard(
*modifiers_tracker.lock().unwrap() = modifiers; *modifiers_tracker.lock().unwrap() = modifiers;
my_sink.send_device_event(DeviceEvent::ModifiersChanged(modifiers), DeviceId); if let Some(wid) = *target.lock().unwrap() {
my_sink.send_window_event(WindowEvent::ModifiersChanged(modifiers), wid);
}
} }
} }
}, },

View File

@@ -32,6 +32,8 @@ pub(super) struct EventProcessor<T: 'static> {
// Number of touch events currently in progress // Number of touch events currently in progress
pub(super) num_touch: u32, pub(super) num_touch: u32,
pub(super) first_touch: Option<u64>, pub(super) first_touch: Option<u64>,
// Currently focused window belonging to this process
pub(super) active_window: Option<ffi::Window>,
} }
impl<T: 'static> EventProcessor<T> { impl<T: 'static> EventProcessor<T> {
@@ -136,14 +138,15 @@ impl<T: 'static> EventProcessor<T> {
if let Some(modifiers) = if let Some(modifiers) =
self.device_mod_state.update_state(&state, modifier) self.device_mod_state.update_state(&state, modifier)
{ {
let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD); if let Some(window_id) = self.active_window {
callback(Event::DeviceEvent { callback(Event::WindowEvent {
device_id, window_id: mkwid(window_id),
event: DeviceEvent::ModifiersChanged(modifiers), event: WindowEvent::ModifiersChanged(modifiers),
}); });
} }
} }
} }
}
}}; }};
} }
@@ -874,21 +877,31 @@ impl<T: 'static> EventProcessor<T> {
ffi::XI_FocusIn => { ffi::XI_FocusIn => {
let xev: &ffi::XIFocusInEvent = unsafe { &*(xev.data as *const _) }; let xev: &ffi::XIFocusInEvent = unsafe { &*(xev.data as *const _) };
let window_id = mkwid(xev.event);
wt.ime wt.ime
.borrow_mut() .borrow_mut()
.focus(xev.event) .focus(xev.event)
.expect("Failed to focus input context"); .expect("Failed to focus input context");
let modifiers = ModifiersState::from_x11(&xev.mods);
self.device_mod_state.update_state(&modifiers, None);
if self.active_window != Some(xev.event) {
self.active_window = Some(xev.event);
let window_id = mkwid(xev.event);
callback(Event::WindowEvent { callback(Event::WindowEvent {
window_id, window_id,
event: Focused(true), event: Focused(true),
}); });
let modifiers = ModifiersState::from_x11(&xev.mods); if !modifiers.is_empty() {
callback(Event::WindowEvent {
update_modifiers!(modifiers, None); window_id,
event: WindowEvent::ModifiersChanged(modifiers),
});
}
// The deviceid for this event is for a keyboard instead of a pointer, // The deviceid for this event is for a keyboard instead of a pointer,
// so we have to do a little extra work. // so we have to do a little extra work.
@@ -912,7 +925,12 @@ impl<T: 'static> EventProcessor<T> {
}); });
// Issue key press events for all pressed keys // Issue key press events for all pressed keys
self.handle_pressed_keys(window_id, ElementState::Pressed, &mut callback); self.handle_pressed_keys(
window_id,
ElementState::Pressed,
&mut callback,
);
}
} }
ffi::XI_FocusOut => { ffi::XI_FocusOut => {
let xev: &ffi::XIFocusOutEvent = unsafe { &*(xev.data as *const _) }; let xev: &ffi::XIFocusOutEvent = unsafe { &*(xev.data as *const _) };
@@ -924,16 +942,27 @@ impl<T: 'static> EventProcessor<T> {
.unfocus(xev.event) .unfocus(xev.event)
.expect("Failed to unfocus input context"); .expect("Failed to unfocus input context");
if self.active_window.take() == Some(xev.event) {
let window_id = mkwid(xev.event); let window_id = mkwid(xev.event);
// Issue key release events for all pressed keys // Issue key release events for all pressed keys
self.handle_pressed_keys(window_id, ElementState::Released, &mut callback); self.handle_pressed_keys(
window_id,
ElementState::Released,
&mut callback,
);
callback(Event::WindowEvent {
window_id,
event: WindowEvent::ModifiersChanged(ModifiersState::empty()),
});
callback(Event::WindowEvent { callback(Event::WindowEvent {
window_id, window_id,
event: Focused(false), event: Focused(false),
}) })
} }
}
ffi::XI_TouchBegin | ffi::XI_TouchUpdate | ffi::XI_TouchEnd => { ffi::XI_TouchBegin | ffi::XI_TouchUpdate | ffi::XI_TouchEnd => {
let xev: &ffi::XIDeviceEvent = unsafe { &*(xev.data as *const _) }; let xev: &ffi::XIDeviceEvent = unsafe { &*(xev.data as *const _) };
@@ -1087,13 +1116,15 @@ impl<T: 'static> EventProcessor<T> {
let new_modifiers = self.device_mod_state.modifiers(); let new_modifiers = self.device_mod_state.modifiers();
if modifiers != new_modifiers { if modifiers != new_modifiers {
callback(Event::DeviceEvent { if let Some(window_id) = self.active_window {
device_id, callback(Event::WindowEvent {
event: DeviceEvent::ModifiersChanged(new_modifiers), window_id: mkwid(window_id),
event: WindowEvent::ModifiersChanged(new_modifiers),
}); });
} }
} }
} }
}
ffi::XI_HierarchyChanged => { ffi::XI_HierarchyChanged => {
let xev: &ffi::XIHierarchyEvent = unsafe { &*(xev.data as *const _) }; let xev: &ffi::XIHierarchyEvent = unsafe { &*(xev.data as *const _) };

View File

@@ -206,6 +206,7 @@ impl<T: 'static> EventLoop<T> {
device_mod_state: Default::default(), device_mod_state: Default::default(),
num_touch: 0, num_touch: 0,
first_touch: None, first_touch: None,
active_window: None,
}; };
// Register for device hotplug events // Register for device hotplug events