xdg-decoration: clean up implementation
We now send some protocol errors that wlroots 0.16 is missing [1]. This also allows us to access the xdg decoration from a view, which will be necessary for some future changes. [1]: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4051
This commit is contained in:
parent
fcb184f0bd
commit
05eac54b07
@ -91,6 +91,7 @@ pub fn build(b: *zbs.Builder) !void {
|
||||
scanner.addSystemProtocol("staging/ext-session-lock/ext-session-lock-v1.xml");
|
||||
scanner.addSystemProtocol("unstable/pointer-gestures/pointer-gestures-unstable-v1.xml");
|
||||
scanner.addSystemProtocol("unstable/pointer-constraints/pointer-constraints-unstable-v1.xml");
|
||||
scanner.addSystemProtocol("unstable/xdg-decoration/xdg-decoration-unstable-v1.xml");
|
||||
scanner.addProtocolPath("protocol/river-control-unstable-v1.xml");
|
||||
scanner.addProtocolPath("protocol/river-status-unstable-v1.xml");
|
||||
scanner.addProtocolPath("protocol/river-layout-v3.xml");
|
||||
@ -109,6 +110,7 @@ pub fn build(b: *zbs.Builder) !void {
|
||||
scanner.generate("xdg_wm_base", 2);
|
||||
scanner.generate("zwp_pointer_gestures_v1", 3);
|
||||
scanner.generate("zwp_pointer_constraints_v1", 1);
|
||||
scanner.generate("zxdg_decoration_manager_v1", 1);
|
||||
scanner.generate("ext_session_lock_manager_v1", 1);
|
||||
|
||||
scanner.generate("zriver_control_v1", 1);
|
||||
|
2
deps/zig-wlroots
vendored
2
deps/zig-wlroots
vendored
@ -1 +1 @@
|
||||
Subproject commit f804c6d2ab1a240f7659c82325dc21ddcc6392b7
|
||||
Subproject commit c4cdb08505de19f6bfbf8e1825349b80c7696475
|
@ -1,70 +0,0 @@
|
||||
// This file is part of river, a dynamic tiling wayland compositor.
|
||||
//
|
||||
// Copyright 2020 The River Developers
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 3.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const Self = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const wlr = @import("wlroots");
|
||||
const wl = @import("wayland").server.wl;
|
||||
|
||||
const server = &@import("main.zig").server;
|
||||
const util = @import("util.zig");
|
||||
|
||||
const Server = @import("Server.zig");
|
||||
const View = @import("View.zig");
|
||||
|
||||
xdg_toplevel_decoration: *wlr.XdgToplevelDecorationV1,
|
||||
|
||||
destroy: wl.Listener(*wlr.XdgToplevelDecorationV1) =
|
||||
wl.Listener(*wlr.XdgToplevelDecorationV1).init(handleDestroy),
|
||||
request_mode: wl.Listener(*wlr.XdgToplevelDecorationV1) =
|
||||
wl.Listener(*wlr.XdgToplevelDecorationV1).init(handleRequestMode),
|
||||
|
||||
pub fn init(self: *Self, xdg_toplevel_decoration: *wlr.XdgToplevelDecorationV1) void {
|
||||
self.* = .{ .xdg_toplevel_decoration = xdg_toplevel_decoration };
|
||||
|
||||
xdg_toplevel_decoration.events.destroy.add(&self.destroy);
|
||||
xdg_toplevel_decoration.events.request_mode.add(&self.request_mode);
|
||||
|
||||
handleRequestMode(&self.request_mode, self.xdg_toplevel_decoration);
|
||||
}
|
||||
|
||||
fn handleDestroy(
|
||||
listener: *wl.Listener(*wlr.XdgToplevelDecorationV1),
|
||||
_: *wlr.XdgToplevelDecorationV1,
|
||||
) void {
|
||||
const self = @fieldParentPtr(Self, "destroy", listener);
|
||||
self.destroy.link.remove();
|
||||
self.request_mode.link.remove();
|
||||
|
||||
const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self);
|
||||
server.decoration_manager.decorations.remove(node);
|
||||
util.gpa.destroy(node);
|
||||
}
|
||||
|
||||
fn handleRequestMode(
|
||||
listener: *wl.Listener(*wlr.XdgToplevelDecorationV1),
|
||||
_: *wlr.XdgToplevelDecorationV1,
|
||||
) void {
|
||||
const self = @fieldParentPtr(Self, "request_mode", listener);
|
||||
|
||||
const view = @intToPtr(*View, self.xdg_toplevel_decoration.surface.data);
|
||||
if (server.config.csdAllowed(view)) {
|
||||
_ = self.xdg_toplevel_decoration.setMode(.client_side);
|
||||
} else {
|
||||
_ = self.xdg_toplevel_decoration.setMode(.server_side);
|
||||
}
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
// This file is part of river, a dynamic tiling wayland compositor.
|
||||
//
|
||||
// Copyright 2020 The River Developers
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 3.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const Self = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const wlr = @import("wlroots");
|
||||
const wl = @import("wayland").server.wl;
|
||||
|
||||
const server = &@import("main.zig").server;
|
||||
const util = @import("util.zig");
|
||||
|
||||
const Decoration = @import("Decoration.zig");
|
||||
const Server = @import("Server.zig");
|
||||
|
||||
/// List of all Decoration objects. This will clean itself up on exit through
|
||||
/// the wlr.XdgToplevelDecorationV1.events.destroy event.
|
||||
decorations: std.TailQueue(Decoration) = .{},
|
||||
|
||||
xdg_decoration_manager: *wlr.XdgDecorationManagerV1,
|
||||
|
||||
new_toplevel_decoration: wl.Listener(*wlr.XdgToplevelDecorationV1) =
|
||||
wl.Listener(*wlr.XdgToplevelDecorationV1).init(handleNewToplevelDecoration),
|
||||
|
||||
pub fn init(self: *Self) !void {
|
||||
self.* = .{
|
||||
.xdg_decoration_manager = try wlr.XdgDecorationManagerV1.create(server.wl_server),
|
||||
};
|
||||
|
||||
self.xdg_decoration_manager.events.new_toplevel_decoration.add(&self.new_toplevel_decoration);
|
||||
}
|
||||
|
||||
fn handleNewToplevelDecoration(
|
||||
listener: *wl.Listener(*wlr.XdgToplevelDecorationV1),
|
||||
xdg_toplevel_decoration: *wlr.XdgToplevelDecorationV1,
|
||||
) void {
|
||||
const self = @fieldParentPtr(Self, "new_toplevel_decoration", listener);
|
||||
const decoration_node = util.gpa.create(std.TailQueue(Decoration).Node) catch {
|
||||
xdg_toplevel_decoration.resource.postNoMemory();
|
||||
return;
|
||||
};
|
||||
decoration_node.data.init(xdg_toplevel_decoration);
|
||||
self.decorations.append(decoration_node);
|
||||
}
|
@ -11,7 +11,7 @@ const IdleInhibitorManager = @import("IdleInhibitorManager.zig");
|
||||
|
||||
inhibitor_manager: *IdleInhibitorManager,
|
||||
inhibitor: *wlr.IdleInhibitorV1,
|
||||
destroy: wl.Listener(*wlr.IdleInhibitorV1) = wl.Listener(*wlr.IdleInhibitorV1).init(handleDestroy),
|
||||
destroy: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleDestroy),
|
||||
|
||||
pub fn init(self: *Self, inhibitor: *wlr.IdleInhibitorV1, inhibitor_manager: *IdleInhibitorManager) !void {
|
||||
self.inhibitor_manager = inhibitor_manager;
|
||||
@ -22,7 +22,7 @@ pub fn init(self: *Self, inhibitor: *wlr.IdleInhibitorV1, inhibitor_manager: *Id
|
||||
inhibitor_manager.idleInhibitCheckActive();
|
||||
}
|
||||
|
||||
fn handleDestroy(listener: *wl.Listener(*wlr.IdleInhibitorV1), _: *wlr.IdleInhibitorV1) void {
|
||||
fn handleDestroy(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
|
||||
const self = @fieldParentPtr(Self, "destroy", listener);
|
||||
self.destroy.link.remove();
|
||||
|
||||
|
@ -71,6 +71,8 @@ hidden: struct {
|
||||
},
|
||||
},
|
||||
|
||||
views: wl.list.Head(View, .link),
|
||||
|
||||
new_output: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleNewOutput),
|
||||
|
||||
output_layout: *wlr.OutputLayout,
|
||||
@ -146,6 +148,7 @@ pub fn init(self: *Self) !void {
|
||||
.wm_stack = undefined,
|
||||
},
|
||||
},
|
||||
.views = undefined,
|
||||
.output_layout = output_layout,
|
||||
.output_manager = try wlr.OutputManagerV1.create(server.wl_server),
|
||||
.power_manager = try wlr.OutputPowerManagerV1.create(server.wl_server),
|
||||
@ -155,6 +158,7 @@ pub fn init(self: *Self) !void {
|
||||
self.hidden.pending.wm_stack.init();
|
||||
self.hidden.inflight.focus_stack.init();
|
||||
self.hidden.inflight.wm_stack.init();
|
||||
self.views.init();
|
||||
|
||||
server.backend.events.new_output.add(&self.new_output);
|
||||
self.output_manager.events.apply.add(&self.manager_apply);
|
||||
|
@ -26,7 +26,6 @@ const util = @import("util.zig");
|
||||
|
||||
const Config = @import("Config.zig");
|
||||
const Control = @import("Control.zig");
|
||||
const DecorationManager = @import("DecorationManager.zig");
|
||||
const IdleInhibitorManager = @import("IdleInhibitorManager.zig");
|
||||
const InputManager = @import("InputManager.zig");
|
||||
const LayerSurface = @import("LayerSurface.zig");
|
||||
@ -36,6 +35,7 @@ const Output = @import("Output.zig");
|
||||
const Root = @import("Root.zig");
|
||||
const SceneNodeData = @import("SceneNodeData.zig");
|
||||
const StatusManager = @import("StatusManager.zig");
|
||||
const XdgDecoration = @import("XdgDecoration.zig");
|
||||
const XdgToplevel = @import("XdgToplevel.zig");
|
||||
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
|
||||
const XwaylandView = @import("XwaylandView.zig");
|
||||
@ -55,6 +55,9 @@ allocator: *wlr.Allocator,
|
||||
xdg_shell: *wlr.XdgShell,
|
||||
new_xdg_surface: wl.Listener(*wlr.XdgSurface),
|
||||
|
||||
xdg_decoration_manager: *wlr.XdgDecorationManagerV1,
|
||||
new_toplevel_decoration: wl.Listener(*wlr.XdgToplevelDecorationV1),
|
||||
|
||||
layer_shell: *wlr.LayerShellV1,
|
||||
new_layer_surface: wl.Listener(*wlr.LayerSurfaceV1),
|
||||
|
||||
@ -66,7 +69,6 @@ foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1,
|
||||
xdg_activation: *wlr.XdgActivationV1,
|
||||
request_activate: wl.Listener(*wlr.XdgActivationV1.event.RequestActivate),
|
||||
|
||||
decoration_manager: DecorationManager,
|
||||
input_manager: InputManager,
|
||||
root: Root,
|
||||
config: Config,
|
||||
@ -103,6 +105,10 @@ pub fn init(self: *Self) !void {
|
||||
self.new_xdg_surface.setNotify(handleNewXdgSurface);
|
||||
self.xdg_shell.events.new_surface.add(&self.new_xdg_surface);
|
||||
|
||||
self.xdg_decoration_manager = try wlr.XdgDecorationManagerV1.create(self.wl_server);
|
||||
self.new_toplevel_decoration.setNotify(handleNewToplevelDecoration);
|
||||
self.xdg_decoration_manager.events.new_toplevel_decoration.add(&self.new_toplevel_decoration);
|
||||
|
||||
self.layer_shell = try wlr.LayerShellV1.create(self.wl_server);
|
||||
self.new_layer_surface.setNotify(handleNewLayerSurface);
|
||||
self.layer_shell.events.new_surface.add(&self.new_layer_surface);
|
||||
@ -122,7 +128,6 @@ pub fn init(self: *Self) !void {
|
||||
_ = try wlr.PrimarySelectionDeviceManagerV1.create(self.wl_server);
|
||||
|
||||
self.config = try Config.init();
|
||||
try self.decoration_manager.init();
|
||||
try self.root.init();
|
||||
// Must be called after root is initialized
|
||||
try self.input_manager.init();
|
||||
@ -205,6 +210,24 @@ fn handleNewXdgSurface(_: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSu
|
||||
};
|
||||
}
|
||||
|
||||
fn handleNewToplevelDecoration(
|
||||
_: *wl.Listener(*wlr.XdgToplevelDecorationV1),
|
||||
wlr_decoration: *wlr.XdgToplevelDecorationV1,
|
||||
) void {
|
||||
const xdg_toplevel = @intToPtr(*XdgToplevel, wlr_decoration.surface.data);
|
||||
|
||||
// TODO(wlroots): The next wlroots version will handle this for us
|
||||
if (xdg_toplevel.decoration != null) {
|
||||
wlr_decoration.resource.postError(
|
||||
.already_constructed,
|
||||
"xdg_toplevel already has a decoration object",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
XdgDecoration.init(wlr_decoration);
|
||||
}
|
||||
|
||||
fn handleNewLayerSurface(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: *wlr.LayerSurfaceV1) void {
|
||||
const self = @fieldParentPtr(Self, "new_layer_surface", listener);
|
||||
|
||||
|
@ -117,6 +117,9 @@ pub const State = struct {
|
||||
/// The implementation of this view
|
||||
impl: Impl,
|
||||
|
||||
/// Link for Root.views
|
||||
link: wl.list.Link,
|
||||
|
||||
tree: *wlr.SceneTree,
|
||||
surface_tree: *wlr.SceneTree,
|
||||
saved_surface_tree: *wlr.SceneTree,
|
||||
@ -182,6 +185,7 @@ pub fn create(impl: Impl) error{OutOfMemory}!*Self {
|
||||
|
||||
view.* = .{
|
||||
.impl = impl,
|
||||
.link = undefined,
|
||||
.tree = tree,
|
||||
.surface_tree = try tree.createSceneTree(),
|
||||
.saved_surface_tree = try tree.createSceneTree(),
|
||||
@ -199,6 +203,7 @@ pub fn create(impl: Impl) error{OutOfMemory}!*Self {
|
||||
.inflight_focus_stack_link = undefined,
|
||||
};
|
||||
|
||||
server.root.views.prepend(view);
|
||||
server.root.hidden.pending.focus_stack.prepend(view);
|
||||
server.root.hidden.pending.wm_stack.prepend(view);
|
||||
server.root.hidden.inflight.focus_stack.prepend(view);
|
||||
@ -229,6 +234,7 @@ pub fn destroy(view: *Self) void {
|
||||
view.tree.node.destroy();
|
||||
view.popup_tree.node.destroy();
|
||||
|
||||
view.link.remove();
|
||||
view.pending_focus_stack_link.remove();
|
||||
view.pending_wm_stack_link.remove();
|
||||
view.inflight_focus_stack_link.remove();
|
||||
|
80
river/XdgDecoration.zig
Normal file
80
river/XdgDecoration.zig
Normal file
@ -0,0 +1,80 @@
|
||||
// This file is part of river, a dynamic tiling wayland compositor.
|
||||
//
|
||||
// Copyright 2023 The River Developers
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 3.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
const XdgDecoration = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const wlr = @import("wlroots");
|
||||
const wl = @import("wayland").server.wl;
|
||||
|
||||
const server = &@import("main.zig").server;
|
||||
const util = @import("util.zig");
|
||||
|
||||
const XdgToplevel = @import("XdgToplevel.zig");
|
||||
|
||||
wlr_decoration: *wlr.XdgToplevelDecorationV1,
|
||||
|
||||
destroy: wl.Listener(*wlr.XdgToplevelDecorationV1) =
|
||||
wl.Listener(*wlr.XdgToplevelDecorationV1).init(handleDestroy),
|
||||
request_mode: wl.Listener(*wlr.XdgToplevelDecorationV1) =
|
||||
wl.Listener(*wlr.XdgToplevelDecorationV1).init(handleRequestMode),
|
||||
|
||||
pub fn init(wlr_decoration: *wlr.XdgToplevelDecorationV1) void {
|
||||
const xdg_toplevel = @intToPtr(*XdgToplevel, wlr_decoration.surface.data);
|
||||
|
||||
xdg_toplevel.decoration = .{ .wlr_decoration = wlr_decoration };
|
||||
const decoration = &xdg_toplevel.decoration.?;
|
||||
|
||||
wlr_decoration.events.destroy.add(&decoration.destroy);
|
||||
wlr_decoration.events.request_mode.add(&decoration.request_mode);
|
||||
|
||||
handleRequestMode(&decoration.request_mode, decoration.wlr_decoration);
|
||||
}
|
||||
|
||||
// TODO(wlroots): remove this function when updating to 0.17.0
|
||||
// https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4051
|
||||
pub fn deinit(decoration: *XdgDecoration) void {
|
||||
decoration.destroy.link.remove();
|
||||
decoration.request_mode.link.remove();
|
||||
}
|
||||
|
||||
fn handleDestroy(
|
||||
listener: *wl.Listener(*wlr.XdgToplevelDecorationV1),
|
||||
_: *wlr.XdgToplevelDecorationV1,
|
||||
) void {
|
||||
const decoration = @fieldParentPtr(XdgDecoration, "destroy", listener);
|
||||
const xdg_toplevel = @intToPtr(*XdgToplevel, decoration.wlr_decoration.surface.data);
|
||||
|
||||
decoration.deinit();
|
||||
|
||||
assert(xdg_toplevel.decoration != null);
|
||||
xdg_toplevel.decoration = null;
|
||||
}
|
||||
|
||||
fn handleRequestMode(
|
||||
listener: *wl.Listener(*wlr.XdgToplevelDecorationV1),
|
||||
_: *wlr.XdgToplevelDecorationV1,
|
||||
) void {
|
||||
const decoration = @fieldParentPtr(XdgDecoration, "request_mode", listener);
|
||||
|
||||
const xdg_toplevel = @intToPtr(*XdgToplevel, decoration.wlr_decoration.surface.data);
|
||||
if (server.config.csdAllowed(xdg_toplevel.view)) {
|
||||
_ = decoration.wlr_decoration.setMode(.client_side);
|
||||
} else {
|
||||
_ = decoration.wlr_decoration.setMode(.server_side);
|
||||
}
|
||||
}
|
@ -29,6 +29,7 @@ const Output = @import("Output.zig");
|
||||
const Seat = @import("Seat.zig");
|
||||
const XdgPopup = @import("XdgPopup.zig");
|
||||
const View = @import("View.zig");
|
||||
const XdgDecoration = @import("XdgDecoration.zig");
|
||||
|
||||
const log = std.log.scoped(.xdg_shell);
|
||||
|
||||
@ -37,6 +38,8 @@ view: *View,
|
||||
|
||||
xdg_toplevel: *wlr.XdgToplevel,
|
||||
|
||||
decoration: ?XdgDecoration = null,
|
||||
|
||||
/// Initialized on map
|
||||
geometry: wlr.Box = undefined,
|
||||
|
||||
@ -74,15 +77,15 @@ pub fn create(xdg_toplevel: *wlr.XdgToplevel) error{OutOfMemory}!void {
|
||||
} });
|
||||
errdefer view.destroy();
|
||||
|
||||
view.impl.xdg_toplevel.view = view;
|
||||
|
||||
_ = try view.surface_tree.createSceneXdgSurface(xdg_toplevel.base);
|
||||
|
||||
xdg_toplevel.base.data = @ptrToInt(view);
|
||||
xdg_toplevel.base.surface.data = @ptrToInt(&view.tree.node);
|
||||
|
||||
// Add listeners that are active over the view's entire lifetime
|
||||
const self = &view.impl.xdg_toplevel;
|
||||
|
||||
self.view = view;
|
||||
|
||||
xdg_toplevel.base.data = @ptrToInt(self);
|
||||
|
||||
// Add listeners that are active over the toplevel's entire lifetime
|
||||
xdg_toplevel.base.events.destroy.add(&self.destroy);
|
||||
xdg_toplevel.base.events.map.add(&self.map);
|
||||
xdg_toplevel.base.events.unmap.add(&self.unmap);
|
||||
@ -170,6 +173,17 @@ pub fn destroyPopups(self: Self) void {
|
||||
fn handleDestroy(listener: *wl.Listener(void)) void {
|
||||
const self = @fieldParentPtr(Self, "destroy", listener);
|
||||
|
||||
// TODO(wlroots): Replace this with an assertion when updating to wlroots 0.17.0
|
||||
// https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4051
|
||||
if (self.decoration) |*decoration| {
|
||||
decoration.wlr_decoration.resource.postError(
|
||||
.orphaned,
|
||||
"xdg_toplevel destroyed before xdg_toplevel_decoration",
|
||||
);
|
||||
decoration.deinit();
|
||||
self.decoration = null;
|
||||
}
|
||||
|
||||
// Remove listeners that are active for the entire lifetime of the view
|
||||
self.destroy.link.remove();
|
||||
self.map.link.remove();
|
||||
|
@ -116,24 +116,25 @@ pub fn csdFilterRemove(
|
||||
}
|
||||
|
||||
fn csdFilterUpdateViews(kind: FilterKind, pattern: []const u8, operation: enum { add, remove }) void {
|
||||
var decoration_it = server.decoration_manager.decorations.first;
|
||||
while (decoration_it) |decoration_node| : (decoration_it = decoration_node.next) {
|
||||
const xdg_toplevel_decoration = decoration_node.data.xdg_toplevel_decoration;
|
||||
|
||||
const view = @intToPtr(*View, xdg_toplevel_decoration.surface.data);
|
||||
var it = server.root.views.iterator(.forward);
|
||||
while (it.next()) |view| {
|
||||
if (view.impl == .xdg_toplevel) {
|
||||
if (view.impl.xdg_toplevel.decoration) |decoration| {
|
||||
if (viewMatchesPattern(kind, pattern, view)) {
|
||||
switch (operation) {
|
||||
.add => {
|
||||
_ = xdg_toplevel_decoration.setMode(.client_side);
|
||||
_ = decoration.wlr_decoration.setMode(.client_side);
|
||||
view.pending.borders = false;
|
||||
},
|
||||
.remove => {
|
||||
_ = xdg_toplevel_decoration.setMode(.server_side);
|
||||
_ = decoration.wlr_decoration.setMode(.server_side);
|
||||
view.pending.borders = true;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn viewMatchesPattern(kind: FilterKind, pattern: []const u8, view: *View) bool {
|
||||
|
Loading…
Reference in New Issue
Block a user