From 97ec77e8fa2ebb272221f96d739ec274cd880bbf Mon Sep 17 00:00:00 2001 From: ShootingStarDragons Date: Wed, 4 Mar 2026 20:45:29 +0900 Subject: [PATCH] fix: panic on hyperland relate: https://github.com/waycrate/wayshot/issues/304 init ZXdgOutputInfo during wl_output callback, do not use oncecell set it later. Maybe dispatch is not finished --- libwaysip/src/dispatch.rs | 13 +++++++++++-- libwaysip/src/lib.rs | 20 ++++++++------------ libwaysip/src/state.rs | 20 +++++++++----------- 3 files changed, 28 insertions(+), 25 deletions(-) diff --git a/libwaysip/src/dispatch.rs b/libwaysip/src/dispatch.rs index 3c884d9..418fc1a 100644 --- a/libwaysip/src/dispatch.rs +++ b/libwaysip/src/dispatch.rs @@ -1,6 +1,6 @@ use crate::{ Position, Size, - state::{self, LayerSurfaceInfo, WaysipState}, + state::{self, LayerSurfaceInfo, WaysipState, ZXdgOutputInfo}, }; use wayland_client::{ Connection, Dispatch, Proxy, WEnum, delegate_noop, @@ -118,7 +118,16 @@ impl Dispatch for state::WaysipState { if interface == wl_output::WlOutput::interface().name { let output = proxy.bind::(name, version, qh, ()); - state.wloutput_infos.push(state::WlOutputInfo::new(output)); + let zxdgoutput = + state + .zxdg_output_manager + .get() + .unwrap() + .get_xdg_output(&output, qh, ()); + let zxdg_output_info = ZXdgOutputInfo::new(zxdgoutput); + state + .wloutput_infos + .push(state::WlOutputInfo::new(output, zxdg_output_info)); } } } diff --git a/libwaysip/src/lib.rs b/libwaysip/src/lib.rs index a6bea71..d5d2634 100644 --- a/libwaysip/src/lib.rs +++ b/libwaysip/src/lib.rs @@ -165,6 +165,14 @@ fn get_area_inner( if cursor_manager.is_none() && cursor_buffer.is_none() { return Err(WaySipError::CursorThemeFetchFailed); } + state + .zxdg_output_manager + .set( + globals + .bind::(&qh, 1..=3, ()) + .map_err(WaySipError::NotSupportedProtocol)?, + ) + .expect("Only can be set once"); state.cursor_manager = cursor_manager; @@ -179,18 +187,6 @@ fn get_area_inner( .blocking_dispatch(&mut state) .map_err(WaySipError::DispatchError)?; // then make a dispatch - let xdg_output_manager = globals - .bind::(&qh, 1..=3, ()) - .map_err(WaySipError::NotSupportedProtocol)?; - - for wloutput in state.wloutput_infos.iter_mut() { - let zwloutput = xdg_output_manager.get_xdg_output(wloutput.get_output(), &qh, ()); - wloutput - .xdg_output_info - .set(state::ZXdgOutputInfo::new(zwloutput)) - .expect("should be set only once"); - } - event_queue .blocking_dispatch(&mut state) .map_err(WaySipError::DispatchError)?; // then make a dispatch diff --git a/libwaysip/src/state.rs b/libwaysip/src/state.rs index 56c9b82..cf3d1a4 100644 --- a/libwaysip/src/state.rs +++ b/libwaysip/src/state.rs @@ -12,7 +12,7 @@ use wayland_client::{ use wayland_cursor::CursorImageBuffer; use wayland_protocols::{ wp::cursor_shape::v1::client::wp_cursor_shape_manager_v1::WpCursorShapeManagerV1, - xdg::xdg_output::zv1::client::zxdg_output_v1, + xdg::xdg_output::zv1::client::{zxdg_output_manager_v1::ZxdgOutputManagerV1, zxdg_output_v1}, }; use wayland_protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1; @@ -65,24 +65,20 @@ pub struct WlOutputInfo { pub description: String, pub name: String, pub size: Size, - pub xdg_output_info: OnceCell, + pub xdg_output_info: ZXdgOutputInfo, } impl WlOutputInfo { pub(crate) fn xdg_output_info_mut(&mut self) -> &mut ZXdgOutputInfo { - self.xdg_output_info.get_mut().expect("should inited") + &mut self.xdg_output_info } pub(crate) fn xdg_output_info(&self) -> &ZXdgOutputInfo { - self.xdg_output_info.get().expect("should inited") + &self.xdg_output_info } pub(crate) fn zxdg_output(&self) -> &zxdg_output_v1::ZxdgOutputV1 { - &self - .xdg_output_info - .get() - .expect("should inited") - .zxdg_output + &self.xdg_output_info.zxdg_output } - pub fn new(output: WlOutput) -> Self { + pub fn new(output: WlOutput, xdg_output_info: ZXdgOutputInfo) -> Self { Self { output, description: "".to_string(), @@ -91,7 +87,7 @@ impl WlOutputInfo { width: 0, height: 0, }, - xdg_output_info: OnceCell::new(), + xdg_output_info, } } pub fn get_screen_info(&self) -> ScreenInfo { @@ -177,6 +173,7 @@ pub struct WaysipState { pub end_pos: Option>, pub current_screen: usize, pub cursor_manager: Option, + pub zxdg_output_manager: OnceCell, pub shm: Option, pub qh: Option>, pub predefined_boxes: Option>, @@ -200,6 +197,7 @@ impl WaysipState { end_pos: None, current_screen: 0, cursor_manager: None, + zxdg_output_manager: OnceCell::new(), qh: None, shm: None, predefined_boxes: None,