View: only send configures through transactions
This reduces the number of separate configure events sent to clients through better batching and is also more correct.
This commit is contained in:
		| @ -658,7 +658,7 @@ pub fn enterMode(self: *Self, mode: enum { move, resize }, view: *View) void { | |||||||
|                 .offset_x = cur_box.x + cur_box.width - @floatToInt(i32, self.wlr_cursor.x), |                 .offset_x = cur_box.x + cur_box.width - @floatToInt(i32, self.wlr_cursor.x), | ||||||
|                 .offset_y = cur_box.y + cur_box.height - @floatToInt(i32, self.wlr_cursor.y), |                 .offset_y = cur_box.y + cur_box.height - @floatToInt(i32, self.wlr_cursor.y), | ||||||
|             } }; |             } }; | ||||||
|             view.setResizing(true); |             view.pending.resizing = true; | ||||||
|         }, |         }, | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -690,7 +690,7 @@ fn leaveMode(self: *Self, event: *wlr.Pointer.event.Button) void { | |||||||
|             _ = self.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state); |             _ = self.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state); | ||||||
|         }, |         }, | ||||||
|         .move => {}, |         .move => {}, | ||||||
|         .resize => |resize| resize.view.setResizing(false), |         .resize => |resize| resize.view.pending.resizing = false, | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     self.mode = .passthrough; |     self.mode = .passthrough; | ||||||
|  | |||||||
| @ -420,8 +420,6 @@ pub fn applyPending(root: *Self) void { | |||||||
|             } |             } | ||||||
|             if (output.pending.fullscreen != output.inflight.fullscreen) { |             if (output.pending.fullscreen != output.inflight.fullscreen) { | ||||||
|                 if (output.inflight.fullscreen) |view| { |                 if (output.inflight.fullscreen) |view| { | ||||||
|                     view.setFullscreen(false); |  | ||||||
|  |  | ||||||
|                     view.pending.box = view.post_fullscreen_box; |                     view.pending.box = view.post_fullscreen_box; | ||||||
|                     view.pending.clampToOutput(); |                     view.pending.clampToOutput(); | ||||||
|  |  | ||||||
| @ -449,7 +447,6 @@ pub fn applyPending(root: *Self) void { | |||||||
|             const output = &node.data; |             const output = &node.data; | ||||||
|             if (output.pending.fullscreen != output.inflight.fullscreen) { |             if (output.pending.fullscreen != output.inflight.fullscreen) { | ||||||
|                 if (output.pending.fullscreen) |view| { |                 if (output.pending.fullscreen) |view| { | ||||||
|                     view.setFullscreen(true); |  | ||||||
|                     view.post_fullscreen_box = view.pending.box; |                     view.post_fullscreen_box = view.pending.box; | ||||||
|                     view.pending.box = .{ |                     view.pending.box = .{ | ||||||
|                         .x = 0, |                         .x = 0, | ||||||
|  | |||||||
| @ -220,7 +220,6 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void { | |||||||
|     switch (self.focused) { |     switch (self.focused) { | ||||||
|         .view => |view| { |         .view => |view| { | ||||||
|             view.pending.focus -= 1; |             view.pending.focus -= 1; | ||||||
|             if (view.pending.focus == 0) view.setActivated(false); |  | ||||||
|             view.destroyPopups(); |             view.destroyPopups(); | ||||||
|         }, |         }, | ||||||
|         .layer => |layer_surface| { |         .layer => |layer_surface| { | ||||||
| @ -234,7 +233,6 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void { | |||||||
|         .view => |target_view| { |         .view => |target_view| { | ||||||
|             assert(server.lock_manager.state != .locked); |             assert(server.lock_manager.state != .locked); | ||||||
|             assert(self.focused_output == target_view.pending.output); |             assert(self.focused_output == target_view.pending.output); | ||||||
|             if (target_view.pending.focus == 0) target_view.setActivated(true); |  | ||||||
|             target_view.pending.focus += 1; |             target_view.pending.focus += 1; | ||||||
|             target_view.pending.urgent = false; |             target_view.pending.urgent = false; | ||||||
|         }, |         }, | ||||||
|  | |||||||
| @ -66,6 +66,7 @@ pub const State = struct { | |||||||
|     fullscreen: bool = false, |     fullscreen: bool = false, | ||||||
|     urgent: bool = false, |     urgent: bool = false, | ||||||
|     borders: bool = true, |     borders: bool = true, | ||||||
|  |     resizing: bool = false, | ||||||
|  |  | ||||||
|     /// Modify the x/y of the given state by delta_x/delta_y, clamping to the |     /// Modify the x/y of the given state by delta_x/delta_y, clamping to the | ||||||
|     /// bounds of the output. |     /// bounds of the output. | ||||||
| @ -353,48 +354,6 @@ pub fn destroyPopups(self: Self) void { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn setActivated(self: Self, activated: bool) void { |  | ||||||
|     switch (self.impl) { |  | ||||||
|         .xdg_toplevel => |xdg_toplevel| xdg_toplevel.setActivated(activated), |  | ||||||
|         .xwayland_view => |xwayland_view| xwayland_view.setActivated(activated), |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub fn setFullscreen(self: *Self, fullscreen: bool) void { |  | ||||||
|     switch (self.impl) { |  | ||||||
|         .xdg_toplevel => |xdg_toplevel| xdg_toplevel.setFullscreen(fullscreen), |  | ||||||
|         .xwayland_view => |*xwayland_view| { |  | ||||||
|             // TODO(zig): remove this uneeded if statement |  | ||||||
|             // https://github.com/ziglang/zig/issues/13655 |  | ||||||
|             if (build_options.xwayland) xwayland_view.setFullscreen(fullscreen); |  | ||||||
|         }, |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub fn setResizing(self: Self, resizing: bool) void { |  | ||||||
|     switch (self.impl) { |  | ||||||
|         .xdg_toplevel => |xdg_toplevel| xdg_toplevel.setResizing(resizing), |  | ||||||
|         .xwayland_view => {}, |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Iterates over all surfaces, subsurfaces, and popups in the tree |  | ||||||
| pub inline fn forEachSurface( |  | ||||||
|     self: Self, |  | ||||||
|     comptime T: type, |  | ||||||
|     comptime iterator: fn (surface: *wlr.Surface, sx: c_int, sy: c_int, data: T) void, |  | ||||||
|     user_data: T, |  | ||||||
| ) void { |  | ||||||
|     switch (self.impl) { |  | ||||||
|         .xdg_toplevel => |xdg_toplevel| { |  | ||||||
|             xdg_toplevel.xdg_toplevel.base.forEachSurface(T, iterator, user_data); |  | ||||||
|         }, |  | ||||||
|         .xwayland_view => |xwayland_view| { |  | ||||||
|             xwayland_view.xwayland_surface.surface.?.forEachSurface(T, iterator, user_data); |  | ||||||
|         }, |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Return the current title of the view if any. | /// Return the current title of the view if any. | ||||||
| pub fn getTitle(self: Self) ?[*:0]const u8 { | pub fn getTitle(self: Self) ?[*:0]const u8 { | ||||||
|     return switch (self.impl) { |     return switch (self.impl) { | ||||||
|  | |||||||
| @ -89,13 +89,33 @@ pub fn needsConfigure(self: Self) bool { | |||||||
|     // configured by setting the current width/height to the initial width/height |     // configured by setting the current width/height to the initial width/height | ||||||
|     // of the view in handleMap(). |     // of the view in handleMap(). | ||||||
|     return view.inflight.box.width != view.current.box.width or |     return view.inflight.box.width != view.current.box.width or | ||||||
|         view.inflight.box.height != view.current.box.height; |         view.inflight.box.height != view.current.box.height or | ||||||
|  |         (view.inflight.focus != 0) != (view.current.focus != 0) or | ||||||
|  |         (view.inflight.output != null and view.inflight.output.?.inflight.fullscreen == view) != | ||||||
|  |         (view.current.output != null and view.current.output.?.current.fullscreen == view) or | ||||||
|  |         view.inflight.borders != view.current.borders or | ||||||
|  |         view.inflight.resizing != view.current.resizing; | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Send a configure event, applying the inflight state of the view. | /// Send a configure event, applying the inflight state of the view. | ||||||
| pub fn configure(self: *Self) void { | pub fn configure(self: *Self) void { | ||||||
|     const state = &self.view.inflight; |     const state = &self.view.inflight; | ||||||
|  |  | ||||||
|     self.view.inflight_serial = self.xdg_toplevel.setSize(state.box.width, state.box.height); |     self.view.inflight_serial = self.xdg_toplevel.setSize(state.box.width, state.box.height); | ||||||
|  |  | ||||||
|  |     _ = self.xdg_toplevel.setActivated(state.focus != 0); | ||||||
|  |  | ||||||
|  |     const fullscreen = state.output != null and state.output.?.inflight.fullscreen == self.view; | ||||||
|  |     _ = self.xdg_toplevel.setFullscreen(fullscreen); | ||||||
|  |  | ||||||
|  |     if (state.borders) { | ||||||
|  |         _ = self.xdg_toplevel.setTiled(.{ .top = true, .bottom = true, .left = true, .right = true }); | ||||||
|  |     } else { | ||||||
|  |         _ = self.xdg_toplevel.setTiled(.{ .top = false, .bottom = false, .left = false, .right = false }); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     _ = self.xdg_toplevel.setResizing(state.resizing); | ||||||
|  |  | ||||||
|     self.acked_inflight_serial = false; |     self.acked_inflight_serial = false; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -108,18 +128,6 @@ pub fn close(self: Self) void { | |||||||
|     self.xdg_toplevel.sendClose(); |     self.xdg_toplevel.sendClose(); | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn setActivated(self: Self, activated: bool) void { |  | ||||||
|     _ = self.xdg_toplevel.setActivated(activated); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub fn setFullscreen(self: Self, fullscreen: bool) void { |  | ||||||
|     _ = self.xdg_toplevel.setFullscreen(fullscreen); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| pub fn setResizing(self: Self, resizing: bool) void { |  | ||||||
|     _ = self.xdg_toplevel.setResizing(resizing); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Return the current title of the toplevel if any. | /// Return the current title of the toplevel if any. | ||||||
| pub fn getTitle(self: Self) ?[*:0]const u8 { | pub fn getTitle(self: Self) ?[*:0]const u8 { | ||||||
|     return self.xdg_toplevel.title; |     return self.xdg_toplevel.title; | ||||||
| @ -193,13 +201,7 @@ fn handleMap(listener: *wl.Listener(void)) void { | |||||||
|  |  | ||||||
|     self.view.pending.fullscreen = self.xdg_toplevel.requested.fullscreen; |     self.view.pending.fullscreen = self.xdg_toplevel.requested.fullscreen; | ||||||
|  |  | ||||||
|     // If the view has an app_id or title which is not configured to use client |     view.pending.borders = !server.config.csdAllowed(view); | ||||||
|     // side decorations, inform it that it is tiled. |  | ||||||
|     if (server.config.csdAllowed(view)) { |  | ||||||
|         view.pending.borders = false; |  | ||||||
|     } else { |  | ||||||
|         _ = self.xdg_toplevel.setTiled(.{ .top = true, .bottom = true, .left = true, .right = true }); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     view.map() catch { |     view.map() catch { | ||||||
|         log.err("out of memory", .{}); |         log.err("out of memory", .{}); | ||||||
|  | |||||||
| @ -84,11 +84,14 @@ pub fn needsConfigure(self: Self) bool { | |||||||
|     var output_box: wlr.Box = undefined; |     var output_box: wlr.Box = undefined; | ||||||
|     server.root.output_layout.getBox(output.wlr_output, &output_box); |     server.root.output_layout.getBox(output.wlr_output, &output_box); | ||||||
|  |  | ||||||
|     const state = &self.view.inflight; |     const view = self.view; | ||||||
|     return self.xwayland_surface.x != state.box.x + output_box.x or |     return self.xwayland_surface.x != view.inflight.box.x + output_box.x or | ||||||
|         self.xwayland_surface.y != state.box.y + output_box.y or |         self.xwayland_surface.y != view.inflight.box.y + output_box.y or | ||||||
|         self.xwayland_surface.width != state.box.width or |         self.xwayland_surface.width != view.inflight.box.width or | ||||||
|         self.xwayland_surface.height != state.box.height; |         self.xwayland_surface.height != view.inflight.box.height or | ||||||
|  |         (view.inflight.focus != 0) != (view.current.focus != 0) or | ||||||
|  |         (view.inflight.output != null and view.inflight.output.?.inflight.fullscreen == view) != | ||||||
|  |         (view.current.output != null and view.current.output.?.current.fullscreen == view); | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn configure(self: Self) void { | pub fn configure(self: Self) void { | ||||||
| @ -103,6 +106,11 @@ pub fn configure(self: Self) void { | |||||||
|         @intCast(u16, state.box.width), |         @intCast(u16, state.box.width), | ||||||
|         @intCast(u16, state.box.height), |         @intCast(u16, state.box.height), | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|  |     self.setActivated(state.focus != 0); | ||||||
|  |  | ||||||
|  |     const fullscreen = state.output != null and state.output.?.inflight.fullscreen == self.view; | ||||||
|  |     self.xwayland_surface.setFullscreen(fullscreen); | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn rootSurface(self: Self) *wlr.Surface { | pub fn rootSurface(self: Self) *wlr.Surface { | ||||||
| @ -115,7 +123,7 @@ pub fn close(self: Self) void { | |||||||
|     self.xwayland_surface.close(); |     self.xwayland_surface.close(); | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn setActivated(self: Self, activated: bool) void { | fn setActivated(self: Self, activated: bool) void { | ||||||
|     // See comment on handleRequestMinimize() for details |     // See comment on handleRequestMinimize() for details | ||||||
|     if (activated and self.xwayland_surface.minimized) { |     if (activated and self.xwayland_surface.minimized) { | ||||||
|         self.xwayland_surface.setMinimized(false); |         self.xwayland_surface.setMinimized(false); | ||||||
| @ -124,10 +132,6 @@ pub fn setActivated(self: Self, activated: bool) void { | |||||||
|     self.xwayland_surface.restack(null, .above); |     self.xwayland_surface.restack(null, .above); | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn setFullscreen(self: *Self, fullscreen: bool) void { |  | ||||||
|     self.xwayland_surface.setFullscreen(fullscreen); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /// Get the current title of the xwayland surface if any. | /// Get the current title of the xwayland surface if any. | ||||||
| pub fn getTitle(self: Self) ?[*:0]const u8 { | pub fn getTitle(self: Self) ?[*:0]const u8 { | ||||||
|     return self.xwayland_surface.title; |     return self.xwayland_surface.title; | ||||||
|  | |||||||
| @ -122,17 +122,14 @@ fn csdFilterUpdateViews(kind: FilterKind, pattern: []const u8, operation: enum { | |||||||
|  |  | ||||||
|         const view = @intToPtr(*View, xdg_toplevel_decoration.surface.data); |         const view = @intToPtr(*View, xdg_toplevel_decoration.surface.data); | ||||||
|         if (viewMatchesPattern(kind, pattern, view)) { |         if (viewMatchesPattern(kind, pattern, view)) { | ||||||
|             const toplevel = view.impl.xdg_toplevel.xdg_toplevel; |  | ||||||
|             switch (operation) { |             switch (operation) { | ||||||
|                 .add => { |                 .add => { | ||||||
|                     _ = xdg_toplevel_decoration.setMode(.client_side); |                     _ = xdg_toplevel_decoration.setMode(.client_side); | ||||||
|                     view.pending.borders = false; |                     view.pending.borders = false; | ||||||
|                     _ = toplevel.setTiled(.{ .top = false, .bottom = false, .left = false, .right = false }); |  | ||||||
|                 }, |                 }, | ||||||
|                 .remove => { |                 .remove => { | ||||||
|                     _ = xdg_toplevel_decoration.setMode(.server_side); |                     _ = xdg_toplevel_decoration.setMode(.server_side); | ||||||
|                     view.pending.borders = true; |                     view.pending.borders = true; | ||||||
|                     _ = toplevel.setTiled(.{ .top = true, .bottom = true, .left = true, .right = true }); |  | ||||||
|                 }, |                 }, | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user