From b908e6d4fdb38f0892f894ae347a6cfa5da331a3 Mon Sep 17 00:00:00 2001 From: bolphen <[email protected]> Date: Tue, 11 Mar 2025 10:38:52 +0000 Subject: [PATCH 1/3] native/linux_wayland: Add error handling --- src/native/linux_wayland.rs | 27 +++++++++++++++++++ src/native/linux_wayland/libwayland_client.rs | 7 +++++ 2 files changed, 34 insertions(+) diff --git a/src/native/linux_wayland.rs b/src/native/linux_wayland.rs index 79293865..65950f94 100644 --- a/src/native/linux_wayland.rs +++ b/src/native/linux_wayland.rs @@ -120,6 +120,33 @@ impl WaylandPayload { } else { (self.client.wl_display_cancel_read)(self.display); } + let errno = (self.client.wl_display_get_error)(self.display); + // A non-zero errno means the compositor decided that we need to die. + // Nothing more we can do at this point :( + // If we want the detailed error message, we need to run with `WAYLAND_DEBUG=client`, since + // the message string is not accessible to us. + match errno { + 0 => (), + EPROTO => { + let mut interface: *const wl_interface = std::ptr::null(); + let mut id = 0; + let code = (self.client.wl_display_get_protocol_error)( + self.display, + &mut interface, + &mut id, + ); + let name = core::ffi::CStr::from_ptr((*interface).name) + .to_str() + .unwrap(); + panic!( + "Wayland protocol error at {}#{} with code {}", + name, id, code + ) + } + _ => { + panic!("Wayland display error with code {}", errno) + } + } } unsafe fn init_data_device(&mut self) { self.data_device = wl_request_constructor!( diff --git a/src/native/linux_wayland/libwayland_client.rs b/src/native/linux_wayland/libwayland_client.rs index 5ba484a4..9e31eb59 100644 --- a/src/native/linux_wayland/libwayland_client.rs +++ b/src/native/linux_wayland/libwayland_client.rs @@ -186,6 +186,11 @@ pub const WL_SUBSURFACE_PLACE_BELOW_SINCE_VERSION: u32 = 1; pub const WL_SUBSURFACE_SET_SYNC_SINCE_VERSION: u32 = 1; pub const WL_SUBSURFACE_SET_DESYNC_SINCE_VERSION: u32 = 1; +pub const ENOMEM: c_int = 12; +pub const EFAULT: c_int = 14; +pub const EINVAL: c_int = 22; +pub const EPROTO: c_int = 71; + pub type wl_shm_format = ::core::ffi::c_uint; pub const wl_shm_format_WL_SHM_FORMAT_ARGB8888: wl_shm_format = 0; @@ -608,6 +613,8 @@ crate::declare_module!( pub fn wl_display_dispatch_pending(*mut wl_display) -> c_int, pub fn wl_display_dispatch_queue(*mut wl_display, *mut wl_event_queue) -> c_int, pub fn wl_display_dispatch_queue_pending(*mut wl_display, *mut wl_event_queue) -> c_int, + pub fn wl_display_get_error(*mut wl_display) -> c_int, + pub fn wl_display_get_protocol_error(*mut wl_display, *mut *const wl_interface, *mut c_uint) -> c_uint, pub fn wl_proxy_set_queue(*mut wl_proxy, *mut wl_event_queue), pub fn wl_proxy_get_queue(*mut wl_proxy) -> *mut wl_event_queue, pub fn wl_proxy_add_listener(*mut wl_proxy, *mut Option, *mut c_void) -> c_int, From 9e48631f0245d8f840aa22cff63eb4776de2d45e Mon Sep 17 00:00:00 2001 From: bolphen <[email protected]> Date: Tue, 11 Mar 2025 10:39:32 +0000 Subject: [PATCH 2/3] native/linux_wayland: Fix pointer_handle_enter --- src/native/linux_wayland.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/native/linux_wayland.rs b/src/native/linux_wayland.rs index 65950f94..a8271396 100644 --- a/src/native/linux_wayland.rs +++ b/src/native/linux_wayland.rs @@ -690,9 +690,11 @@ unsafe extern "C" fn pointer_handle_enter( ) { let display: &mut WaylandPayload = &mut *(data as *mut _); display.focused_window = surface; - display - .pointer_context - .handle_enter(&mut display.client, serial); + if surface == display.surface { + display + .pointer_context + .handle_enter(&mut display.client, serial); + } } unsafe extern "C" fn pointer_handle_leave( From 02cc674c2fdba95d1b917a5ef89f6fa0d048f6dd Mon Sep 17 00:00:00 2001 From: bolphen <[email protected]> Date: Tue, 11 Mar 2025 12:46:01 +0000 Subject: [PATCH 3/3] native/linux_wayland: Fix high-dpi --- src/native/linux_wayland.rs | 18 +++++++++--------- src/native/linux_wayland/decorations.rs | 10 ++++++++++ 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/native/linux_wayland.rs b/src/native/linux_wayland.rs index a8271396..ba010d2c 100644 --- a/src/native/linux_wayland.rs +++ b/src/native/linux_wayland.rs @@ -787,23 +787,16 @@ unsafe extern "C" fn relative_pointer_handle_relative_motion( } unsafe extern "C" fn output_handle_scale( - data: *mut std::ffi::c_void, + _data: *mut std::ffi::c_void, _output: *mut wl_output, factor: core::ffi::c_int, ) { - let display: &mut WaylandPayload = &mut *(data as *mut _); let mut d = crate::native_display().try_lock().unwrap(); if d.high_dpi { let dpi_scale = d.dpi_scale as i32; d.screen_width = d.screen_width / dpi_scale * factor; d.screen_height = d.screen_height / dpi_scale * factor; d.dpi_scale = factor as _; - wl_request!( - display.client, - display.surface, - WL_SURFACE_SET_BUFFER_SCALE, - factor - ); } } @@ -1126,7 +1119,7 @@ where let clipboard = Box::new(clipboard::WaylandClipboard::new(&mut display as *mut _)); crate::set_display(NativeDisplayData { high_dpi: conf.high_dpi, - dpi_scale: 1., + dpi_scale: 1., // At this point dpi_scale is not known to us blocking_event_loop: conf.platform.blocking_event_loop, ..NativeDisplayData::new(conf.window_width, conf.window_height, tx, clipboard) }); @@ -1147,12 +1140,19 @@ where .unwrap(); { + // At this point we have been told the dpi_scale let d = crate::native_display().try_lock().unwrap(); display.egl_window = (display.egl.wl_egl_window_create)( display.surface as _, d.screen_width, d.screen_height, ); + wl_request!( + display.client, + display.surface, + WL_SURFACE_SET_BUFFER_SCALE, + d.dpi_scale as i32 + ); } let egl_surface = (libegl.eglCreateWindowSurface)( diff --git a/src/native/linux_wayland/decorations.rs b/src/native/linux_wayland/decorations.rs index 6789d03f..a6680ca6 100644 --- a/src/native/linux_wayland/decorations.rs +++ b/src/native/linux_wayland/decorations.rs @@ -211,6 +211,16 @@ unsafe extern "C" fn handle_configure(data: *mut std::ffi::c_void, width: i32, h fallback.resize(&mut payload.client, width, height); } (payload.egl.wl_egl_window_resize)(payload.egl_window, window_width, window_height, 0, 0); + // We need to ensure that the buffer has been correctly resized before setting the + // dpi_scale, since Wayland would rather crash than letting you have a width that's an + // odd number on a display with 2x dpi... + (payload.client.wl_display_dispatch_pending)(payload.display); + wl_request!( + payload.client, + payload.surface, + WL_SURFACE_SET_BUFFER_SCALE, + dpi_scale + ); // The compositor can send multiple resizing configure during a single frame, and we // probably don't want to fire the resize event for every one of them // So if we still have a Resize event in the queue, instead of pushing a new one, we batch