1
0
Fork 0
forked from wry/wry

Merge pull request #535 from mahkoh/jorth/batch-xdg-surface-configure

xdg-shell: batch xdg_surface.configure events
This commit is contained in:
mahkoh 2025-07-22 23:00:36 +02:00 committed by GitHub
commit eb14eb6a68
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 53 additions and 9 deletions

View file

@ -35,7 +35,10 @@ use {
jay_screencast::{perform_screencast_realloc, perform_toplevel_screencasts},
wl_output::{OutputId, PersistentOutputState, WlOutputGlobal},
wl_seat::handle_position_hint_requests,
wl_surface::{NoneSurfaceExt, zwp_input_popup_surface_v2::input_popup_positioning},
wl_surface::{
NoneSurfaceExt, xdg_surface::handle_xdg_surface_configure_events,
zwp_input_popup_surface_v2::input_popup_positioning,
},
wlr_output_manager::wlr_output_manager_done,
workspace_manager::workspace_manager_done,
},
@ -353,6 +356,7 @@ fn start_compositor2(
head_managers_async: Default::default(),
show_bar: Cell::new(true),
enable_primary_selection: Cell::new(true),
xdg_surface_configure_events: Default::default(),
});
state.tracker.register(ClientId::from_raw(0));
create_dummy_output(&state);
@ -546,6 +550,11 @@ fn start_global_event_handlers(state: &Rc<State>) -> Vec<SpawnedFuture<()>> {
Phase::Layout,
handle_jay_head_manager_done(state.clone()),
),
eng.spawn2(
"xdg_surface configure events",
Phase::PostLayout,
handle_xdg_surface_configure_events(state.clone()),
),
]
}

View file

@ -18,6 +18,7 @@ use {
leaks::Tracker,
object::Object,
rect::Rect,
state::State,
tree::{
FindTreeResult, FoundNode, Node, NodeLayerLink, NodeLocation, OutputNode, StackedNode,
WorkspaceNode,
@ -41,6 +42,22 @@ use {
thiserror::Error,
};
pub struct XdgSurfaceConfigureEvent {
xdg: Rc<XdgSurface>,
serial: u32,
}
pub async fn handle_xdg_surface_configure_events(state: Rc<State>) {
loop {
let ev = state.xdg_surface_configure_events.pop().await;
ev.xdg.configure_scheduled.set(false);
if ev.xdg.destroyed.get() {
continue;
}
ev.xdg.send_configure(ev.serial);
}
}
#[expect(dead_code)]
const NOT_CONSTRUCTED: u32 = 1;
const ALREADY_CONSTRUCTED: u32 = 2;
@ -81,6 +98,8 @@ pub struct XdgSurface {
pub workspace: CloneCell<Option<Rc<WorkspaceNode>>>,
pub tracker: Tracker<Self>,
have_initial_commit: Cell<bool>,
configure_scheduled: Cell<bool>,
destroyed: Cell<bool>,
}
struct Popup {
@ -236,6 +255,8 @@ impl XdgSurface {
workspace: Default::default(),
tracker: Default::default(),
have_initial_commit: Default::default(),
configure_scheduled: Default::default(),
destroyed: Default::default(),
}
}
@ -319,9 +340,19 @@ impl XdgSurface {
self.geometry.get()
}
pub fn do_send_configure(&self) {
let serial = self.requested_serial.fetch_add(1) + 1;
self.send_configure(serial);
pub fn schedule_configure(self: &Rc<Self>) {
if self.configure_scheduled.replace(true) {
return;
}
let serial = self.requested_serial.add_fetch(1);
self.surface
.client
.state
.xdg_surface_configure_events
.push(XdgSurfaceConfigureEvent {
xdg: self.clone(),
serial,
});
}
pub fn send_configure(&self, serial: u32) {
@ -375,6 +406,7 @@ impl XdgSurfaceRequestHandler for XdgSurface {
type Error = XdgSurfaceError;
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.destroyed.set(true);
if self.ext.is_some() {
return Err(XdgSurfaceError::RoleNotYetDestroyed(self.id));
}
@ -564,7 +596,7 @@ impl SurfaceExt for XdgSurface {
&& let Some(ext) = self.ext.get()
{
ext.initial_configure()?;
self.do_send_configure();
self.schedule_configure();
self.have_initial_commit.set(true);
}
if let Some(pending) = &mut pending.xdg_surface

View file

@ -245,7 +245,7 @@ impl XdgPopupRequestHandler for XdgPopup {
let rel = self.relative_position.get();
self.send_repositioned(req.token);
self.send_configure(rel.x1(), rel.y1(), rel.width(), rel.height());
self.xdg.do_send_configure();
self.xdg.schedule_configure();
}
Ok(())
}

View file

@ -195,7 +195,7 @@ impl XdgToplevel {
let rect = self.xdg.absolute_desired_extents.get();
self.send_configure_checked(rect.width(), rect.height());
}
self.xdg.do_send_configure();
self.xdg.schedule_configure();
}
fn send_configure_checked(&self, mut width: i32, mut height: i32) {
@ -658,7 +658,7 @@ impl ToplevelNodeBase for XdgToplevel {
if changed {
let rect = self.xdg.absolute_desired_extents.get();
self.send_configure_checked(rect.width(), rect.height());
self.xdg.do_send_configure();
self.xdg.schedule_configure();
}
}
@ -677,7 +677,7 @@ impl ToplevelNodeBase for XdgToplevel {
let de = self.xdg.absolute_desired_extents.get();
if de.width() != nw || de.height() != nh {
self.send_configure_checked(nw, nh);
self.xdg.do_send_configure();
self.xdg.schedule_configure();
// self.xdg.surface.client.flush();
}
self.xdg.set_absolute_desired_extents(rect);

View file

@ -64,6 +64,7 @@ use {
tray::TrayItemIds,
wl_subsurface::SubsurfaceIds,
x_surface::xwindow::{Xwindow, XwindowId},
xdg_surface::XdgSurfaceConfigureEvent,
zwp_idle_inhibitor_v1::{IdleInhibitorId, IdleInhibitorIds, ZwpIdleInhibitorV1},
zwp_input_popup_surface_v2::ZwpInputPopupSurfaceV2,
},
@ -273,6 +274,7 @@ pub struct State {
pub head_managers_async: AsyncQueue<HeadManagerEvent>,
pub show_bar: Cell<bool>,
pub enable_primary_selection: Cell<bool>,
pub xdg_surface_configure_events: AsyncQueue<XdgSurfaceConfigureEvent>,
}
// impl Drop for State {
@ -1079,6 +1081,7 @@ impl State {
self.cursor_user_group_hardware_cursor.take();
self.cpu_worker.clear();
self.wait_for_sync_obj.clear();
self.xdg_surface_configure_events.clear();
}
pub fn remove_toplevel_id(&self, id: ToplevelIdentifier) {