Merge pull request #365 from i509VCB/mouse-f/b
This commit is contained in:
commit
b890bfd768
|
@ -10,6 +10,9 @@
|
|||
- `XdgPositionerState` moved to `XdgPopupState` and added to `XdgRequest::NewPopup`
|
||||
- `PopupSurface::send_configure` now checks the protocol version and returns an `Result`
|
||||
- `KeyboardHandle::input` filter closure now receives a `KeysymHandle` instead of a `Keysym` and returns a `FilterResult`.
|
||||
- `PointerButtonEvent::button` now returns an `Option<MouseButton>`.
|
||||
- `MouseButton` is now non-exhaustive.
|
||||
- Remove `Other` and add `Forward` and `Back` variants to `MouseButton`. Use the new `PointerButtonEvent::button_code` in place of `Other`.
|
||||
|
||||
#### Backends
|
||||
|
||||
|
@ -40,6 +43,7 @@
|
|||
- `x11rb` event source integration used in anvil's XWayland implementation is now part of smithay at `utils::x11rb`. Enabled through the `x11rb_event_source` feature.
|
||||
- `KeyState`, `MouseButton`, `ButtonState` and `Axis` in `backend::input` now derive `Hash`.
|
||||
- New `DrmNode` type in drm backend. This is primarily for use a backend which needs to run as client inside another session.
|
||||
- The button code for a `PointerButtonEvent` may now be obtained using `PointerButtonEvent::button_code`.
|
||||
|
||||
### Bugfixes
|
||||
|
||||
|
|
|
@ -86,12 +86,7 @@ impl<Backend> AnvilState<Backend> {
|
|||
|
||||
fn on_pointer_button<B: InputBackend>(&mut self, evt: B::PointerButtonEvent) {
|
||||
let serial = SCOUNTER.next_serial();
|
||||
let button = match evt.button() {
|
||||
input::MouseButton::Left => 0x110,
|
||||
input::MouseButton::Right => 0x111,
|
||||
input::MouseButton::Middle => 0x112,
|
||||
input::MouseButton::Other(b) => b as u32,
|
||||
};
|
||||
let button = evt.button_code();
|
||||
let state = match evt.state() {
|
||||
input::ButtonState::Pressed => {
|
||||
// change the keyboard focus unless the pointer is grabbed
|
||||
|
|
|
@ -87,10 +87,17 @@ pub enum KeyState {
|
|||
|
||||
/// Trait for keyboard event
|
||||
pub trait KeyboardKeyEvent<B: InputBackend>: Event<B> {
|
||||
/// Code of the pressed key. See `linux/input-event-codes.h`
|
||||
/// Returns the numerical button code of the keyboard button.
|
||||
///
|
||||
/// The value will correspond to one `KEY_` constants from the Linux [input event codes] inside
|
||||
/// `input-event-codes.h`.
|
||||
///
|
||||
/// [input event codes]: https://gitlab.freedesktop.org/libinput/libinput/-/blob/main/include/linux/linux/input-event-codes.h
|
||||
fn key_code(&self) -> u32;
|
||||
|
||||
/// State of the key
|
||||
fn state(&self) -> KeyState;
|
||||
|
||||
/// Total number of keys pressed on all devices on the associated [`Seat`](crate::wayland::seat::Seat)
|
||||
fn count(&self) -> u32;
|
||||
}
|
||||
|
@ -110,6 +117,7 @@ impl<B: InputBackend> KeyboardKeyEvent<B> for UnusedEvent {
|
|||
}
|
||||
|
||||
/// A particular mouse button
|
||||
#[non_exhaustive]
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||
pub enum MouseButton {
|
||||
/// Left mouse button
|
||||
|
@ -118,8 +126,10 @@ pub enum MouseButton {
|
|||
Middle,
|
||||
/// Right mouse button
|
||||
Right,
|
||||
/// Other mouse button with index
|
||||
Other(u8),
|
||||
/// Forward mouse button.
|
||||
Forward,
|
||||
/// Back mouse button.
|
||||
Back,
|
||||
}
|
||||
|
||||
/// State of a button on a pointer device, like mouse or tablet tool. Either pressed or released
|
||||
|
@ -133,14 +143,35 @@ pub enum ButtonState {
|
|||
|
||||
/// Common methods pointer event generated by pressed buttons do implement
|
||||
pub trait PointerButtonEvent<B: InputBackend>: Event<B> {
|
||||
/// Pressed button of the event
|
||||
fn button(&self) -> MouseButton;
|
||||
/// Pressed button of the event.
|
||||
///
|
||||
/// This may return [`None`] if the button pressed in the event is not a standard mouse button. You may
|
||||
/// obtain the button code using [`PointerButtonEvent::button_code`].
|
||||
fn button(&self) -> Option<MouseButton> {
|
||||
match self.button_code() {
|
||||
0x110 => Some(MouseButton::Left),
|
||||
0x111 => Some(MouseButton::Right),
|
||||
0x112 => Some(MouseButton::Middle),
|
||||
0x115 => Some(MouseButton::Forward),
|
||||
0x116 => Some(MouseButton::Back),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the numerical button code of the mouse button.
|
||||
///
|
||||
/// The value will correspond to one `BTN_` constants from the Linux [input event codes] inside
|
||||
/// `input-event-codes.h`.
|
||||
///
|
||||
/// [input event codes]: https://gitlab.freedesktop.org/libinput/libinput/-/blob/main/include/linux/linux/input-event-codes.h
|
||||
fn button_code(&self) -> u32;
|
||||
|
||||
/// State of the button
|
||||
fn state(&self) -> ButtonState;
|
||||
}
|
||||
|
||||
impl<B: InputBackend> PointerButtonEvent<B> for UnusedEvent {
|
||||
fn button(&self) -> MouseButton {
|
||||
fn button_code(&self) -> u32 {
|
||||
match *self {}
|
||||
}
|
||||
|
||||
|
@ -613,3 +644,17 @@ pub enum InputEvent<B: InputBackend> {
|
|||
/// Special event specific of this backend
|
||||
Special(B::SpecialEvent),
|
||||
}
|
||||
|
||||
/// Converts an xorg mouse button to the format used by libinput.
|
||||
///
|
||||
/// Taken from https://sources.debian.org/src/xserver-xorg-input-libinput/1.1.0-1/src/xf86libinput.c/?hl=1508#L236-L252
|
||||
#[cfg(any(feature = "backend_winit", feature = "backend_x11"))]
|
||||
pub(crate) fn xorg_mouse_to_libinput(xorg: u32) -> u32 {
|
||||
match xorg {
|
||||
0 => 0,
|
||||
1 => 0x110, // BTN_LEFT
|
||||
2 => 0x112, // BTN_MIDDLE
|
||||
3 => 0x111, // BTN_RIGHT
|
||||
_ => xorg - 8 + 0x113, // BTN_SIZE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -188,13 +188,8 @@ impl backend::Event<LibinputInputBackend> for event::pointer::PointerButtonEvent
|
|||
}
|
||||
|
||||
impl backend::PointerButtonEvent<LibinputInputBackend> for event::pointer::PointerButtonEvent {
|
||||
fn button(&self) -> backend::MouseButton {
|
||||
match self.button() {
|
||||
0x110 => backend::MouseButton::Left,
|
||||
0x111 => backend::MouseButton::Right,
|
||||
0x112 => backend::MouseButton::Middle,
|
||||
x => backend::MouseButton::Other(x as u8),
|
||||
}
|
||||
fn button_code(&self) -> u32 {
|
||||
self.button()
|
||||
}
|
||||
|
||||
fn state(&self) -> backend::ButtonState {
|
||||
|
|
|
@ -6,9 +6,9 @@ use winit::{
|
|||
};
|
||||
|
||||
use crate::backend::input::{
|
||||
Axis, AxisSource, ButtonState, Device, DeviceCapability, Event, InputBackend, InputEvent, KeyState,
|
||||
KeyboardKeyEvent, MouseButton, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent,
|
||||
TouchCancelEvent, TouchDownEvent, TouchMotionEvent, TouchSlot, TouchUpEvent, UnusedEvent,
|
||||
self, Axis, AxisSource, ButtonState, Device, DeviceCapability, Event, InputBackend, InputEvent, KeyState,
|
||||
KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, TouchCancelEvent,
|
||||
TouchDownEvent, TouchMotionEvent, TouchSlot, TouchUpEvent, UnusedEvent,
|
||||
};
|
||||
|
||||
use super::{WindowSize, WinitError};
|
||||
|
@ -170,6 +170,7 @@ pub struct WinitMouseInputEvent {
|
|||
pub(crate) time: u32,
|
||||
pub(crate) button: WinitMouseButton,
|
||||
pub(crate) state: ElementState,
|
||||
pub(crate) is_x11: bool,
|
||||
}
|
||||
|
||||
impl Event<WinitInput> for WinitMouseInputEvent {
|
||||
|
@ -183,8 +184,19 @@ impl Event<WinitInput> for WinitMouseInputEvent {
|
|||
}
|
||||
|
||||
impl PointerButtonEvent<WinitInput> for WinitMouseInputEvent {
|
||||
fn button(&self) -> MouseButton {
|
||||
self.button.into()
|
||||
fn button_code(&self) -> u32 {
|
||||
match self.button {
|
||||
WinitMouseButton::Left => 0x110,
|
||||
WinitMouseButton::Right => 0x111,
|
||||
WinitMouseButton::Middle => 0x112,
|
||||
WinitMouseButton::Other(b) => {
|
||||
if self.is_x11 {
|
||||
input::xorg_mouse_to_libinput(b as u32)
|
||||
} else {
|
||||
b as u32
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn state(&self) -> ButtonState {
|
||||
|
@ -332,17 +344,6 @@ impl TouchCancelEvent<WinitInput> for WinitTouchCancelledEvent {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<WinitMouseButton> for MouseButton {
|
||||
fn from(button: WinitMouseButton) -> MouseButton {
|
||||
match button {
|
||||
WinitMouseButton::Left => MouseButton::Left,
|
||||
WinitMouseButton::Right => MouseButton::Right,
|
||||
WinitMouseButton::Middle => MouseButton::Middle,
|
||||
WinitMouseButton::Other(num) => MouseButton::Other(num as u8),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ElementState> for KeyState {
|
||||
fn from(state: ElementState) -> Self {
|
||||
match state {
|
||||
|
|
|
@ -106,6 +106,8 @@ pub struct WinitEventLoop {
|
|||
initialized: bool,
|
||||
size: Rc<RefCell<WindowSize>>,
|
||||
resize_notification: Rc<Cell<Option<Size<i32, Physical>>>>,
|
||||
/// Whether winit is using Wayland or X11 as it's backend.
|
||||
is_x11: bool,
|
||||
}
|
||||
|
||||
/// Create a new [`WinitGraphicsBackend`], which implements the [`Renderer`] trait and a corresponding
|
||||
|
@ -164,41 +166,47 @@ where
|
|||
debug!(log, "Window created");
|
||||
|
||||
let reqs = Default::default();
|
||||
let (display, context, surface) = {
|
||||
let (display, context, surface, is_x11) = {
|
||||
let display = EGLDisplay::new(&winit_window, log.clone())?;
|
||||
let context = EGLContext::new_with_config(&display, attributes, reqs, log.clone())?;
|
||||
|
||||
let surface = if let Some(wl_surface) = winit_window.wayland_surface() {
|
||||
let (surface, is_x11) = if let Some(wl_surface) = winit_window.wayland_surface() {
|
||||
debug!(log, "Winit backend: Wayland");
|
||||
let size = winit_window.inner_size();
|
||||
let surface = unsafe {
|
||||
wegl::WlEglSurface::new_from_raw(wl_surface as *mut _, size.width as i32, size.height as i32)
|
||||
};
|
||||
EGLSurface::new(
|
||||
&display,
|
||||
context.pixel_format().unwrap(),
|
||||
context.config_id(),
|
||||
surface,
|
||||
log.clone(),
|
||||
(
|
||||
EGLSurface::new(
|
||||
&display,
|
||||
context.pixel_format().unwrap(),
|
||||
context.config_id(),
|
||||
surface,
|
||||
log.clone(),
|
||||
)
|
||||
.map_err(EGLError::CreationFailed)?,
|
||||
false,
|
||||
)
|
||||
.map_err(EGLError::CreationFailed)?
|
||||
} else if let Some(xlib_window) = winit_window.xlib_window().map(native::XlibWindow) {
|
||||
debug!(log, "Winit backend: X11");
|
||||
EGLSurface::new(
|
||||
&display,
|
||||
context.pixel_format().unwrap(),
|
||||
context.config_id(),
|
||||
xlib_window,
|
||||
log.clone(),
|
||||
(
|
||||
EGLSurface::new(
|
||||
&display,
|
||||
context.pixel_format().unwrap(),
|
||||
context.config_id(),
|
||||
xlib_window,
|
||||
log.clone(),
|
||||
)
|
||||
.map_err(EGLError::CreationFailed)?,
|
||||
true,
|
||||
)
|
||||
.map_err(EGLError::CreationFailed)?
|
||||
} else {
|
||||
unreachable!("No backends for winit other then Wayland and X11 are supported")
|
||||
};
|
||||
|
||||
let _ = context.unbind();
|
||||
|
||||
(display, context, surface)
|
||||
(display, context, surface, is_x11)
|
||||
};
|
||||
|
||||
let (w, h): (u32, u32) = winit_window.inner_size().into();
|
||||
|
@ -230,6 +238,7 @@ where
|
|||
initialized: false,
|
||||
logger: log.new(o!("smithay_winit_component" => "event_loop")),
|
||||
size,
|
||||
is_x11,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
@ -338,6 +347,7 @@ impl WinitEventLoop {
|
|||
let resize_notification = &self.resize_notification;
|
||||
let logger = &self.logger;
|
||||
let window_size = &self.size;
|
||||
let is_x11 = self.is_x11;
|
||||
|
||||
if !self.initialized {
|
||||
callback(Input(InputEvent::DeviceAdded {
|
||||
|
@ -428,7 +438,12 @@ impl WinitEventLoop {
|
|||
}
|
||||
WindowEvent::MouseInput { state, button, .. } => {
|
||||
callback(Input(InputEvent::PointerButton {
|
||||
event: WinitMouseInputEvent { time, button, state },
|
||||
event: WinitMouseInputEvent {
|
||||
time,
|
||||
button,
|
||||
state,
|
||||
is_x11,
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,7 @@ use super::X11Error;
|
|||
use crate::{
|
||||
backend::input::{
|
||||
self, Axis, AxisSource, ButtonState, Device, DeviceCapability, InputBackend, InputEvent, KeyState,
|
||||
KeyboardKeyEvent, MouseButton, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent,
|
||||
UnusedEvent,
|
||||
KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionAbsoluteEvent, UnusedEvent,
|
||||
},
|
||||
utils::{Logical, Size},
|
||||
};
|
||||
|
@ -120,7 +119,7 @@ impl PointerAxisEvent<X11Input> for X11MouseWheelEvent {
|
|||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct X11MouseInputEvent {
|
||||
pub(crate) time: u32,
|
||||
pub(crate) button: MouseButton,
|
||||
pub(crate) raw: u32,
|
||||
pub(crate) state: ButtonState,
|
||||
}
|
||||
|
||||
|
@ -135,8 +134,8 @@ impl input::Event<X11Input> for X11MouseInputEvent {
|
|||
}
|
||||
|
||||
impl PointerButtonEvent<X11Input> for X11MouseInputEvent {
|
||||
fn button(&self) -> MouseButton {
|
||||
self.button
|
||||
fn button_code(&self) -> u32 {
|
||||
input::xorg_mouse_to_libinput(self.raw)
|
||||
}
|
||||
|
||||
fn state(&self) -> ButtonState {
|
||||
|
|
|
@ -59,7 +59,7 @@ use crate::{
|
|||
backend::{
|
||||
allocator::dmabuf::{AsDmabuf, Dmabuf},
|
||||
drm::{DrmNode, NodeType},
|
||||
input::{Axis, ButtonState, InputEvent, KeyState, MouseButton},
|
||||
input::{Axis, ButtonState, InputEvent, KeyState},
|
||||
},
|
||||
utils::{x11rb::X11Source, Logical, Size},
|
||||
};
|
||||
|
@ -625,115 +625,69 @@ impl EventSource for X11Backend {
|
|||
// 6 => Axis::Horizontal -1.0
|
||||
// 7 => Axis::Horizontal +1.0
|
||||
// Others => ??
|
||||
match button_press.detail {
|
||||
1..=3 => {
|
||||
// Clicking a button.
|
||||
callback(
|
||||
Input(InputEvent::PointerButton {
|
||||
event: X11MouseInputEvent {
|
||||
time: button_press.time,
|
||||
button: match button_press.detail {
|
||||
1 => MouseButton::Left,
|
||||
|
||||
// Confusion: XCB docs for ButtonIndex and what plasma does don't match?
|
||||
2 => MouseButton::Middle,
|
||||
// Scrolling
|
||||
if button_press.detail >= 4 && button_press.detail <= 7 {
|
||||
callback(
|
||||
Input(InputEvent::PointerAxis {
|
||||
event: X11MouseWheelEvent {
|
||||
time: button_press.time,
|
||||
axis: match button_press.detail {
|
||||
// Up | Down
|
||||
4 | 5 => Axis::Vertical,
|
||||
|
||||
3 => MouseButton::Right,
|
||||
// Right | Left
|
||||
6 | 7 => Axis::Horizontal,
|
||||
|
||||
_ => unreachable!(),
|
||||
},
|
||||
state: ButtonState::Pressed,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
}),
|
||||
&mut event_window,
|
||||
)
|
||||
}
|
||||
amount: match button_press.detail {
|
||||
// Up | Right
|
||||
4 | 7 => 1.0,
|
||||
|
||||
4..=7 => {
|
||||
// Scrolling
|
||||
callback(
|
||||
Input(InputEvent::PointerAxis {
|
||||
event: X11MouseWheelEvent {
|
||||
time: button_press.time,
|
||||
axis: match button_press.detail {
|
||||
// Up | Down
|
||||
4 | 5 => Axis::Vertical,
|
||||
// Down | Left
|
||||
5 | 6 => -1.0,
|
||||
|
||||
// Right | Left
|
||||
6 | 7 => Axis::Horizontal,
|
||||
|
||||
_ => unreachable!(),
|
||||
},
|
||||
amount: match button_press.detail {
|
||||
// Up | Right
|
||||
4 | 7 => 1.0,
|
||||
|
||||
// Down | Left
|
||||
5 | 6 => -1.0,
|
||||
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => unreachable!(),
|
||||
},
|
||||
}),
|
||||
&mut event_window,
|
||||
)
|
||||
}
|
||||
|
||||
// Unknown mouse button
|
||||
_ => callback(
|
||||
},
|
||||
}),
|
||||
&mut event_window,
|
||||
)
|
||||
} else {
|
||||
callback(
|
||||
Input(InputEvent::PointerButton {
|
||||
event: X11MouseInputEvent {
|
||||
time: button_press.time,
|
||||
button: MouseButton::Other(button_press.detail),
|
||||
raw: button_press.detail as u32,
|
||||
state: ButtonState::Pressed,
|
||||
},
|
||||
}),
|
||||
&mut event_window,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x11::Event::ButtonRelease(button_release) => {
|
||||
if button_release.event == window.id {
|
||||
match button_release.detail {
|
||||
1..=3 => {
|
||||
// Releasing a button.
|
||||
callback(
|
||||
Input(InputEvent::PointerButton {
|
||||
event: X11MouseInputEvent {
|
||||
time: button_release.time,
|
||||
button: match button_release.detail {
|
||||
1 => MouseButton::Left,
|
||||
|
||||
2 => MouseButton::Middle,
|
||||
|
||||
3 => MouseButton::Right,
|
||||
|
||||
_ => unreachable!(),
|
||||
},
|
||||
state: ButtonState::Released,
|
||||
},
|
||||
}),
|
||||
&mut event_window,
|
||||
)
|
||||
}
|
||||
|
||||
// We may ignore the release tick for scrolling, as the X server will
|
||||
// always emit this immediately after press.
|
||||
4..=7 => (),
|
||||
|
||||
_ => callback(
|
||||
Input(InputEvent::PointerButton {
|
||||
event: X11MouseInputEvent {
|
||||
time: button_release.time,
|
||||
button: MouseButton::Other(button_release.detail),
|
||||
state: ButtonState::Released,
|
||||
},
|
||||
}),
|
||||
&mut event_window,
|
||||
),
|
||||
// Ignore release tick because this event is always sent immediately after the press
|
||||
// tick for scrolling and the backend will dispatch release event automatically during
|
||||
// the press event.
|
||||
if button_release.detail >= 4 && button_release.detail <= 7 {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(
|
||||
Input(InputEvent::PointerButton {
|
||||
event: X11MouseInputEvent {
|
||||
time: button_release.time,
|
||||
raw: button_release.detail as u32,
|
||||
state: ButtonState::Released,
|
||||
},
|
||||
}),
|
||||
&mut event_window,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue