From a44f36641e139e95dd6442ceee3796655e79796a Mon Sep 17 00:00:00 2001 From: Nova Date: Sat, 25 Jan 2025 14:02:03 -0800 Subject: [PATCH] fix: wayland inconsistencies --- Cargo.lock | 38 +++++++++++---------------- src/wayland/compositor.rs | 55 ++++++++++++++++++++++++++++----------- src/wayland/seat.rs | 2 +- src/wayland/state.rs | 4 +++ src/wayland/xdg_shell.rs | 11 +++++--- 5 files changed, 68 insertions(+), 42 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ab6942a..4e78955 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -842,22 +842,23 @@ checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "drm" -version = "0.12.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98888c4bbd601524c11a7ed63f814b8825f420514f78e96f752c437ae9cbb5d1" +checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" dependencies = [ "bitflags 2.6.0", "bytemuck", "drm-ffi", "drm-fourcc", + "libc", "rustix", ] [[package]] name = "drm-ffi" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97c98727e48b7ccb4f4aea8cfe881e5b07f702d17b7875991881b41af7278d53" +checksum = "d8e41459d99a9b529845f6d2c909eb9adf3b6d2f82635ae40be8de0601726e8b" dependencies = [ "drm-sys", "rustix", @@ -871,9 +872,9 @@ checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" [[package]] name = "drm-sys" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd39dde40b6e196c2e8763f23d119ddb1a8714534bf7d77fa97a65b0feda3986" +checksum = "bafb66c8dbc944d69e15cfcc661df7e703beffbaec8bd63151368b06c5f9858c" dependencies = [ "libc", "linux-raw-sys 0.6.5", @@ -1519,7 +1520,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -2449,12 +2450,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scan_fmt" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b53b0a5db882a8e2fdaae0a43f7b39e7e9082389e978398bdf223a55b581248" - [[package]] name = "scoped-tls" version = "1.0.1" @@ -2600,8 +2595,8 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithay" -version = "0.3.0" -source = "git+https://github.com/smithay/smithay.git#656178be0a19ae4c577c9c93a3d4ebfdb80e649c" +version = "0.4.0" +source = "git+https://github.com/smithay/smithay.git#0c2230f858580b52d628087d6dae1795278b8756" dependencies = [ "appendlist", "bitflags 2.6.0", @@ -2615,14 +2610,11 @@ dependencies = [ "errno", "gl_generator", "indexmap 2.5.0", - "lazy_static", "libc", "libloading", - "once_cell", "profiling", "rand", "rustix", - "scan_fmt", "smallvec", "tempfile", "thiserror 1.0.63", @@ -3302,9 +3294,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.4" +version = "0.32.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5755d77ae9040bb872a25026555ce4cb0ae75fd923e90d25fba07d81057de0" +checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -3351,9 +3343,9 @@ dependencies = [ [[package]] name = "wayland-server" -version = "0.31.5" +version = "0.31.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f18d47038c0b10479e695d99ed073e400ccd9bdbb60e6e503c96f62adcb12b6" +checksum = "c89532cc712a2adb119eb4d09694b402576052254d0bb284f82ac1c47fb786ad" dependencies = [ "bitflags 2.6.0", "downcast-rs", @@ -3396,7 +3388,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] diff --git a/src/wayland/compositor.rs b/src/wayland/compositor.rs index 1527bbc..5124709 100644 --- a/src/wayland/compositor.rs +++ b/src/wayland/compositor.rs @@ -8,18 +8,20 @@ use crate::{ wayland::surface::CoreSurface, }; use parking_lot::Mutex; -use portable_atomic::{AtomicU32, Ordering}; use rand::Rng; use smithay::{ backend::renderer::utils::{on_commit_buffer_handler, RendererSurfaceStateUserData}, delegate_compositor, + desktop::PopupKind, reexports::wayland_server::{protocol::wl_surface::WlSurface, Client}, wayland::compositor::{ - self, add_post_commit_hook, CompositorClientState, CompositorHandler, CompositorState, + add_post_commit_hook, CompositorClientState, CompositorHandler, CompositorState, }, }; use std::sync::Arc; -use tracing::debug; +use tracing::{debug, warn}; + +pub struct ConfiguredSurface; impl CompositorHandler for WaylandState { fn compositor_state(&mut self) -> &mut CompositorState { @@ -30,19 +32,27 @@ impl CompositorHandler for WaylandState { debug!(?surface, "Surface commit"); on_commit_buffer_handler::(surface); - let mut count = 0; - compositor::with_states(surface, |data| { - let count_new = data - .data_map - .insert_if_missing_threadsafe(|| AtomicU32::new(0)); - if !count_new { - if let Some(stored_count) = data.data_map.get::() { - count = stored_count.fetch_add(1, Ordering::Relaxed); - } - } - data.data_map.get::>().cloned() - }); + if let Some(toplevel) = self + .xdg_shell + .toplevel_surfaces() + .iter() + .find(|s| s.wl_surface() == surface) + { + if !toplevel.is_initial_configure_sent() { + debug!("Sending initial configure for toplevel surface"); + toplevel.send_configure(); + surface.insert_data(ConfiguredSurface); + } + } + + self.popup_manager.commit(surface); + if let Some(PopupKind::Xdg(popup)) = self.popup_manager.find_popup(surface) { + if surface.insert_data(ConfiguredSurface) { + debug!("Configuring popup surface"); + let _ = popup.send_configure(); + } + } } fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState { @@ -54,6 +64,7 @@ impl CompositorHandler for WaylandState { surface.insert_data(SurfaceId::Child(id)); CoreSurface::add_to(surface); let Some(parent_surface_id) = parent.get_data::() else { + warn!("Parent surface has no SurfaceId"); return; }; surface.insert_data(Mutex::new(ChildInfo { @@ -68,6 +79,7 @@ impl CompositorHandler for WaylandState { })); let Some(panel_item) = surface_panel_item(parent) else { + warn!("Parent has no panel item"); return; }; let panel_item_weak = Arc::downgrade(&panel_item); @@ -75,11 +87,19 @@ impl CompositorHandler for WaylandState { if surface_panel_item(surf).is_some() { return; } + debug!("Linking surface to panel item"); surf.insert_data(panel_item_weak.clone()); let Some(panel_item) = surface_panel_item(surf) else { + warn!("Failed to link surface to panel item"); return; }; + + surf.with_child_info(|_info| { + panel_item.backend.reposition_child(surf); + }); + + debug!("Adding new child to panel item"); panel_item.backend.new_child(surf); }); @@ -88,6 +108,7 @@ impl CompositorHandler for WaylandState { .get_data_raw::(|s| s.lock().ok()?.view()) .flatten() else { + debug!("No view data for surface"); return; }; let mut changed = false; @@ -96,11 +117,13 @@ impl CompositorHandler for WaylandState { && info.geometry.origin.y != view.offset.y { changed = true; + debug!("Surface position changed"); } if info.geometry.size.x != view.dst.w as u32 && info.geometry.size.y != view.dst.h as u32 { changed = true; + debug!("Surface size changed"); } info.geometry.size = [view.dst.w as u32, view.dst.h as u32].into(); }); @@ -109,6 +132,7 @@ impl CompositorHandler for WaylandState { return; }; if changed { + debug!("Repositioning child due to geometry change"); panel_item.backend.reposition_child(surf); } }); @@ -119,6 +143,7 @@ impl CompositorHandler for WaylandState { return; }; if surface.get_child_info().is_some() { + debug!("Dropping destroyed child surface"); panel_item.backend.drop_child(surface); } } diff --git a/src/wayland/seat.rs b/src/wayland/seat.rs index 43aff00..8463473 100644 --- a/src/wayland/seat.rs +++ b/src/wayland/seat.rs @@ -225,7 +225,7 @@ impl SeatWrapper { } keyboard.input( &mut state.lock(), - key, + key.into(), if pressed { KeyState::Pressed } else { diff --git a/src/wayland/state.rs b/src/wayland/state.rs index aaebb01..30f708d 100644 --- a/src/wayland/state.rs +++ b/src/wayland/state.rs @@ -9,6 +9,7 @@ use smithay::{ renderer::gles::GlesRenderer, }, delegate_dmabuf, delegate_output, delegate_shm, + desktop::PopupManager, input::{keyboard::XkbConfig, SeatState}, output::{Mode, Output, Scale, Subpixel}, reexports::{ @@ -76,6 +77,7 @@ pub struct WaylandState { pub seat_state: SeatState, pub seat: Arc, pub xdg_shell: XdgShellState, + pub popup_manager: PopupManager, pub output: Output, } @@ -158,6 +160,7 @@ impl WaylandState { output.set_preferred(mode); let mut xdg_shell = XdgShellState::new::(&display_handle); + let popup_manager = PopupManager::default(); let mut capabilities = WmCapabilitySet::default(); capabilities.set(WmCapabilities::Maximize); capabilities.set(WmCapabilities::Fullscreen); @@ -182,6 +185,7 @@ impl WaylandState { seat_state, seat: Arc::new(SeatWrapper::new(weak.clone(), seat)), xdg_shell, + popup_manager, output, }) }) diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index 3500585..cdc0151 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -20,6 +20,7 @@ use rand::Rng; use rustc_hash::FxHashMap; use smithay::{ delegate_xdg_shell, + desktop::PopupKind, reexports::{ wayland_protocols::xdg::{ decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode, @@ -90,7 +91,6 @@ impl XdgShellHandler for WaylandState { s.states.set(State::Maximized); s.states.unset(State::Fullscreen); }); - toplevel.send_configure(); let initial_size = toplevel .wl_surface() @@ -225,14 +225,17 @@ impl XdgShellHandler for WaylandState { }; panel_item.toplevel_title_changed(&title) } - fn new_popup(&mut self, popup: PopupSurface, positioner: PositionerState) { + self.popup_manager + .track_popup(PopupKind::Xdg(popup.clone())) + .unwrap(); + let id = rand::thread_rng().gen_range(0..u64::MAX); popup.wl_surface().insert_data(SurfaceId::Child(id)); let Some(parent) = popup.get_parent_surface() else { + warn!("No parent surface found for popup"); return; }; - let _ = popup.send_configure(); CoreSurface::add_to(popup.wl_surface()); popup.wl_surface().insert_data(Mutex::new(ChildInfo { @@ -244,6 +247,7 @@ impl XdgShellHandler for WaylandState { })); let Some(panel_item) = surface_panel_item(&parent) else { + warn!("No panel item found for popup parent"); return; }; let panel_item_weak = Arc::downgrade(&panel_item); @@ -255,6 +259,7 @@ impl XdgShellHandler for WaylandState { } surf.insert_data(panel_item_weak.clone()); let Some(panel) = surface_panel_item(surf) else { + warn!("Failed to get panel item for popup surface"); return; }; panel.backend.new_child(surf);