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