atagen

monolith

public
Star0
Watch0

Commit e27a31fac80d

tarball

atagen <boss@atagen.co>2026-10-19 10:36 UTC

4 files changed+34-13
scale: tell popups and send the scale before the initial configure

send_scales skipped popups, which kept a stale scale until their next commit. The scale also went out after the initial configure of toplevels, popups and layers, so a first buffer could be drawn at scale 1 and redrawn. A surface with no output found was marked told and then waited for an unrelated layout pass, and follow_pointer_scale allocated the output name on every motion event.
Modified file: crates/monolith/src/commit.rs+2 additions
@@ -93,6 +93,7 @@ impl CompositorHandler for State {
9393 let toplevel = window.toplevel().cloned();
9494 self.map_window(window, None);
9595 if let Some(t) = toplevel {
96+ self.send_scale_once(surface);
9697 t.send_configure();
9798 }
9899 }
@@ -101,6 +102,7 @@ impl CompositorHandler for State {
101102 if let Some(PopupKind::Xdg(popup)) = self.wm.popups.find_popup(surface)
102103 && !popup.is_initial_configure_sent()
103104 {
105+ self.send_scale_once(surface);
104106 let _ = popup.send_configure();
105107 }
106108 self.layer_commit(surface);
Modified file: crates/monolith/src/layers.rs+3 additions
@@ -112,6 +112,9 @@ impl State {
112112 .and_then(|d| d.lock().ok())
113113 .is_some_and(|d| d.initial_configure_sent)
114114 });
115+ if !configured {
116+ self.send_scale_once(surface);
117+ }
115118 {
116119 let mut map = layer_map_for_output(&output);
117120 map.arrange();
Modified file: crates/monolith/src/scale.rs+28 additions−12 deletions
@@ -4,7 +4,9 @@
44
55 use crate::state::State;
66 use smithay::desktop::utils::with_surfaces_surface_tree;
7-use smithay::desktop::{WindowSurfaceType, find_popup_root_surface, layer_map_for_output};
7+use smithay::desktop::{
8+ PopupManager, WindowSurfaceType, find_popup_root_surface, layer_map_for_output,
9+};
810 use smithay::output::{Output, Scale};
911 use smithay::reexports::wayland_server::Resource;
1012 use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
@@ -28,6 +30,14 @@ fn apply(surface: &WlSurface, states: &SurfaceData, scale: Scale) {
2830 states.data_map.insert_if_missing(|| Told);
2931 }
3032
33+fn apply_popups(root: &WlSurface, scale: Scale) {
34+ for (popup, _) in PopupManager::popups_for_surface(root) {
35+ with_surfaces_surface_tree(popup.wl_surface(), |surface, states| {
36+ apply(surface, states, scale);
37+ });
38+ }
39+}
40+
3141 impl State {
3242 /// Tells a surface that has not heard yet, which every commit asks of
3343 /// the surfaces it may have just created.
@@ -42,14 +52,13 @@ impl State {
4252 c.get_data::<smithay::xwayland::XWaylandClientData>()
4353 .is_some()
4454 });
45- match self.scale_output(surface).filter(|_| !xwayland) {
46- Some(output) => {
47- let scale = output.current_scale();
48- with_states(surface, |states| apply(surface, states, scale));
49- }
50- None => with_states(surface, |states| {
55+ if xwayland {
56+ with_states(surface, |states| {
5157 states.data_map.insert_if_missing(|| Told);
52- }),
58+ });
59+ } else if let Some(output) = self.scale_output(surface) {
60+ let scale = output.current_scale();
61+ with_states(surface, |states| apply(surface, states, scale));
5362 }
5463 }
5564
@@ -71,12 +80,16 @@ impl State {
7180 state
7281 .window
7382 .with_surfaces(|surface, states| apply(surface, states, scale));
83+ if let Some(root) = state.window.toplevel() {
84+ apply_popups(root.wl_surface(), scale);
85+ }
7486 }
7587 }
7688 for output in self.wm.space.outputs() {
7789 let scale = output.current_scale();
7890 for l in layer_map_for_output(output).layers() {
7991 l.with_surfaces(|surface, states| apply(surface, states, scale));
92+ apply_popups(l.wl_surface(), scale);
8093 }
8194 }
8295 for (output, surface) in self.services.lock.surfaces() {
@@ -105,20 +118,23 @@ impl State {
105118
106119 /// Retells the cursor and drag icon when the pointer crosses to an output.
107120 pub fn follow_pointer_scale(&mut self) {
108- let name = self.pointer_output().map(|o| o.name());
109- if self.input.pointer_output != name {
110- self.input.pointer_output = name;
121+ let under = self.pointer_output_ref();
122+ if self.input.pointer_output.as_ref() != under {
123+ self.input.pointer_output = under.cloned();
111124 self.send_pointer_scales();
112125 }
113126 }
114127
115128 pub fn pointer_output(&self) -> Option<Output> {
129+ self.pointer_output_ref().cloned()
130+ }
131+
132+ fn pointer_output_ref(&self) -> Option<&Output> {
116133 self.wm
117134 .space
118135 .output_under(self.input.pointer_pos)
119136 .next()
120137 .or_else(|| self.wm.space.outputs().next())
121- .cloned()
122138 }
123139
124140 /// The output a surface is mainly shown on.
Modified file: crates/monolith/src/state.rs+1 additions−1 deletions
@@ -64,7 +64,7 @@ pub struct Input {
6464 /// The edges of the window border under the pointer, for the resize cursor.
6565 pub hover: Option<crate::input::Edges>,
6666 /// The output the pointer was last on, whose scale cursor and drag icon surfaces follow.
67- pub pointer_output: Option<String>,
67+ pub pointer_output: Option<smithay::output::Output>,
6868 /// Where the last absolute device event put the pointer, so the next
6969 /// one yields a relative delta even while the pointer is held in place.
7070 pub absolute: Option<Point<f64, Logical>>,