Skip to content
Open
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
15 changes: 8 additions & 7 deletions winit-appkit/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ use objc2::runtime::{Imp, Sel};
use objc2::sel;
use objc2_app_kit::{NSApplication, NSEvent, NSEventModifierFlags, NSEventType};
use objc2_foundation::MainThreadMarker;
use winit_core::event::{DeviceEvent, ElementState};
use winit_core::event::{ButtonSource, DeviceEvent, ElementState};

use super::app_state::AppState;
use super::view::mouse_button;

type SendEvent = extern "C-unwind" fn(&NSApplication, Sel, &NSEvent);

Expand Down Expand Up @@ -117,19 +118,19 @@ fn maybe_dispatch_device_event(app_state: &Rc<AppState>, event: &NSEvent) {
}
},
NSEventType::LeftMouseDown | NSEventType::RightMouseDown | NSEventType::OtherMouseDown => {
let button = event.buttonNumber() as u32;
let source = ButtonSource::Mouse(mouse_button(event));
app_state.maybe_queue_with_handler(move |app, event_loop| {
app.device_event(event_loop, None, DeviceEvent::Button {
button,
app.device_event(event_loop, None, DeviceEvent::PointerButton {
button: source,
state: ElementState::Pressed,
});
});
},
NSEventType::LeftMouseUp | NSEventType::RightMouseUp | NSEventType::OtherMouseUp => {
let button = event.buttonNumber() as u32;
let source = ButtonSource::Mouse(mouse_button(event));
app_state.maybe_queue_with_handler(move |app, event_loop| {
app.device_event(event_loop, None, DeviceEvent::Button {
button,
app.device_event(event_loop, None, DeviceEvent::PointerButton {
button: source,
state: ElementState::Released,
});
});
Expand Down
2 changes: 1 addition & 1 deletion winit-appkit/src/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,7 @@ impl WinitView {
}

/// Get the mouse button from the NSEvent.
fn mouse_button(event: &NSEvent) -> MouseButton {
pub fn mouse_button(event: &NSEvent) -> MouseButton {
// The buttonNumber property only makes sense for the mouse events:
// NSLeftMouse.../NSRightMouse.../NSOtherMouse...
// For the other events, it's always set to 0.
Expand Down
14 changes: 6 additions & 8 deletions winit-core/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -510,7 +510,8 @@ impl From<PointerSource> for PointerKind {
}
}

/// Represents the pointer type of a [`WindowEvent::PointerButton`].
/// Represents the pointer type of [`WindowEvent::PointerButton`] and
/// [`DeviceEvent::PointerButton`].
///
/// **Wayland/X11:** [`Unknown`](Self::Unknown) device types are converted to known variants by the
/// system.
Expand Down Expand Up @@ -615,7 +616,7 @@ impl FingerId {
/// Note that these events are delivered regardless of input focus.
///
/// [window events]: WindowEvent
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Debug, PartialEq)]
pub enum DeviceEvent {
/// Change in physical position of a pointing device.
///
Expand All @@ -640,8 +641,8 @@ pub enum DeviceEvent {
delta: MouseScrollDelta,
},

Button {
button: ButtonId,
PointerButton {
button: ButtonSource,
state: ElementState,
},

Expand Down Expand Up @@ -1047,9 +1048,6 @@ impl Force {
/// Identifier for a specific analog axis on some device.
pub type AxisId = u32;

/// Identifier for a specific button on some device.
pub type ButtonId = u32;

/// Tablet of the tablet tool.
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
Expand Down Expand Up @@ -1621,7 +1619,7 @@ mod tests {

with_device_event(PointerMotion { delta: (0.0, 0.0).into() });
with_device_event(MouseWheel { delta: event::MouseScrollDelta::LineDelta(0.0, 0.0) });
with_device_event(Button { button: 0, state: event::ElementState::Pressed });
with_device_event(PointerButton { button: event::ButtonSource::Unknown(0), state: event::ElementState::Pressed });
}};
}

Expand Down
64 changes: 55 additions & 9 deletions winit-web/src/event_loop/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use web_sys::{Document, KeyboardEvent, Navigator, PageTransitionEvent, PointerEv
use web_time::{Duration, Instant};
use winit_core::application::ApplicationHandler;
use winit_core::event::{
DeviceEvent, DeviceId, ElementState, RawKeyEvent, StartCause, WindowEvent,
ButtonSource, DeviceEvent, DeviceId, ElementState, PointerSource, RawKeyEvent, StartCause,
WindowEvent,
};
use winit_core::event_loop::{ControlFlow, DeviceEvents};
use winit_core::window::WindowId;
Expand Down Expand Up @@ -315,9 +316,10 @@ impl Shared {
return;
}

// chorded button event
let device_id = event::mkdid(event.pointer_id());
let pointer_id = event.pointer_id();
let device_id = event::mkdid(pointer_id);

// chorded button event
if let Some(button) = backend::event::raw_button(&event) {
let state = if backend::event::pointer_buttons(&event)
.contains(ButtonsState::from_bits_retain(button))
Expand All @@ -327,9 +329,23 @@ impl Shared {
ElementState::Released
};

let kind = backend::event::pointer_kind(&event, pointer_id);
let source = match backend::event::pointer_source(&event, kind) {
PointerSource::Mouse => backend::event::mouse_button(button),
PointerSource::Touch { finger_id, force } => {
ButtonSource::Touch { finger_id, force }
},
PointerSource::TabletTool { kind, data } => ButtonSource::TabletTool {
kind,
button: backend::event::tool_button(button),
data,
},
PointerSource::Unknown => ButtonSource::Unknown(button),
};

runner.send_event(Event::DeviceEvent {
device_id,
event: DeviceEvent::Button { button: button.into(), state },
event: DeviceEvent::PointerButton { button: source, state },
});

return;
Expand Down Expand Up @@ -376,11 +392,26 @@ impl Shared {
return;
}

let pointer_id = event.pointer_id();
let kind = backend::event::pointer_kind(&event, pointer_id);
let button = backend::event::raw_button(&event).expect("no pointer button pressed");
let source = match backend::event::pointer_source(&event, kind) {
PointerSource::Mouse => backend::event::mouse_button(button),
PointerSource::Touch { finger_id, force } => {
ButtonSource::Touch { finger_id, force }
},
PointerSource::TabletTool { kind, data } => ButtonSource::TabletTool {
kind,
button: backend::event::tool_button(button),
data,
},
PointerSource::Unknown => ButtonSource::Unknown(button),
};

runner.send_event(Event::DeviceEvent {
device_id: event::mkdid(event.pointer_id()),
event: DeviceEvent::Button {
button: button.into(),
device_id: event::mkdid(pointer_id),
event: DeviceEvent::PointerButton {
button: source,
state: ElementState::Pressed,
},
});
Expand All @@ -395,11 +426,26 @@ impl Shared {
return;
}

let pointer_id = event.pointer_id();
let kind = backend::event::pointer_kind(&event, pointer_id);
let button = backend::event::raw_button(&event).expect("no pointer button pressed");
let source = match backend::event::pointer_source(&event, kind) {
PointerSource::Mouse => backend::event::mouse_button(button),
PointerSource::Touch { finger_id, force } => {
ButtonSource::Touch { finger_id, force }
},
PointerSource::TabletTool { kind, data } => ButtonSource::TabletTool {
kind,
button: backend::event::tool_button(button),
data,
},
PointerSource::Unknown => ButtonSource::Unknown(button),
};

runner.send_event(Event::DeviceEvent {
device_id: event::mkdid(event.pointer_id()),
event: DeviceEvent::Button {
button: button.into(),
event: DeviceEvent::PointerButton {
button: source,
state: ElementState::Released,
},
});
Expand Down
15 changes: 8 additions & 7 deletions winit-win32/src/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@ use winit_core::application::ApplicationHandler;
use winit_core::cursor::{CustomCursor, CustomCursorSource};
use winit_core::error::{EventLoopError, NotSupportedError, RequestError};
use winit_core::event::{
DeviceEvent, DeviceId, FingerId, Force, Ime, RawKeyEvent, SurfaceSizeWriter, TabletToolButton,
TabletToolData, TabletToolKind, TabletToolTilt, TouchPhase, WindowEvent,
ButtonSource, DeviceEvent, DeviceId, FingerId, Force, Ime, RawKeyEvent, SurfaceSizeWriter,
TabletToolButton, TabletToolData, TabletToolKind, TabletToolTilt, TouchPhase, WindowEvent,
};
use winit_core::event_loop::pump_events::PumpStatus;
use winit_core::event_loop::{
Expand Down Expand Up @@ -2416,7 +2416,7 @@ unsafe extern "system" fn thread_event_target_callback(
}

unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: RAWINPUT) {
use winit_core::event::DeviceEvent::{Button, Key, MouseWheel, PointerMotion};
use winit_core::event::DeviceEvent::{Key, MouseWheel, PointerButton, PointerMotion};
use winit_core::event::ElementState::{Pressed, Released};
use winit_core::event::MouseScrollDelta::LineDelta;

Expand Down Expand Up @@ -2447,10 +2447,11 @@ unsafe fn handle_raw_input(userdata: &ThreadMsgTargetData, data: RAWINPUT) {
}

let button_state = raw_input::get_raw_mouse_button_state(button_flags as u32);
for (button, state) in button_state.iter().enumerate() {
if let Some(state) = *state {
userdata.send_device_event(device_id, Button { button: button as _, state });
}
for (mouse_button, state) in button_state.into_iter().flatten() {
userdata.send_device_event(device_id, PointerButton {
button: ButtonSource::Mouse(mouse_button),
state,
});
}
} else if data.header.dwType == RIM_TYPEKEYBOARD {
let keyboard = unsafe { data.data.keyboard };
Expand Down
34 changes: 21 additions & 13 deletions winit-win32/src/raw_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use windows_sys::Win32::UI::WindowsAndMessaging::{
RI_MOUSE_BUTTON_2_UP, RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP, RI_MOUSE_BUTTON_4_DOWN,
RI_MOUSE_BUTTON_4_UP, RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP,
};
use winit_core::event::ElementState;
use winit_core::event::{ElementState, MouseButton};
use winit_core::event_loop::DeviceEvents;
use winit_core::keyboard::{KeyCode, PhysicalKey};

Expand Down Expand Up @@ -180,28 +180,36 @@ pub fn get_raw_input_data(handle: HRAWINPUT) -> Option<RAWINPUT> {
Some(data)
}

fn button_flags_to_element_state(
fn button_flags_to_mouse_button_state(
button_flags: u32,
down_flag: u32,
up_flag: u32,
) -> Option<ElementState> {
mouse_button: MouseButton,
) -> Option<(MouseButton, ElementState)> {
let (down_flag, up_flag) = match mouse_button {
MouseButton::Left => (RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP),
MouseButton::Right => (RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP),
MouseButton::Middle => (RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP),
MouseButton::Back => (RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP),
MouseButton::Forward => (RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP),
_ => unreachable!("only 5 mouse buttons are supported by windows raw input"),
};

// We assume the same button won't be simultaneously pressed and released.
if util::has_flag(button_flags, down_flag) {
Some(ElementState::Pressed)
Some((mouse_button, ElementState::Pressed))
} else if util::has_flag(button_flags, up_flag) {
Some(ElementState::Released)
Some((mouse_button, ElementState::Released))
} else {
None
}
}

pub fn get_raw_mouse_button_state(button_flags: u32) -> [Option<ElementState>; 5] {
pub fn get_raw_mouse_button_state(button_flags: u32) -> [Option<(MouseButton, ElementState)>; 5] {
[
button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP),
button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP),
button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP),
button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP),
button_flags_to_element_state(button_flags, RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP),
button_flags_to_mouse_button_state(button_flags, MouseButton::Left),
button_flags_to_mouse_button_state(button_flags, MouseButton::Right),
button_flags_to_mouse_button_state(button_flags, MouseButton::Middle),
button_flags_to_mouse_button_state(button_flags, MouseButton::Back),
button_flags_to_mouse_button_state(button_flags, MouseButton::Forward),
]
}

Expand Down
18 changes: 17 additions & 1 deletion winit-x11/src/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,23 @@ impl EventProcessor {
self.target.xconn.set_timestamp(xev.time as xproto::Timestamp);

if xev.flags & xinput2::XIPointerEmulated == 0 {
let event = DeviceEvent::Button { state, button: xev.detail as u32 };
let button = xev.detail as u32;
let source = match button {
xlib::Button1 => ButtonSource::Mouse(MouseButton::Left),
xlib::Button2 => ButtonSource::Mouse(MouseButton::Middle),
xlib::Button3 => ButtonSource::Mouse(MouseButton::Right),

// Scroll inputs
4..=7 => return,

8 => ButtonSource::Mouse(MouseButton::Back),
9 => ButtonSource::Mouse(MouseButton::Forward),
_ => match MouseButton::try_from_u8(button as u8) {
Some(mouse_button) => ButtonSource::Mouse(mouse_button),
None => return,
},
};
let event = DeviceEvent::PointerButton { button: source, state };
app.device_event(&self.target, Some(mkdid(xev.deviceid as xinput::DeviceId)), event);
}
}
Expand Down
4 changes: 3 additions & 1 deletion winit/src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ changelog entry.
type to a generic mouse button.
- New `FingerId` added to `PointerKind::Touch` and `PointerSource::Touch` able to uniquely
identify a finger in a multi-touch interaction. Replaces the old `Touch::id`.
- In the same spirit rename `DeviceEvent::MouseMotion` to `PointerMotion`.
- In the same spirit rename `DeviceEvent::MouseMotion` and `DeviceEvent::Button` to
`PointerMotion` and `PointerButton` respectively.
- Change `DeviceEvent::PointerButton` to use `ButtonSource`.
- Remove `Force::Calibrated::altitude_angle`.
- On X11, use bottom-right corner for IME hotspot in `Window::set_ime_cursor_area`.
- On macOS and iOS, no longer emit `ScaleFactorChanged` upon window creation.
Expand Down