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

Wayland: add missing mouse input events #391

Merged
merged 4 commits into from
Jul 19, 2023
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
171 changes: 167 additions & 4 deletions src/native/linux_wayland.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ use libwayland_egl::*;
use libxkbcommon::*;

use crate::{
event::{EventHandler, KeyCode, KeyMods},
event::{EventHandler, KeyCode, KeyMods, MouseButton},
native::{egl, NativeDisplayData},
};

use std::collections::HashSet;

fn wl_fixed_to_double(f: i32) -> f32 {
(f as f32) / 256.0
}

pub struct WaylandDisplay {
client: LibWaylandClient,
// this is libwayland-egl.so, a library with ~4 functions
Expand Down Expand Up @@ -173,6 +177,19 @@ unsafe extern "C" fn seat_handle_capabilities(
) {
let display: &mut WaylandDisplay = &mut *(data as *mut _);

if caps & wl_seat_capability_WL_SEAT_CAPABILITY_POINTER != 0 {
// struct wl_pointer *pointer = wl_seat_get_pointer (seat);
let id: *mut wl_proxy = wl_request_constructor!(
display.client,
seat,
WL_SEAT_GET_POINTER,
display.client.wl_pointer_interface
);
assert!(!id.is_null());
// wl_pointer_add_listener (pointer, &pointer_listener, NULL);
(display.client.wl_proxy_add_listener)(id, &POINTER_LISTENER as *const _ as _, data);
}

if caps & wl_seat_capability_WL_SEAT_CAPABILITY_KEYBOARD != 0 {
// struct wl_keyboard *keyboard = wl_seat_get_keyboard(seat);
let id: *mut wl_proxy = wl_request_constructor!(
Expand All @@ -189,6 +206,9 @@ unsafe extern "C" fn seat_handle_capabilities(

enum WaylandEvent {
KeyboardKey(KeyCode, bool),
PointerMotion(f32, f32),
PointerButton(MouseButton, bool),
PointerAxis(f32, f32),
}

static mut EVENTS: Vec<WaylandEvent> = Vec::new();
Expand Down Expand Up @@ -249,8 +269,8 @@ unsafe extern "C" fn keyboard_handle_leave(
unsafe extern "C" fn keyboard_handle_key(
data: *mut ::std::os::raw::c_void,
_wl_keyboard: *mut wl_keyboard,
serial: u32,
time: u32,
_serial: u32,
_time: u32,
key: u32,
state: u32,
) {
Expand Down Expand Up @@ -289,6 +309,126 @@ unsafe extern "C" fn keyboard_handle_repeat_info(
) {
}

static mut POINTER_LISTENER: wl_pointer_listener = wl_pointer_listener {
enter: Some(pointer_handle_enter),
leave: Some(pointer_handle_leave),
motion: Some(pointer_handle_motion),
button: Some(pointer_handle_button),
axis: Some(pointer_handle_axis),
frame: Some(pointer_handle_frame),
axis_source: Some(pointer_handle_axis_source),
axis_stop: Some(pointer_handle_axis_stop),
axis_discrete: Some(pointer_handle_axis_discrete),
axis_value120: Some(pointer_handle_axis_value120),
axis_relative_direction: Some(pointer_handle_axis_relative_direction),
};

unsafe extern "C" fn pointer_handle_enter(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
_serial: u32,
_surface: *mut wl_surface,
_surface_x: i32,
_surface_y: i32,
) {
}
unsafe extern "C" fn pointer_handle_leave(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
_serial: u32,
_surface: *mut wl_surface,
) {
}
unsafe extern "C" fn pointer_handle_motion(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
_time: u32,
surface_x: i32,
surface_y: i32,
) {
// From wl_fixed_to_double(), it simply divides by 256
let (x, y) = (wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
EVENTS.push(WaylandEvent::PointerMotion(x, y));
}
unsafe extern "C" fn pointer_handle_button(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
_serial: u32,
_time: u32,
button: u32,
state: u32,
) {
// The code is defined in the kernel's linux/input-event-codes.h header file, e.g. BTN_LEFT
let button = match button {
272 => MouseButton::Left,
273 => MouseButton::Right,
274 => MouseButton::Middle,
_ => MouseButton::Unknown,
};
EVENTS.push(WaylandEvent::PointerButton(button, state == 1));
}
unsafe extern "C" fn pointer_handle_axis(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
_time: u32,
axis: u32,
value: i32,
) {
let mut value = wl_fixed_to_double(value);
// Normalize the value to {-1, 0, 1}
value /= value.abs();

// https://wayland-book.com/seat/pointer.html
if axis == 0 {
// Vertical scroll
// Wayland defines the direction differently to miniquad so lets flip it
value = -value;
EVENTS.push(WaylandEvent::PointerAxis(0.0, value));
} else if axis == 1 {
// Horizontal scroll
EVENTS.push(WaylandEvent::PointerAxis(value, 0.0));
}
}
unsafe extern "C" fn pointer_handle_frame(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
) {
}
unsafe extern "C" fn pointer_handle_axis_source(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
_axis_source: u32,
) {
}
unsafe extern "C" fn pointer_handle_axis_stop(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
_time: u32,
_axis: u32,
) {
}
unsafe extern "C" fn pointer_handle_axis_discrete(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
_axis: u32,
_discrete: i32,
) {
}
unsafe extern "C" fn pointer_handle_axis_value120(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
_axis: u32,
_value120: i32,
) {
}
unsafe extern "C" fn pointer_handle_axis_relative_direction(
_data: *mut ::std::os::raw::c_void,
_wl_pointer: *mut wl_pointer,
_axis: u32,
_direction: u32,
) {
}

extern "C" fn seat_handle_name(
_data: *mut std::ffi::c_void,
_seat: *mut wl_seat,
Expand Down Expand Up @@ -648,6 +788,7 @@ where
logo: false,
};
let mut repeated_keys: HashSet<KeyCode> = HashSet::new();
let (mut last_mouse_x, mut last_mouse_y) = (0.0, 0.0);

while tl_display::with(|d| d.closed == false) {
(client.wl_display_dispatch_pending)(wdisplay);
Expand All @@ -662,7 +803,9 @@ where
WaylandEvent::KeyboardKey(keycode, state) => {
match keycode {
KeyCode::LeftShift | KeyCode::RightShift => keymods.shift = state,
KeyCode::LeftControl | KeyCode::RightControl => keymods.ctrl = state,
KeyCode::LeftControl | KeyCode::RightControl => {
keymods.ctrl = state
}
KeyCode::LeftAlt | KeyCode::RightAlt => keymods.alt = state,
KeyCode::LeftSuper | KeyCode::RightSuper => keymods.logo = state,
_ => {}
Expand All @@ -676,6 +819,26 @@ where
repeated_keys.remove(&keycode);
}
}
WaylandEvent::PointerMotion(x, y) => {
event_handler.mouse_motion_event(x, y);
(last_mouse_x, last_mouse_y) = (x, y);
}
WaylandEvent::PointerButton(button, state) => {
if state {
event_handler.mouse_button_down_event(
button,
last_mouse_x,
last_mouse_y,
);
} else {
event_handler.mouse_button_up_event(
button,
last_mouse_x,
last_mouse_y,
);
}
}
WaylandEvent::PointerAxis(x, y) => event_handler.mouse_wheel_event(x, y),
}
}

Expand Down
95 changes: 95 additions & 0 deletions src/native/linux_wayland/libwayland_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,99 @@ pub struct wl_keyboard_listener {
>,
}

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct wl_pointer_listener {
pub enter: ::std::option::Option<
unsafe extern "C" fn(
data: *mut ::std::os::raw::c_void,
wl_pointer: *mut wl_pointer,
serial: u32,
surface: *mut wl_surface,
surface_x: i32,
surface_y: i32,
),
>,
pub leave: ::std::option::Option<
unsafe extern "C" fn(
data: *mut ::std::os::raw::c_void,
wl_pointer: *mut wl_pointer,
serial: u32,
surface: *mut wl_surface,
),
>,
pub motion: ::std::option::Option<
unsafe extern "C" fn(
data: *mut ::std::os::raw::c_void,
wl_pointer: *mut wl_pointer,
time: u32,
surface_x: i32,
surface_y: i32,
),
>,
pub button: ::std::option::Option<
unsafe extern "C" fn(
data: *mut ::std::os::raw::c_void,
wl_pointer: *mut wl_pointer,
serial: u32,
time: u32,
button: u32,
state: u32,
),
>,
pub axis: ::std::option::Option<
unsafe extern "C" fn(
data: *mut ::std::os::raw::c_void,
wl_pointer: *mut wl_pointer,
time: u32,
axis: u32,
value: i32,
),
>,
pub frame: ::std::option::Option<
unsafe extern "C" fn(data: *mut ::std::os::raw::c_void, wl_pointer: *mut wl_pointer),
>,
pub axis_source: ::std::option::Option<
unsafe extern "C" fn(
data: *mut ::std::os::raw::c_void,
wl_pointer: *mut wl_pointer,
axis_source: u32,
),
>,
pub axis_stop: ::std::option::Option<
unsafe extern "C" fn(
data: *mut ::std::os::raw::c_void,
wl_pointer: *mut wl_pointer,
time: u32,
axis: u32,
),
>,
pub axis_discrete: ::std::option::Option<
unsafe extern "C" fn(
data: *mut ::std::os::raw::c_void,
wl_pointer: *mut wl_pointer,
axis: u32,
discrete: i32,
),
>,
pub axis_value120: ::std::option::Option<
unsafe extern "C" fn(
data: *mut ::std::os::raw::c_void,
wl_pointer: *mut wl_pointer,
axis: u32,
value120: i32,
),
>,
pub axis_relative_direction: ::std::option::Option<
unsafe extern "C" fn(
data: *mut ::std::os::raw::c_void,
wl_pointer: *mut wl_pointer,
axis: u32,
direction: u32,
),
>,
}

pub type wl_display_connect =
unsafe extern "C" fn(name: *const ::std::os::raw::c_char) -> *mut wl_display;
pub type wl_proxy_destroy = unsafe extern "C" fn(proxy: *mut wl_proxy);
Expand Down Expand Up @@ -521,6 +614,7 @@ pub struct LibWaylandClient {
pub wl_shm_interface: *mut wl_interface,
pub wl_shm_pool_interface: *mut wl_interface,
pub wl_keyboard_interface: *mut wl_interface,
pub wl_pointer_interface: *mut wl_interface,
}

impl LibWaylandClient {
Expand Down Expand Up @@ -556,6 +650,7 @@ impl LibWaylandClient {
wl_shm_interface: module.get_symbol("wl_shm_interface").unwrap(),
wl_shm_pool_interface: module.get_symbol("wl_shm_pool_interface").unwrap(),
wl_keyboard_interface: module.get_symbol("wl_keyboard_interface").unwrap(),
wl_pointer_interface: module.get_symbol("wl_pointer_interface").unwrap(),

_module: std::rc::Rc::new(module),
})
Expand Down
1 change: 0 additions & 1 deletion src/native/linux_wayland/libxkbcommon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,3 @@ impl LibXkbCommon {
.ok()
}
}

Loading