From 83fe764fcd68eccaa0ed73269ea98334d5055c51 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Wed, 1 Mar 2023 20:44:13 +0100 Subject: 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. --- river/Cursor.zig | 4 ++-- river/Root.zig | 3 --- river/Seat.zig | 2 -- river/View.zig | 43 +------------------------------------------ river/XdgToplevel.zig | 42 ++++++++++++++++++++++-------------------- river/XwaylandView.zig | 24 ++++++++++++++---------- river/command/filter.zig | 3 --- 7 files changed, 39 insertions(+), 82 deletions(-) diff --git a/river/Cursor.zig b/river/Cursor.zig index efe9f4f..b5279fa 100644 --- a/river/Cursor.zig +++ b/river/Cursor.zig @@ -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_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); }, .move => {}, - .resize => |resize| resize.view.setResizing(false), + .resize => |resize| resize.view.pending.resizing = false, } self.mode = .passthrough; diff --git a/river/Root.zig b/river/Root.zig index f989796..518d94a 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -420,8 +420,6 @@ pub fn applyPending(root: *Self) void { } if (output.pending.fullscreen != output.inflight.fullscreen) { if (output.inflight.fullscreen) |view| { - view.setFullscreen(false); - view.pending.box = view.post_fullscreen_box; view.pending.clampToOutput(); @@ -449,7 +447,6 @@ pub fn applyPending(root: *Self) void { const output = &node.data; if (output.pending.fullscreen != output.inflight.fullscreen) { if (output.pending.fullscreen) |view| { - view.setFullscreen(true); view.post_fullscreen_box = view.pending.box; view.pending.box = .{ .x = 0, diff --git a/river/Seat.zig b/river/Seat.zig index 802a5ce..21c40d5 100644 --- a/river/Seat.zig +++ b/river/Seat.zig @@ -220,7 +220,6 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void { switch (self.focused) { .view => |view| { view.pending.focus -= 1; - if (view.pending.focus == 0) view.setActivated(false); view.destroyPopups(); }, .layer => |layer_surface| { @@ -234,7 +233,6 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void { .view => |target_view| { assert(server.lock_manager.state != .locked); 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.urgent = false; }, diff --git a/river/View.zig b/river/View.zig index 158d1c5..af44cdb 100644 --- a/river/View.zig +++ b/river/View.zig @@ -66,6 +66,7 @@ pub const State = struct { fullscreen: bool = false, urgent: bool = false, borders: bool = true, + resizing: bool = false, /// Modify the x/y of the given state by delta_x/delta_y, clamping to the /// 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. pub fn getTitle(self: Self) ?[*:0]const u8 { return switch (self.impl) { diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig index 0969f80..cb5a20c 100644 --- a/river/XdgToplevel.zig +++ b/river/XdgToplevel.zig @@ -89,13 +89,33 @@ pub fn needsConfigure(self: Self) bool { // configured by setting the current width/height to the initial width/height // of the view in handleMap(). 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. pub fn configure(self: *Self) void { const state = &self.view.inflight; + 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; } @@ -108,18 +128,6 @@ pub fn close(self: Self) void { 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. pub fn getTitle(self: Self) ?[*:0]const u8 { 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; - // If the view has an app_id or title which is not configured to use client - // 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.pending.borders = !server.config.csdAllowed(view); view.map() catch { log.err("out of memory", .{}); diff --git a/river/XwaylandView.zig b/river/XwaylandView.zig index 376d7a2..10373d5 100644 --- a/river/XwaylandView.zig +++ b/river/XwaylandView.zig @@ -84,11 +84,14 @@ pub fn needsConfigure(self: Self) bool { var output_box: wlr.Box = undefined; server.root.output_layout.getBox(output.wlr_output, &output_box); - const state = &self.view.inflight; - return self.xwayland_surface.x != state.box.x + output_box.x or - self.xwayland_surface.y != state.box.y + output_box.y or - self.xwayland_surface.width != state.box.width or - self.xwayland_surface.height != state.box.height; + const view = self.view; + return self.xwayland_surface.x != view.inflight.box.x + output_box.x or + self.xwayland_surface.y != view.inflight.box.y + output_box.y or + self.xwayland_surface.width != view.inflight.box.width or + 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 { @@ -103,6 +106,11 @@ pub fn configure(self: Self) void { @intCast(u16, state.box.width), @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 { @@ -115,7 +123,7 @@ pub fn close(self: Self) void { 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 if (activated and self.xwayland_surface.minimized) { self.xwayland_surface.setMinimized(false); @@ -124,10 +132,6 @@ pub fn setActivated(self: Self, activated: bool) void { 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. pub fn getTitle(self: Self) ?[*:0]const u8 { return self.xwayland_surface.title; diff --git a/river/command/filter.zig b/river/command/filter.zig index 37d2cd2..8a69954 100644 --- a/river/command/filter.zig +++ b/river/command/filter.zig @@ -122,17 +122,14 @@ fn csdFilterUpdateViews(kind: FilterKind, pattern: []const u8, operation: enum { const view = @intToPtr(*View, xdg_toplevel_decoration.surface.data); if (viewMatchesPattern(kind, pattern, view)) { - const toplevel = view.impl.xdg_toplevel.xdg_toplevel; switch (operation) { .add => { _ = xdg_toplevel_decoration.setMode(.client_side); view.pending.borders = false; - _ = toplevel.setTiled(.{ .top = false, .bottom = false, .left = false, .right = false }); }, .remove => { _ = xdg_toplevel_decoration.setMode(.server_side); view.pending.borders = true; - _ = toplevel.setTiled(.{ .top = true, .bottom = true, .left = true, .right = true }); }, } } -- cgit v1.2.3