Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
river: rename view -> window
This terminology was cargo-culted from sway, which in turn cargo-culted
it from weston. The terminology doesn't even make sense in weston.
river/Config.zig | 2 +-
river/Cursor.zig | 76 +++++-----
river/ForeignToplevelHandle.zig | 30 ++--
river/IdleInhibitManager.zig | 4 +-
river/InputPopup.zig | 4 +-
river/Output.zig | 16 +-
river/PointerConstraint.zig | 2 +-
river/Root.zig | 74 ++++-----
river/SceneNodeData.zig | 4 +-
river/Seat.zig | 36 ++---
river/Server.zig | 8 +-
river/{View.zig => Window.zig} | 286 +++++++++++++++++------------------
river/XdgDecoration.zig | 6 +-
river/XdgPopup.zig | 4 +-
river/XdgToplevel.zig | 122 +++++++--------
river/XwaylandOverrideRedirect.zig | 20 +--
river/XwaylandView.zig | 297 -------------------------------------
river/XwaylandWindow.zig | 297 +++++++++++++++++++++++++++++++++++++
18 files changed, 644 insertions(+), 644 deletions(-)
diff --git a/river/Config.zig b/river/Config.zig
index 0e7d015..fd1b129 100644
--- a/river/Config.zig
+++ b/river/Config.zig
@@ -30,7 +30,7 @@ const Server = @import("Server.zig");
const Output = @import("Output.zig");
const Mapping = @import("Mapping.zig");
const Switch = @import("Switch.zig");
-const View = @import("View.zig");
+const Window = @import("Window.zig");
pub const Position = struct {
x: u31,
diff --git a/river/Cursor.zig b/river/Cursor.zig
index 10a3327..786fb94 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -41,7 +41,7 @@ const Root = @import("Root.zig");
const Seat = @import("Seat.zig");
const Tablet = @import("Tablet.zig");
const TabletTool = @import("TabletTool.zig");
-const View = @import("View.zig");
+const Window = @import("Window.zig");
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
const Mode = union(enum) {
@@ -60,9 +60,9 @@ const Mode = union(enum) {
sy: f64,
},
move: struct {
- view: *View,
+ window: *Window,
- /// View coordinates are stored as i32s as they are in logical pixels.
+ /// Window coordinates are stored as i32s as they are in logical pixels.
/// However, it is possible to move the cursor by a fraction of a
/// logical pixel and this happens in practice with low dpi, high
/// polling rate mice. Therefore we must accumulate the current
@@ -77,13 +77,13 @@ const Mode = union(enum) {
offset_y: i32,
},
resize: struct {
- view: *View,
+ window: *Window,
delta_x: f64 = 0,
delta_y: f64 = 0,
/// Total x/y movement of the pointer device since the start of the resize,
- /// clamped to the bounds of the resize as defined by the view min/max
+ /// clamped to the bounds of the resize as defined by the window min/max
/// dimensions and output dimensions.
/// This is not directly tied to the rendered cursor position.
x: i32 = 0,
@@ -116,7 +116,7 @@ mode: Mode = .passthrough,
/// Set to whatever the current mode is when a transaction is started.
/// This is necessary to handle termination of move/resize modes properly
/// since the termination is not complete until a transaction completes and
-/// View.resizeUpdatePosition() is called.
+/// Window.resizeUpdatePosition() is called.
inflight_mode: Mode = .passthrough,
seat: *Seat,
@@ -332,7 +332,7 @@ fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.P
_ = cursor.seat.wlr_seat.pointerNotifyButton(event.time_msec, event.button, event.state);
},
.move => {},
- .resize => |data| data.view.pending.resizing = false,
+ .resize => |data| data.window.pending.resizing = false,
}
cursor.mode = .passthrough;
@@ -354,7 +354,7 @@ fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.P
}
if (server.root.at(cursor.wlr_cursor.x, cursor.wlr_cursor.y)) |result| {
- if (result.data == .view and cursor.handlePointerMapping(event, result.data.view)) {
+ if (result.data == .window and cursor.handlePointerMapping(event, result.data.window)) {
// If a mapping is triggered don't send events to clients.
return;
}
@@ -381,8 +381,8 @@ fn handleButton(listener: *wl.Listener(*wlr.Pointer.event.Button), event: *wlr.P
/// Requires a call to Root.applyPending()
fn updateKeyboardFocus(cursor: Cursor, result: Root.AtResult) void {
switch (result.data) {
- .view => |view| {
- cursor.seat.focus(view);
+ .window => |window| {
+ cursor.seat.focus(window);
},
.layer_surface => |layer_surface| {
// If a keyboard inteactive layer surface has been clicked on,
@@ -626,7 +626,7 @@ fn handleTabletToolButton(
/// Handle the mapping for the passed button if any. Returns true if there
/// was a mapping and the button was handled.
-fn handlePointerMapping(cursor: *Cursor, event: *wlr.Pointer.event.Button, _: *View) bool {
+fn handlePointerMapping(cursor: *Cursor, event: *wlr.Pointer.event.Button, _: *Window) bool {
const wlr_keyboard = cursor.seat.wlr_seat.getKeyboard() orelse return false;
const modifiers = wlr_keyboard.getModifiers();
@@ -703,20 +703,20 @@ fn handleRequestSetCursor(
}
}
-pub fn startMove(cursor: *Cursor, view: *View) void {
+pub fn startMove(cursor: *Cursor, window: *Window) void {
if (cursor.constraint) |constraint| {
if (constraint.state == .active) constraint.deactivate();
}
const new_mode: Mode = .{ .move = .{
- .view = view,
- .offset_x = @as(i32, @intFromFloat(cursor.wlr_cursor.x)) - view.current.box.x,
- .offset_y = @as(i32, @intFromFloat(cursor.wlr_cursor.y)) - view.current.box.y,
+ .window = window,
+ .offset_x = @as(i32, @intFromFloat(cursor.wlr_cursor.x)) - window.current.box.x,
+ .offset_y = @as(i32, @intFromFloat(cursor.wlr_cursor.y)) - window.current.box.y,
} };
- cursor.enterMode(new_mode, view, "move");
+ cursor.enterMode(new_mode, window, "move");
}
-pub fn startResize(cursor: *Cursor, view: *View, proposed_edges: ?wlr.Edges) void {
+pub fn startResize(cursor: *Cursor, window: *Window, proposed_edges: ?wlr.Edges) void {
if (cursor.constraint) |constraint| {
if (constraint.state == .active) constraint.deactivate();
}
@@ -727,31 +727,31 @@ pub fn startResize(cursor: *Cursor, view: *View, proposed_edges: ?wlr.Edges) voi
break :blk edges;
}
}
- break :blk cursor.computeEdges(view);
+ break :blk cursor.computeEdges(window);
};
- const box = &view.current.box;
+ const box = &window.current.box;
const lx: i32 = @intFromFloat(cursor.wlr_cursor.x);
const ly: i32 = @intFromFloat(cursor.wlr_cursor.y);
const offset_x = if (edges.left) lx - box.x else box.x + box.width - lx;
const offset_y = if (edges.top) ly - box.y else box.y + box.height - ly;
- view.pending.resizing = true;
+ window.pending.resizing = true;
const new_mode: Mode = .{ .resize = .{
- .view = view,
+ .window = window,
.edges = edges,
.offset_x = offset_x,
.offset_y = offset_y,
.initial_width = @intCast(box.width),
.initial_height = @intCast(box.height),
} };
- cursor.enterMode(new_mode, view, wlr.Xcursor.getResizeName(edges));
+ cursor.enterMode(new_mode, window, wlr.Xcursor.getResizeName(edges));
}
-fn computeEdges(cursor: *const Cursor, view: *const View) wlr.Edges {
+fn computeEdges(cursor: *const Cursor, window: *const Window) wlr.Edges {
const min_handle_size = 20;
- const box = &view.current.box;
+ const box = &window.current.box;
const sx = @as(i32, @intFromFloat(cursor.wlr_cursor.x)) - box.x;
const sy = @as(i32, @intFromFloat(cursor.wlr_cursor.y)) - box.y;
@@ -783,7 +783,7 @@ fn computeEdges(cursor: *const Cursor, view: *const View) wlr.Edges {
}
}
-fn enterMode(cursor: *Cursor, mode: Mode, view: *View, xcursor_name: [*:0]const u8) void {
+fn enterMode(cursor: *Cursor, mode: Mode, window: *Window, xcursor_name: [*:0]const u8) void {
assert(cursor.mode == .passthrough or cursor.mode == .down);
assert(mode == .move or mode == .resize);
@@ -791,7 +791,7 @@ fn enterMode(cursor: *Cursor, mode: Mode, view: *View, xcursor_name: [*:0]const
cursor.mode = mode;
- cursor.seat.focus(view);
+ cursor.seat.focus(window);
cursor.seat.wlr_seat.pointerNotifyClearFocus();
cursor.setXcursor(xcursor_name);
@@ -851,7 +851,7 @@ fn processMotion(cursor: *Cursor, device: *wlr.InputDevice, time: u32, delta_x:
data.delta_x = dx - @trunc(dx);
data.delta_y = dy - @trunc(dy);
- data.view.pending.move(@intFromFloat(dx), @intFromFloat(dy));
+ data.window.pending.move(@intFromFloat(dx), @intFromFloat(dy));
server.root.applyPending();
},
@@ -865,16 +865,16 @@ fn processMotion(cursor: *Cursor, device: *wlr.InputDevice, time: u32, delta_x:
data.y += @intFromFloat(dy);
// Modify width/height of the pending box, taking constraints into account
- // The x/y coordinates of the view will be adjusted as needed in View.resizeCommit()
+ // The x/y coordinates of the window will be adjusted as needed in Window.resizeCommit()
// based on the dimensions actually committed by the client.
- const border_width = if (data.view.pending.ssd) server.config.border_width else 0;
+ const border_width = if (data.window.pending.ssd) server.config.border_width else 0;
// TODO
const output_width: i32 = 1920;
const output_height: i32 = 1080;
- const constraints = &data.view.constraints;
- const box = &data.view.pending.box;
+ const constraints = &data.window.constraints;
+ const box = &data.window.pending.box;
if (data.edges.left) {
const x2 = box.x + box.width;
@@ -911,8 +911,8 @@ fn processMotion(cursor: *Cursor, device: *wlr.InputDevice, time: u32, delta_x:
}
}
-/// Handle potential change in location of views on the output, as well as
-/// the target view of a cursor operation potentially being moved to a non-visible tag,
+/// Handle potential change in location of windows on the output, as well as
+/// the target window of a cursor operation potentially being moved to a non-visible tag,
/// becoming fullscreen, etc.
pub fn updateState(cursor: *Cursor) void {
if (cursor.constraint) |constraint| {
@@ -930,7 +930,7 @@ pub fn updateState(cursor: *Cursor) void {
// TODO: Leave down mode if the target surface is no longer visible.
.down => {},
.move, .resize => {
- // Moving and resizing of views is handled through the transaction system. Therefore,
+ // Moving and resizing of windows is handled through the transaction system. Therefore,
// we must inspect the inflight_mode instead if a move or a resize is in progress.
//
// The cases when a move/resize is being started or ended and e.g. mode is resize
@@ -942,17 +942,17 @@ pub fn updateState(cursor: *Cursor) void {
//
// In the second case, a move/resize has been terminated by the user but the
// transaction carrying out the final size/position change is still inflight.
- // Therefore, the user already expects the cursor to be free from the view and
+ // Therefore, the user already expects the cursor to be free from the window and
// we should not warp it back to the fixed offset of the move/resize.
switch (cursor.inflight_mode) {
.passthrough, .down => {},
inline .move, .resize => |data, mode| {
// These conditions are checked in Root.applyPending()
- assert(!data.view.current.fullscreen);
+ assert(!data.window.current.fullscreen);
- // Keep the cursor locked to the original offset from the edges of the view.
- const box = &data.view.current.box;
+ // Keep the cursor locked to the original offset from the edges of the window.
+ const box = &data.window.current.box;
const new_x: f64 = blk: {
if (mode == .move or data.edges.left) {
break :blk @floatFromInt(data.offset_x + box.x);
diff --git a/river/ForeignToplevelHandle.zig b/river/ForeignToplevelHandle.zig
index 97a1c90..f6e0555 100644
--- a/river/ForeignToplevelHandle.zig
+++ b/river/ForeignToplevelHandle.zig
@@ -23,7 +23,7 @@ const wl = @import("wayland").server.wl;
const server = &@import("main.zig").server;
-const View = @import("View.zig");
+const Window = @import("Window.zig");
const Seat = @import("Seat.zig");
wlr_handle: ?*wlr.ForeignToplevelHandleV1 = null,
@@ -36,7 +36,7 @@ foreign_close: wl.Listener(*wlr.ForeignToplevelHandleV1) =
wl.Listener(*wlr.ForeignToplevelHandleV1).init(handleForeignClose),
pub fn map(handle: *ForeignToplevelHandle) void {
- const view: *View = @fieldParentPtr("foreign_toplevel_handle", handle);
+ const window: *Window = @fieldParentPtr("foreign_toplevel_handle", handle);
assert(handle.wlr_handle == null);
@@ -49,8 +49,8 @@ pub fn map(handle: *ForeignToplevelHandle) void {
handle.wlr_handle.?.events.request_fullscreen.add(&handle.foreign_fullscreen);
handle.wlr_handle.?.events.request_close.add(&handle.foreign_close);
- if (view.getTitle()) |title| handle.wlr_handle.?.setTitle(title);
- if (view.getAppId()) |app_id| handle.wlr_handle.?.setAppId(app_id);
+ if (window.getTitle()) |title| handle.wlr_handle.?.setTitle(title);
+ if (window.getAppId()) |app_id| handle.wlr_handle.?.setAppId(app_id);
}
pub fn unmap(handle: *ForeignToplevelHandle) void {
@@ -65,27 +65,27 @@ pub fn unmap(handle: *ForeignToplevelHandle) void {
handle.wlr_handle = null;
}
-/// Must be called just before the view's inflight state is made current.
+/// Must be called just before the window's inflight state is made current.
pub fn update(handle: *ForeignToplevelHandle) void {
- const view: *View = @fieldParentPtr("foreign_toplevel_handle", handle);
+ const window: *Window = @fieldParentPtr("foreign_toplevel_handle", handle);
const wlr_handle = handle.wlr_handle orelse return;
- wlr_handle.setActivated(view.inflight.focus != 0);
- wlr_handle.setFullscreen(view.inflight.fullscreen);
+ wlr_handle.setActivated(window.inflight.focus != 0);
+ wlr_handle.setFullscreen(window.inflight.fullscreen);
}
-/// Only honors the request if the view is already visible on the seat's
+/// Only honors the request if the window is already visible on the seat's
/// currently focused output.
fn handleForeignActivate(
listener: *wl.Listener(*wlr.ForeignToplevelHandleV1.event.Activated),
event: *wlr.ForeignToplevelHandleV1.event.Activated,
) void {
const handle: *ForeignToplevelHandle = @fieldParentPtr("foreign_activate", listener);
- const view: *View = @fieldParentPtr("foreign_toplevel_handle", handle);
+ const window: *Window = @fieldParentPtr("foreign_toplevel_handle", handle);
const seat: *Seat = @ptrFromInt(event.seat.data);
- seat.focus(view);
+ seat.focus(window);
server.root.applyPending();
}
@@ -94,9 +94,9 @@ fn handleForeignFullscreen(
event: *wlr.ForeignToplevelHandleV1.event.Fullscreen,
) void {
const handle: *ForeignToplevelHandle = @fieldParentPtr("foreign_fullscreen", listener);
- const view: *View = @fieldParentPtr("foreign_toplevel_handle", handle);
+ const window: *Window = @fieldParentPtr("foreign_toplevel_handle", handle);
- view.pending.fullscreen = event.fullscreen;
+ window.pending.fullscreen = event.fullscreen;
server.root.applyPending();
}
@@ -105,7 +105,7 @@ fn handleForeignClose(
_: *wlr.ForeignToplevelHandleV1,
) void {
const handle: *ForeignToplevelHandle = @fieldParentPtr("foreign_close", listener);
- const view: *View = @fieldParentPtr("foreign_toplevel_handle", handle);
+ const window: *Window = @fieldParentPtr("foreign_toplevel_handle", handle);
- view.close();
+ window.close();
}
diff --git a/river/IdleInhibitManager.zig b/river/IdleInhibitManager.zig
index 73a0141..dfda3ab 100644
--- a/river/IdleInhibitManager.zig
+++ b/river/IdleInhibitManager.zig
@@ -25,7 +25,7 @@ const util = @import("util.zig");
const IdleInhibitor = @import("IdleInhibitor.zig");
const SceneNodeData = @import("SceneNodeData.zig");
-const View = @import("View.zig");
+const Window = @import("Window.zig");
wlr_manager: *wlr.IdleInhibitManagerV1,
new_idle_inhibitor: wl.Listener(*wlr.IdleInhibitorV1) =
@@ -53,7 +53,7 @@ pub fn checkActive(inhibit_manager: *IdleInhibitManager) void {
while (it) |node| : (it = node.next) {
const node_data = SceneNodeData.fromSurface(node.data.wlr_inhibitor.surface) orelse continue;
switch (node_data.data) {
- .view => {
+ .window => {
inhibited = true;
break;
},
diff --git a/river/InputPopup.zig b/river/InputPopup.zig
index 6503ddf..19abbf8 100644
--- a/river/InputPopup.zig
+++ b/river/InputPopup.zig
@@ -108,7 +108,7 @@ pub fn update(input_popup: *InputPopup) void {
const focused = SceneNodeData.fromSurface(focused_surface) orelse return;
const output = switch (focused.data) {
- .view => @panic("TODO"),
+ .window => @panic("TODO"),
.layer_surface => |layer_surface| layer_surface.output,
.lock_surface => |lock_surface| lock_surface.getOutput(),
// Xwayland doesn't use the text-input protocol
@@ -116,7 +116,7 @@ pub fn update(input_popup: *InputPopup) void {
};
const popup_tree = switch (focused.data) {
- .view => |view| view.popup_tree,
+ .window => |window| window.popup_tree,
.layer_surface => |layer_surface| layer_surface.popup_tree,
.lock_surface => |lock_surface| lock_surface.getOutput().layers.popups,
// Xwayland doesn't use the text-input protocol
diff --git a/river/Output.zig b/river/Output.zig
index d8994bd..7a07f6d 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -33,7 +33,7 @@ const util = @import("util.zig");
const LayerSurface = @import("LayerSurface.zig");
const LockSurface = @import("LockSurface.zig");
const SceneNodeData = @import("SceneNodeData.zig");
-const View = @import("View.zig");
+const Window = @import("Window.zig");
const Config = @import("Config.zig");
const log = std.log.scoped(.output);
@@ -47,7 +47,7 @@ all_link: wl.list.Link,
/// For Root.active_outputs
active_link: wl.list.Link,
-/// The area left for views and other layer surfaces after applying the
+/// The area left for windows and other layer surfaces after applying the
/// exclusive zones of exclusive layer surfaces.
/// TODO: this should be part of the output's State
usable_box: wlr.Box,
@@ -69,7 +69,7 @@ layers: struct {
wm: *wlr.SceneTree,
/// Top layer shell layer
top: *wlr.SceneTree,
- /// Fullscreen views
+ /// Fullscreen windows
fullscreen: *wlr.SceneTree,
/// Overlay layer shell layer
overlay: *wlr.SceneTree,
@@ -106,14 +106,14 @@ gamma_dirty: bool = false,
/// This state is immutable until all clients have replied and the transaction
/// is completed, at which point this inflight state is copied to current.
inflight: struct {
- /// The view to be made fullscreen, if any.
- fullscreen: ?*View = null,
+ /// The window to be made fullscreen, if any.
+ fullscreen: ?*Window = null,
} = .{},
/// The current state represented by the scene graph.
current: struct {
- /// The currently fullscreen view, if any.
- fullscreen: ?*View = null,
+ /// The currently fullscreen window, if any.
+ fullscreen: ?*Window = null,
} = .{},
destroy: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleDestroy),
@@ -236,7 +236,7 @@ pub fn layerSurfaceTree(output: Output, layer: zwlr.LayerShellV1.Layer) *wlr.Sce
}
/// Arrange all layer surfaces of this output and adjust the usable area.
-/// Will arrange views as well if the usable area changes.
+/// Will arrange windows as well if the usable area changes.
/// Requires a call to Root.applyPending()
pub fn arrangeLayers(output: *Output) void {
var full_box: wlr.Box = .{
diff --git a/river/PointerConstraint.zig b/river/PointerConstraint.zig
index a2c4d74..7caeb54 100644
--- a/river/PointerConstraint.zig
+++ b/river/PointerConstraint.zig
@@ -127,7 +127,7 @@ pub fn updateState(constraint: *PointerConstraint) void {
}
// It is possible for the cursor to end up outside of the constraint region despite the warp
- // if, for example, the a keybinding is used to resize the view.
+ // if, for example, the a keybinding is used to resize the window.
if (!constraint.wlr_constraint.region.containsPoint(@intFromFloat(sx), @intFromFloat(sy), null)) {
log.info("deactivating pointer constraint, cursor outside region despite warp", .{});
constraint.deactivate();
diff --git a/river/Root.zig b/river/Root.zig
index 22bd4f3..262233a 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -32,7 +32,7 @@ const LayerSurface = @import("LayerSurface.zig");
const LockSurface = @import("LockSurface.zig");
const Output = @import("Output.zig");
const SceneNodeData = @import("SceneNodeData.zig");
-const View = @import("View.zig");
+const Window = @import("Window.zig");
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
scene: *wlr.Scene,
@@ -54,29 +54,29 @@ layers: struct {
wm: struct {
pending: struct {
- render_list: wl.list.Head(View, .pending_render_list_link),
+ render_list: wl.list.Head(Window, .pending_render_list_link),
},
inflight: struct {
- render_list: wl.list.Head(View, .inflight_render_list_link),
+ render_list: wl.list.Head(Window, .inflight_render_list_link),
},
},
-/// This is kind of like an imaginary output where views start and end their life.
+/// This is kind of like an imaginary output where windows start and end their life.
hidden: struct {
/// This tree is always disabled.
tree: *wlr.SceneTree,
pending: struct {
- render_list: wl.list.Head(View, .pending_render_list_link),
+ render_list: wl.list.Head(Window, .pending_render_list_link),
},
inflight: struct {
- render_list: wl.list.Head(View, .inflight_render_list_link),
+ render_list: wl.list.Head(Window, .inflight_render_list_link),
},
},
-views: wl.list.Head(View, .link),
+windows: wl.list.Head(Window, .link),
new_output: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleNewOutput),
@@ -158,7 +158,7 @@ pub fn init(root: *Root) !void {
.render_list = undefined,
},
},
- .views = undefined,
+ .windows = undefined,
.output_layout = output_layout,
.all_outputs = undefined,
.active_outputs = undefined,
@@ -175,7 +175,7 @@ pub fn init(root: *Root) !void {
root.hidden.pending.render_list.init();
root.hidden.inflight.render_list.init();
- root.views.init();
+ root.windows.init();
root.all_outputs.init();
root.active_outputs.init();
@@ -250,7 +250,7 @@ fn handleNewOutput(_: *wl.Listener(*wlr.Output), wlr_output: *wlr.Output) void {
}
/// Remove the output from root.active_outputs and the output layout.
-/// Evacuate views if necessary.
+/// Evacuate windows if necessary.
pub fn deactivateOutput(root: *Root, output: *Output) void {
{
// If the output has already been removed, do nothing
@@ -307,7 +307,7 @@ pub fn activateOutput(root: *Root, output: *Output) void {
};
}
-/// Trigger asynchronous application of pending state for all outputs and views.
+/// Trigger asynchronous application of pending state for all outputs and windows.
/// Changes will not be applied to the scene graph until the layout generator
/// generates a new layout for all outputs and all affected clients ack a
/// configure and commit a new buffer.
@@ -330,9 +330,9 @@ pub fn applyPending(root: *Root) void {
{
var it = root.hidden.pending.render_list.iterator(.forward);
- while (it.next()) |view| {
- view.inflight_render_list_link.remove();
- root.hidden.inflight.render_list.append(view);
+ while (it.next()) |window| {
+ window.inflight_render_list_link.remove();
+ root.hidden.inflight.render_list.append(window);
}
}
@@ -344,10 +344,10 @@ pub fn applyPending(root: *Root) void {
switch (cursor.mode) {
.passthrough, .down => {},
inline .move, .resize => |data| {
- if (data.view.inflight.fullscreen) {
+ if (data.window.inflight.fullscreen) {
cursor.mode = .passthrough;
- data.view.pending.resizing = false;
- data.view.inflight.resizing = false;
+ data.window.pending.resizing = false;
+ data.window.inflight.resizing = false;
}
},
}
@@ -364,19 +364,19 @@ fn sendConfigures(root: *Root) void {
{
var it = root.wm.inflight.render_list.iterator(.forward);
- while (it.next()) |view| {
- assert(!view.inflight_transaction);
- view.inflight_transaction = true;
+ while (it.next()) |window| {
+ assert(!window.inflight_transaction);
+ window.inflight_transaction = true;
- // This can happen if a view is unmapped while a layout demand including it is inflight
- // If a view has been unmapped, don't send it a configure.
- if (!view.mapped) continue;
+ // This can happen if a window is unmapped while a layout demand including it is inflight
+ // If a window has been unmapped, don't send it a configure.
+ if (!window.mapped) continue;
- if (view.configure()) {
+ if (window.configure()) {
root.inflight_configures += 1;
- view.saveSurfaceTree();
- view.sendFrameDone();
+ window.saveSurfaceTree();
+ window.sendFrameDone();
}
}
}
@@ -424,19 +424,19 @@ fn commitTransaction(root: *Root) void {
{
var it = root.hidden.inflight.render_list.safeIterator(.forward);
- while (it.next()) |view| {
- view.tree.node.reparent(root.hidden.tree);
- view.popup_tree.node.reparent(root.hidden.tree);
+ while (it.next()) |window| {
+ window.tree.node.reparent(root.hidden.tree);
+ window.popup_tree.node.reparent(root.hidden.tree);
}
}
{
var it = root.wm.inflight.render_list.iterator(.forward);
- while (it.next()) |view| {
- view.commitTransaction();
+ while (it.next()) |window| {
+ window.commitTransaction();
- view.tree.node.setEnabled(true);
- view.popup_tree.node.setEnabled(true);
+ window.tree.node.setEnabled(true);
+ window.popup_tree.node.setEnabled(true);
}
}
@@ -446,11 +446,11 @@ fn commitTransaction(root: *Root) void {
}
{
- // This must be done after updating cursor state in case the view was the target of move/resize.
+ // This must be done after updating cursor state in case the window was the target of move/resize.
var it = root.hidden.inflight.render_list.safeIterator(.forward);
- while (it.next()) |view| {
- view.dropSavedSurfaceTree();
- if (view.destroying) view.destroy(.assert);
+ while (it.next()) |window| {
+ window.dropSavedSurfaceTree();
+ if (window.destroying) window.destroy(.assert);
}
}
diff --git a/river/SceneNodeData.zig b/river/SceneNodeData.zig
index 68d5923..ec28f45 100644
--- a/river/SceneNodeData.zig
+++ b/river/SceneNodeData.zig
@@ -25,11 +25,11 @@ const util = @import("util.zig");
const LayerSurface = @import("LayerSurface.zig");
const LockSurface = @import("LockSurface.zig");
const InputPopup = @import("InputPopup.zig");
-const View = @import("View.zig");
+const Window = @import("Window.zig");
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
pub const Data = union(enum) {
- view: *View,
+ window: *Window,
lock_surface: *LockSurface,
layer_surface: *LayerSurface,
override_redirect: if (build_options.xwayland) *XwaylandOverrideRedirect else noreturn,
diff --git a/river/Seat.zig b/river/Seat.zig
index 7289278..77864e5 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -40,13 +40,13 @@ const Output = @import("Output.zig");
const PointerConstraint = @import("PointerConstraint.zig");
const Switch = @import("Switch.zig");
const Tablet = @import("Tablet.zig");
-const View = @import("View.zig");
+const Window = @import("Window.zig");
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
const log = std.log.scoped(.seat);
pub const FocusTarget = union(enum) {
- view: *View,
+ window: *Window,
override_redirect: if (build_options.xwayland) *XwaylandOverrideRedirect else noreturn,
layer: *LayerSurface,
lock_surface: *LockSurface,
@@ -54,7 +54,7 @@ pub const FocusTarget = union(enum) {
pub fn surface(target: FocusTarget) ?*wlr.Surface {
return switch (target) {
- .view => |view| view.rootSurface(),
+ .window => |window| window.rootSurface(),
.override_redirect => |override_redirect| override_redirect.xwayland_surface.surface,
.layer => |layer| layer.wlr_layer_surface.surface,
.lock_surface => |lock_surface| lock_surface.wlr_lock_surface.surface,
@@ -127,16 +127,16 @@ pub fn deinit(seat: *Seat) void {
seat.request_set_primary_selection.link.remove();
}
-/// Set the current focus. If a visible view is passed it will be focused.
-/// If null is passed, the top view in the stack of the focused output will be focused.
+/// Set the current focus. If a visible window is passed it will be focused.
+/// If null is passed, the top window in the stack of the focused output will be focused.
/// Requires a call to Root.applyPending()
-pub fn focus(seat: *Seat, target: ?*View) void {
+pub fn focus(seat: *Seat, target: ?*Window) void {
// Views may not receive focus while locked.
if (server.lock_manager.state != .unlocked) return;
- // A layer surface with exclusive focus will prevent any view from gaining
+ // A layer surface with exclusive focus will prevent any window from gaining
// focus if it is on the top or overlay layer. Otherwise, only steal focus
- // from a focused layer surface if there is an explicit target view.
+ // from a focused layer surface if there is an explicit target window.
if (seat.focused == .layer) {
const wlr_layer_surface = seat.focused.layer.wlr_layer_surface;
assert(wlr_layer_surface.surface.mapped);
@@ -152,9 +152,9 @@ pub fn focus(seat: *Seat, target: ?*View) void {
}
}
- // Focus the target view or clear the focus if target is null
- if (target) |view| {
- seat.setFocusRaw(.{ .view = view });
+ // Focus the target window or clear the focus if target is null
+ if (target) |window| {
+ seat.setFocusRaw(.{ .window = window });
} else {
seat.setFocusRaw(.{ .none = {} });
}
@@ -162,7 +162,7 @@ pub fn focus(seat: *Seat, target: ?*View) void {
/// Switch focus to the target, handling unfocus and input inhibition
/// properly. This should only be called directly if dealing with layers or
-/// override redirect xwayland views.
+/// override redirect xwayland windows.
pub fn setFocusRaw(seat: *Seat, new_focus: FocusTarget) void {
// If the target is already focused, do nothing
if (std.meta.eql(new_focus, seat.focused)) return;
@@ -171,9 +171,9 @@ pub fn setFocusRaw(seat: *Seat, new_focus: FocusTarget) void {
// First clear the current focus
switch (seat.focused) {
- .view => |view| {
- view.pending.focus -= 1;
- view.destroyPopups();
+ .window => |window| {
+ window.pending.focus -= 1;
+ window.destroyPopups();
},
.layer => |layer_surface| {
layer_surface.destroyPopups();
@@ -183,10 +183,10 @@ pub fn setFocusRaw(seat: *Seat, new_focus: FocusTarget) void {
// Set the new focus
switch (new_focus) {
- .view => |target_view| {
+ .window => |target_window| {
assert(server.lock_manager.state != .locked);
- target_view.pending.focus += 1;
- target_view.pending.urgent = false;
+ target_window.pending.focus += 1;
+ target_window.pending.urgent = false;
},
.layer => assert(server.lock_manager.state != .locked),
.lock_surface => assert(server.lock_manager.state != .unlocked),
diff --git a/river/Server.zig b/river/Server.zig
index d46cb4f..459beae 100644
--- a/river/Server.zig
+++ b/river/Server.zig
@@ -39,7 +39,7 @@ const TabletTool = @import("TabletTool.zig");
const XdgDecoration = @import("XdgDecoration.zig");
const XdgToplevel = @import("XdgToplevel.zig");
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
-const XwaylandView = @import("XwaylandView.zig");
+const XwaylandWindow = @import("XwaylandWindow.zig");
const log = std.log.scoped(.server);
@@ -394,7 +394,7 @@ fn handleNewXwaylandSurface(_: *wl.Listener(*wlr.XwaylandSurface), xwayland_surf
return;
};
} else {
- _ = XwaylandView.create(xwayland_surface) catch {
+ _ = XwaylandWindow.create(xwayland_surface) catch {
log.err("out of memory", .{});
return;
};
@@ -409,8 +409,8 @@ fn handleRequestActivate(
const node_data = SceneNodeData.fromSurface(event.surface) orelse return;
switch (node_data.data) {
- .view => |view| if (view.pending.focus == 0) {
- view.pending.urgent = true;
+ .window => |window| if (window.pending.focus == 0) {
+ window.pending.urgent = true;
server.root.applyPending();
},
else => |tag| {
diff --git a/river/View.zig b/river/Window.zig
similarity index 59%
rename from river/View.zig
rename to river/Window.zig
index 27a6301..779c251 100644
--- a/river/View.zig
+++ b/river/Window.zig
@@ -14,7 +14,7 @@
// 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 View = @This();
+const Window = @This();
const build_options = @import("build_options");
const std = @import("std");
@@ -32,9 +32,9 @@ const Output = @import("Output.zig");
const SceneNodeData = @import("SceneNodeData.zig");
const Seat = @import("Seat.zig");
const XdgToplevel = @import("XdgToplevel.zig");
-const XwaylandView = @import("XwaylandView.zig");
+const XwaylandWindow = @import("XwaylandWindow.zig");
-const log = std.log.scoped(.view);
+const log = std.log.scoped(.window);
pub const Constraints = struct {
min_width: u31 = 1,
@@ -45,20 +45,20 @@ pub const Constraints = struct {
const Impl = union(enum) {
toplevel: XdgToplevel,
- xwayland_view: if (build_options.xwayland) XwaylandView else noreturn,
+ xwayland_window: if (build_options.xwayland) XwaylandWindow else noreturn,
/// This state is assigned during destruction after the xdg toplevel
/// has been destroyed but while the transaction system is still rendering
- /// saved surfaces of the view.
+ /// saved surfaces of the window.
/// The toplevel could simply be set to undefined instead, but using a
/// tag like this gives us better safety checks.
none,
};
pub const State = struct {
- /// The output-relative coordinates of the view and dimensions requested by river.
+ /// The output-relative coordinates of the window and dimensions requested by river.
box: wlr.Box = .{ .x = 0, .y = 0, .width = 0, .height = 0 },
- /// Number of seats currently focusing the view
+ /// Number of seats currently focusing the window
focus: u32 = 0,
fullscreen: bool = false,
@@ -102,10 +102,10 @@ pub const State = struct {
}
};
-/// The implementation of this view
+/// The implementation of this window
impl: Impl,
-/// Link for Root.views
+/// Link for Root.windows
link: wl.list.Link,
tree: *wlr.SceneTree,
@@ -115,17 +115,17 @@ saved_surface_tree: *wlr.SceneTree,
borders: [4]*wlr.SceneRect,
popup_tree: *wlr.SceneTree,
-/// Bounds on the width/height of the view, set by the toplevel/xwayland_view implementation.
+/// Bounds on the width/height of the window, set by the toplevel/xwayland_window implementation.
constraints: Constraints = .{},
mapped: bool = false,
-/// This is true if the View is involved in the currently inflight transaction.
+/// This is true if the Window is involved in the currently inflight transaction.
inflight_transaction: bool = false,
-/// This indicates that the view should be destroyed when the current
-/// transaction completes. See View.destroy()
+/// This indicates that the window should be destroyed when the current
+/// transaction completes. See Window.destroy()
destroying: bool = false,
-/// The state of the view that is directly acted upon/modified through user input.
+/// The state of the window that is directly acted upon/modified through user input.
///
/// Pending state will be copied to the inflight state and communicated to clients
/// to be applied as a single atomic transaction across all clients as soon as any
@@ -147,11 +147,11 @@ current: State = .{},
foreign_toplevel_handle: ForeignToplevelHandle = .{},
-pub fn create(impl: Impl) error{OutOfMemory}!*View {
+pub fn create(impl: Impl) error{OutOfMemory}!*Window {
assert(impl != .none);
- const view = try util.gpa.create(View);
- errdefer util.gpa.destroy(view);
+ const window = try util.gpa.create(Window);
+ errdefer util.gpa.destroy(window);
const tree = try server.root.hidden.tree.createSceneTree();
errdefer tree.node.destroy();
@@ -159,7 +159,7 @@ pub fn create(impl: Impl) error{OutOfMemory}!*View {
const popup_tree = try server.root.hidden.tree.createSceneTree();
errdefer popup_tree.node.destroy();
- view.* = .{
+ window.* = .{
.impl = impl,
.link = undefined,
.tree = tree,
@@ -177,41 +177,41 @@ pub fn create(impl: Impl) error{OutOfMemory}!*View {
.inflight_render_list_link = undefined,
};
- server.root.views.prepend(view);
- server.root.hidden.pending.render_list.prepend(view);
- server.root.hidden.inflight.render_list.prepend(view);
+ server.root.windows.prepend(window);
+ server.root.hidden.pending.render_list.prepend(window);
+ server.root.hidden.inflight.render_list.prepend(window);
- view.tree.node.setEnabled(false);
- view.popup_tree.node.setEnabled(false);
- view.saved_surface_tree.node.setEnabled(false);
+ window.tree.node.setEnabled(false);
+ window.popup_tree.node.setEnabled(false);
+ window.saved_surface_tree.node.setEnabled(false);
- try SceneNodeData.attach(&view.tree.node, .{ .view = view });
- try SceneNodeData.attach(&view.popup_tree.node, .{ .view = view });
+ try SceneNodeData.attach(&window.tree.node, .{ .window = window });
+ try SceneNodeData.attach(&window.popup_tree.node, .{ .window = window });
- return view;
+ return window;
}
-/// If saved buffers of the view are currently in use by a transaction,
-/// mark this view for destruction when the transaction completes. Otherwise
+/// If saved buffers of the window are currently in use by a transaction,
+/// mark this window for destruction when the transaction completes. Otherwise
/// destroy immediately.
-pub fn destroy(view: *View, when: enum { lazy, assert }) void {
- assert(view.impl == .none);
- assert(!view.mapped);
+pub fn destroy(window: *Window, when: enum { lazy, assert }) void {
+ assert(window.impl == .none);
+ assert(!window.mapped);
- view.destroying = true;
+ window.destroying = true;
- // If there are still saved buffers, then this view needs to be kept
+ // If there are still saved buffers, then this window needs to be kept
// around until the current transaction completes. This function will be
// called again in Root.commitTransaction()
- if (!view.saved_surface_tree.node.enabled) {
- view.tree.node.destroy();
- view.popup_tree.node.destroy();
+ if (!window.saved_surface_tree.node.enabled) {
+ window.tree.node.destroy();
+ window.popup_tree.node.destroy();
- view.link.remove();
- view.pending_render_list_link.remove();
- view.inflight_render_list_link.remove();
+ window.link.remove();
+ window.pending_render_list_link.remove();
+ window.inflight_render_list_link.remove();
- util.gpa.destroy(view);
+ util.gpa.destroy(window);
} else {
switch (when) {
.lazy => {},
@@ -220,47 +220,47 @@ pub fn destroy(view: *View, when: enum { lazy, assert }) void {
}
}
-/// The change in x/y position of the view during resize cannot be determined
+/// The change in x/y position of the window during resize cannot be determined
/// until the size of the buffer actually committed is known. Clients are permitted
/// by the protocol to take a size smaller than that requested by the compositor in
/// order to maintain an aspect ratio or similar (mpv does this for example).
-pub fn resizeUpdatePosition(view: *View, width: i32, height: i32) void {
- assert(view.inflight.resizing);
+pub fn resizeUpdatePosition(window: *Window, width: i32, height: i32) void {
+ assert(window.inflight.resizing);
const data = blk: {
var it = server.input_manager.seats.first;
while (it) |node| : (it = node.next) {
const cursor = &node.data.cursor;
- if (cursor.inflight_mode == .resize and cursor.inflight_mode.resize.view == view) {
+ if (cursor.inflight_mode == .resize and cursor.inflight_mode.resize.window == window) {
break :blk cursor.inflight_mode.resize;
}
} else {
- // The view resizing state should never be set when the view is
+ // The window resizing state should never be set when the window is
// not the target of an interactive resize.
unreachable;
}
};
if (data.edges.left) {
- view.inflight.box.x += view.current.box.width - width;
- view.pending.box.x = view.inflight.box.x;
+ window.inflight.box.x += window.current.box.width - width;
+ window.pending.box.x = window.inflight.box.x;
}
if (data.edges.top) {
- view.inflight.box.y += view.current.box.height - height;
- view.pending.box.y = view.inflight.box.y;
+ window.inflight.box.y += window.current.box.height - height;
+ window.pending.box.y = window.inflight.box.y;
}
}
-pub fn commitTransaction(view: *View) void {
- assert(view.inflight_transaction);
- view.inflight_transaction = false;
+pub fn commitTransaction(window: *Window) void {
+ assert(window.inflight_transaction);
+ window.inflight_transaction = false;
- view.foreign_toplevel_handle.update();
+ window.foreign_toplevel_handle.update();
- view.dropSavedSurfaceTree();
+ window.dropSavedSurfaceTree();
- switch (view.impl) {
+ switch (window.impl) {
.toplevel => |*toplevel| {
switch (toplevel.configure_state) {
.inflight, .acked => {
@@ -288,50 +288,50 @@ pub fn commitTransaction(view: *View) void {
// If we did not use the current geometry of the toplevel at this point
// we would be rendering the SSD border at initial size X but the surface
// would be rendered at size Y.
- if (view.inflight.resizing) {
- view.resizeUpdatePosition(toplevel.geometry.width, toplevel.geometry.height);
+ if (window.inflight.resizing) {
+ window.resizeUpdatePosition(toplevel.geometry.width, toplevel.geometry.height);
}
- view.current = view.inflight;
- view.current.box.width = toplevel.geometry.width;
- view.current.box.height = toplevel.geometry.height;
+ window.current = window.inflight;
+ window.current.box.width = toplevel.geometry.width;
+ window.current.box.height = toplevel.geometry.height;
},
.idle, .committed => {
toplevel.configure_state = .idle;
- view.current = view.inflight;
+ window.current = window.inflight;
},
.timed_out, .timed_out_acked => unreachable,
}
},
- .xwayland_view => |xwayland_view| {
- if (view.inflight.resizing) {
- view.resizeUpdatePosition(
- xwayland_view.xwayland_surface.width,
- xwayland_view.xwayland_surface.height,
+ .xwayland_window => |xwayland_window| {
+ if (window.inflight.resizing) {
+ window.resizeUpdatePosition(
+ xwayland_window.xwayland_surface.width,
+ xwayland_window.xwayland_surface.height,
);
}
- view.inflight.box.width = xwayland_view.xwayland_surface.width;
- view.inflight.box.height = xwayland_view.xwayland_surface.height;
- view.pending.box.width = xwayland_view.xwayland_surface.width;
- view.pending.box.height = xwayland_view.xwayland_surface.height;
+ window.inflight.box.width = xwayland_window.xwayland_surface.width;
+ window.inflight.box.height = xwayland_window.xwayland_surface.height;
+ window.pending.box.width = xwayland_window.xwayland_surface.width;
+ window.pending.box.height = xwayland_window.xwayland_surface.height;
- view.current = view.inflight;
+ window.current = window.inflight;
},
// This may seem pointless at first glance, but is in fact necessary
// to prevent an assertion failure in Root.commitTransaction() as that
// function assumes that the inflight tags/output will be applied by
- // View.commitTransaction() even for views being destroyed.
- .none => view.current = view.inflight,
+ // Window.commitTransaction() even for windows being destroyed.
+ .none => window.current = window.inflight,
}
- view.updateSceneState();
+ window.updateSceneState();
}
-pub fn updateSceneState(view: *View) void {
- const box = &view.current.box;
- view.tree.node.setPosition(box.x, box.y);
- view.popup_tree.node.setPosition(box.x, box.y);
+pub fn updateSceneState(window: *Window) void {
+ const box = &window.current.box;
+ window.tree.node.setPosition(box.x, box.y);
+ window.popup_tree.node.setPosition(box.x, box.y);
{
const config = &server.config;
@@ -367,8 +367,8 @@ pub fn updateSceneState(view: *View) void {
},
};
- for (&view.borders, &border_boxes) |border, *border_box| {
- border.node.setEnabled(view.current.ssd and !view.current.fullscreen);
+ for (&window.borders, &border_boxes) |border, *border_box| {
+ border.node.setEnabled(window.current.ssd and !window.current.fullscreen);
border.node.setPosition(border_box.x, border_box.y);
border.setSize(border_box.width, border_box.height);
border.setColor(border_color);
@@ -377,52 +377,52 @@ pub fn updateSceneState(view: *View) void {
}
/// Returns true if the configure should be waited for by the transaction system.
-pub fn configure(view: *View) bool {
- assert(view.mapped and !view.destroying);
- switch (view.impl) {
+pub fn configure(window: *Window) bool {
+ assert(window.mapped and !window.destroying);
+ switch (window.impl) {
.toplevel => |*toplevel| return toplevel.configure(),
- .xwayland_view => |*xwayland_view| return xwayland_view.configure(),
+ .xwayland_window => |*xwayland_window| return xwayland_window.configure(),
.none => unreachable,
}
}
-/// Returns null if the view is currently being destroyed and no longer has
+/// Returns null if the window is currently being destroyed and no longer has
/// an associated surface.
-/// May also return null for Xwayland views that are not currently mapped.
-pub fn rootSurface(view: View) ?*wlr.Surface {
- return switch (view.impl) {
+/// May also return null for Xwayland windows that are not currently mapped.
+pub fn rootSurface(window: Window) ?*wlr.Surface {
+ return switch (window.impl) {
.toplevel => |toplevel| toplevel.wlr_toplevel.base.surface,
- .xwayland_view => |xwayland_view| xwayland_view.xwayland_surface.surface,
+ .xwayland_window => |xwayland_window| xwayland_window.xwayland_surface.surface,
.none => null,
};
}
-pub fn sendFrameDone(view: View) void {
- assert(view.mapped and !view.destroying);
+pub fn sendFrameDone(window: Window) void {
+ assert(window.mapped and !window.destroying);
var now: posix.timespec = undefined;
posix.clock_gettime(posix.CLOCK.MONOTONIC, &now) catch @panic("CLOCK_MONOTONIC not supported");
- view.rootSurface().?.sendFrameDone(&now);
+ window.rootSurface().?.sendFrameDone(&now);
}
-pub fn dropSavedSurfaceTree(view: *View) void {
- if (!view.saved_surface_tree.node.enabled) return;
+pub fn dropSavedSurfaceTree(window: *Window) void {
+ if (!window.saved_surface_tree.node.enabled) return;
- var it = view.saved_surface_tree.children.safeIterator(.forward);
+ var it = window.saved_surface_tree.children.safeIterator(.forward);
while (it.next()) |node| node.destroy();
- view.saved_surface_tree.node.setEnabled(false);
- view.surface_tree.node.setEnabled(true);
+ window.saved_surface_tree.node.setEnabled(false);
+ window.surface_tree.node.setEnabled(true);
}
-pub fn saveSurfaceTree(view: *View) void {
- assert(!view.saved_surface_tree.node.enabled);
- assert(view.saved_surface_tree.children.empty());
+pub fn saveSurfaceTree(window: *Window) void {
+ assert(!window.saved_surface_tree.node.enabled);
+ assert(window.saved_surface_tree.children.empty());
- view.surface_tree.node.forEachBuffer(*wlr.SceneTree, saveSurfaceTreeIter, view.saved_surface_tree);
+ window.surface_tree.node.forEachBuffer(*wlr.SceneTree, saveSurfaceTreeIter, window.saved_surface_tree);
- view.surface_tree.node.setEnabled(false);
- view.saved_surface_tree.node.setEnabled(true);
+ window.surface_tree.node.setEnabled(false);
+ window.saved_surface_tree.node.setEnabled(true);
}
fn saveSurfaceTreeIter(
@@ -441,87 +441,87 @@ fn saveSurfaceTreeIter(
saved.setTransform(buffer.transform);
}
-pub fn close(view: View) void {
- switch (view.impl) {
+pub fn close(window: Window) void {
+ switch (window.impl) {
.toplevel => |toplevel| toplevel.wlr_toplevel.sendClose(),
- .xwayland_view => |xwayland_view| xwayland_view.xwayland_surface.close(),
+ .xwayland_window => |xwayland_window| xwayland_window.xwayland_surface.close(),
.none => {},
}
}
-pub fn destroyPopups(view: View) void {
- switch (view.impl) {
+pub fn destroyPopups(window: Window) void {
+ switch (window.impl) {
.toplevel => |toplevel| toplevel.destroyPopups(),
- .xwayland_view, .none => {},
+ .xwayland_window, .none => {},
}
}
-/// Return the current title of the view if any.
-pub fn getTitle(view: View) ?[*:0]const u8 {
- assert(!view.destroying);
- return switch (view.impl) {
+/// Return the current title of the window if any.
+pub fn getTitle(window: Window) ?[*:0]const u8 {
+ assert(!window.destroying);
+ return switch (window.impl) {
.toplevel => |toplevel| toplevel.wlr_toplevel.title,
- .xwayland_view => |xwayland_view| xwayland_view.xwayland_surface.title,
+ .xwayland_window => |xwayland_window| xwayland_window.xwayland_surface.title,
.none => unreachable,
};
}
-/// Return the current app_id of the view if any.
-pub fn getAppId(view: View) ?[*:0]const u8 {
- assert(!view.destroying);
- return switch (view.impl) {
+/// Return the current app_id of the window if any.
+pub fn getAppId(window: Window) ?[*:0]const u8 {
+ assert(!window.destroying);
+ return switch (window.impl) {
.toplevel => |toplevel| toplevel.wlr_toplevel.app_id,
// X11 clients don't have an app_id but the class serves a similar role.
- .xwayland_view => |xwayland_view| xwayland_view.xwayland_surface.class,
+ .xwayland_window => |xwayland_window| xwayland_window.xwayland_surface.class,
.none => unreachable,
};
}
-/// Clamp the width/height of the box to the constraints of the view
-pub fn applyConstraints(view: *View, box: *wlr.Box) void {
- box.width = math.clamp(box.width, view.constraints.min_width, view.constraints.max_width);
- box.height = math.clamp(box.height, view.constraints.min_height, view.constraints.max_height);
+/// Clamp the width/height of the box to the constraints of the window
+pub fn applyConstraints(window: *Window, box: *wlr.Box) void {
+ box.width = math.clamp(box.width, window.constraints.min_width, window.constraints.max_width);
+ box.height = math.clamp(box.height, window.constraints.min_height, window.constraints.max_height);
}
/// Called by the impl when the surface is ready to be displayed
-pub fn map(view: *View) !void {
- log.debug("view '{?s}' mapped", .{view.getTitle()});
+pub fn map(window: *Window) !void {
+ log.debug("window '{?s}' mapped", .{window.getTitle()});
- assert(!view.mapped and !view.destroying);
- view.mapped = true;
+ assert(!window.mapped and !window.destroying);
+ window.mapped = true;
- view.foreign_toplevel_handle.map();
+ window.foreign_toplevel_handle.map();
server.root.applyPending();
}
/// Called by the impl when the surface will no longer be displayed
-pub fn unmap(view: *View) void {
- log.debug("view '{?s}' unmapped", .{view.getTitle()});
+pub fn unmap(window: *Window) void {
+ log.debug("window '{?s}' unmapped", .{window.getTitle()});
- if (!view.saved_surface_tree.node.enabled) view.saveSurfaceTree();
+ if (!window.saved_surface_tree.node.enabled) window.saveSurfaceTree();
{
- view.pending_render_list_link.remove();
- server.root.hidden.pending.render_list.prepend(view);
+ window.pending_render_list_link.remove();
+ server.root.hidden.pending.render_list.prepend(window);
}
- assert(view.mapped and !view.destroying);
- view.mapped = false;
+ assert(window.mapped and !window.destroying);
+ window.mapped = false;
- view.foreign_toplevel_handle.unmap();
+ window.foreign_toplevel_handle.unmap();
server.root.applyPending();
}
-pub fn notifyTitle(view: *const View) void {
- if (view.foreign_toplevel_handle.wlr_handle) |wlr_handle| {
- if (view.getTitle()) |title| wlr_handle.setTitle(title);
+pub fn notifyTitle(window: *const Window) void {
+ if (window.foreign_toplevel_handle.wlr_handle) |wlr_handle| {
+ if (window.getTitle()) |title| wlr_handle.setTitle(title);
}
}
-pub fn notifyAppId(view: View) void {
- if (view.foreign_toplevel_handle.wlr_handle) |wlr_handle| {
- if (view.getAppId()) |app_id| wlr_handle.setAppId(app_id);
+pub fn notifyAppId(window: Window) void {
+ if (window.foreign_toplevel_handle.wlr_handle) |wlr_handle| {
+ if (window.getAppId()) |app_id| wlr_handle.setAppId(app_id);
}
}
diff --git a/river/XdgDecoration.zig b/river/XdgDecoration.zig
index eda0664..6545eb9 100644
--- a/river/XdgDecoration.zig
+++ b/river/XdgDecoration.zig
@@ -73,12 +73,12 @@ fn handleRequestMode(
const decoration: *XdgDecoration = @fieldParentPtr("request_mode", listener);
const toplevel: *XdgToplevel = @ptrFromInt(decoration.wlr_decoration.toplevel.base.data);
- const view = toplevel.view;
+ const window = toplevel.window;
const ssd = true;
- if (view.pending.ssd != ssd) {
- view.pending.ssd = ssd;
+ if (window.pending.ssd != ssd) {
+ window.pending.ssd = ssd;
server.root.applyPending();
}
}
diff --git a/river/XdgPopup.zig b/river/XdgPopup.zig
index 911f8d4..b14e1e5 100644
--- a/river/XdgPopup.zig
+++ b/river/XdgPopup.zig
@@ -29,7 +29,7 @@ const SceneNodeData = @import("SceneNodeData.zig");
const log = std.log.scoped(.xdg_popup);
wlr_xdg_popup: *wlr.XdgPopup,
-/// The root of the surface tree, i.e. the View or LayerSurface popup_tree.
+/// The root of the surface tree, i.e. the Window or LayerSurface popup_tree.
root: *wlr.SceneTree,
tree: *wlr.SceneTree,
@@ -96,7 +96,7 @@ fn handleReposition(listener: *wl.Listener(void)) void {
const xdg_popup: *XdgPopup = @fieldParentPtr("reposition", listener);
const output = switch (SceneNodeData.fromNode(&xdg_popup.root.node).?.data) {
- .view => |_| @panic("TODO"),
+ .window => |_| @panic("TODO"),
.layer_surface => |layer_surface| layer_surface.output,
else => unreachable,
};
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 481659a..2c40642 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -28,13 +28,13 @@ const util = @import("util.zig");
const Output = @import("Output.zig");
const Seat = @import("Seat.zig");
const XdgPopup = @import("XdgPopup.zig");
-const View = @import("View.zig");
+const Window = @import("Window.zig");
const XdgDecoration = @import("XdgDecoration.zig");
const log = std.log.scoped(.xdg_shell);
/// TODO(zig): get rid of this and use @fieldParentPtr(), https://github.com/ziglang/zig/issues/6611
-view: *View,
+window: *Window,
wlr_toplevel: *wlr.XdgToplevel,
@@ -58,14 +58,14 @@ configure_state: union(enum) {
timed_out_acked,
} = .idle,
-// Listeners that are always active over the view's lifetime
+// Listeners that are always active over the window's lifetime
destroy: wl.Listener(void) = wl.Listener(void).init(handleDestroy),
map: wl.Listener(void) = wl.Listener(void).init(handleMap),
unmap: wl.Listener(void) = wl.Listener(void).init(handleUnmap),
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
new_popup: wl.Listener(*wlr.XdgPopup) = wl.Listener(*wlr.XdgPopup).init(handleNewPopup),
-// Listeners that are only active while the view is mapped
+// Listeners that are only active while the window is mapped
ack_configure: wl.Listener(*wlr.XdgSurface.Configure) =
wl.Listener(*wlr.XdgSurface.Configure).init(handleAckConfigure),
request_fullscreen: wl.Listener(void) = wl.Listener(void).init(handleRequestFullscreen),
@@ -77,13 +77,13 @@ set_title: wl.Listener(void) = wl.Listener(void).init(handleSetTitle),
set_app_id: wl.Listener(void) = wl.Listener(void).init(handleSetAppId),
pub fn create(wlr_toplevel: *wlr.XdgToplevel) error{OutOfMemory}!void {
- const view = try View.create(.{ .toplevel = .{
- .view = undefined,
+ const window = try Window.create(.{ .toplevel = .{
+ .window = undefined,
.wlr_toplevel = wlr_toplevel,
} });
- errdefer view.destroy(.assert);
+ errdefer window.destroy(.assert);
- const toplevel = &view.impl.toplevel;
+ const toplevel = &window.impl.toplevel;
// This listener must be added before the scene xdg surface is created.
// Otherwise, the scene surface nodes will already be disabled by the unmap
@@ -96,12 +96,12 @@ pub fn create(wlr_toplevel: *wlr.XdgToplevel) error{OutOfMemory}!void {
wlr_toplevel.base.surface.events.unmap.add(&toplevel.unmap);
errdefer toplevel.unmap.link.remove();
- _ = try view.surface_tree.createSceneXdgSurface(wlr_toplevel.base);
+ _ = try window.surface_tree.createSceneXdgSurface(wlr_toplevel.base);
- toplevel.view = view;
+ toplevel.window = window;
wlr_toplevel.base.data = @intFromPtr(toplevel);
- wlr_toplevel.base.surface.data = @intFromPtr(&view.tree.node);
+ wlr_toplevel.base.surface.data = @intFromPtr(&window.tree.node);
// Add listeners that are active over the toplevel's entire lifetime
wlr_toplevel.events.destroy.add(&toplevel.destroy);
@@ -110,7 +110,7 @@ pub fn create(wlr_toplevel: *wlr.XdgToplevel) error{OutOfMemory}!void {
wlr_toplevel.base.events.new_popup.add(&toplevel.new_popup);
}
-/// Send a configure event, applying the inflight state of the view.
+/// Send a configure event, applying the inflight state of the window.
pub fn configure(toplevel: *XdgToplevel) bool {
switch (toplevel.configure_state) {
.idle, .timed_out, .timed_out_acked => {},
@@ -122,12 +122,12 @@ pub fn configure(toplevel: *XdgToplevel) bool {
.timed_out, .timed_out_acked, .committed => unreachable,
};
- const inflight = &toplevel.view.inflight;
- const current = &toplevel.view.current;
+ const inflight = &toplevel.window.inflight;
+ const current = &toplevel.window.current;
- // We avoid a special case for newly mapped views which we have not yet
+ // We avoid a special case for newly mapped windows which we have not yet
// configured by setting the current width/height to the initial width/height
- // of the view in handleMap().
+ // of the window in handleMap().
if (inflight.box.width == current.box.width and
inflight.box.height == current.box.height and
(inflight.focus != 0) == (current.focus != 0) and
@@ -173,7 +173,7 @@ pub fn configure(toplevel: *XdgToplevel) bool {
// from getting out of sync in the case where a client has resized ittoplevel.
const configure_serial = wlr_toplevel.setSize(inflight.box.width, inflight.box.height);
- // Only track configures with the transaction system if they affect the dimensions of the view.
+ // Only track configures with the transaction system if they affect the dimensions of the window.
// If the configure state is not idle this means we are currently tracking a timed out
// configure from a previous transaction and should instead track the newly sent configure.
if (inflight.box.width == current.box.width and
@@ -205,7 +205,7 @@ fn handleDestroy(listener: *wl.Listener(void)) void {
}
assert(toplevel.decoration == null);
- // Remove listeners that are active for the entire lifetime of the view
+ // Remove listeners that are active for the entire lifetime of the window
toplevel.destroy.link.remove();
toplevel.map.link.remove();
toplevel.unmap.link.remove();
@@ -215,14 +215,14 @@ fn handleDestroy(listener: *wl.Listener(void)) void {
// The wlr_surface may outlive the wlr_xdg_toplevel so we must clean up the user data.
toplevel.wlr_toplevel.base.surface.data = 0;
- const view = toplevel.view;
- view.impl = .none;
- view.destroy(.lazy);
+ const window = toplevel.window;
+ window.impl = .none;
+ window.destroy(.lazy);
}
fn handleMap(listener: *wl.Listener(void)) void {
const toplevel: *XdgToplevel = @fieldParentPtr("map", listener);
- const view = toplevel.view;
+ const window = toplevel.window;
// Add listeners that are only active while mapped
toplevel.wlr_toplevel.base.events.ack_configure.add(&toplevel.ack_configure);
@@ -234,18 +234,18 @@ fn handleMap(listener: *wl.Listener(void)) void {
toplevel.wlr_toplevel.base.getGeometry(&toplevel.geometry);
- view.pending.box = .{
+ window.pending.box = .{
.x = 0,
.y = 0,
.width = toplevel.geometry.width,
.height = toplevel.geometry.height,
};
- view.inflight.box = view.pending.box;
- view.current.box = view.pending.box;
+ window.inflight.box = window.pending.box;
+ window.current.box = window.pending.box;
- toplevel.view.pending.fullscreen = toplevel.wlr_toplevel.requested.fullscreen;
+ toplevel.window.pending.fullscreen = toplevel.wlr_toplevel.requested.fullscreen;
- view.map() catch {
+ window.map() catch {
log.err("out of memory", .{});
toplevel.wlr_toplevel.resource.getClient().postNoMemory();
};
@@ -263,13 +263,13 @@ fn handleUnmap(listener: *wl.Listener(void)) void {
toplevel.set_title.link.remove();
toplevel.set_app_id.link.remove();
- toplevel.view.unmap();
+ toplevel.window.unmap();
}
fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_xdg_popup: *wlr.XdgPopup) void {
const toplevel: *XdgToplevel = @fieldParentPtr("new_popup", listener);
- XdgPopup.create(wlr_xdg_popup, toplevel.view.popup_tree, toplevel.view.popup_tree) catch {
+ XdgPopup.create(wlr_xdg_popup, toplevel.window.popup_tree, toplevel.window.popup_tree) catch {
wlr_xdg_popup.resource.postNoMemory();
return;
};
@@ -293,7 +293,7 @@ fn handleAckConfigure(
fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
const toplevel: *XdgToplevel = @fieldParentPtr("commit", listener);
- const view = toplevel.view;
+ const window = toplevel.window;
if (toplevel.wlr_toplevel.base.initial_commit) {
_ = toplevel.wlr_toplevel.setWmCapabilities(.{ .fullscreen = true });
@@ -301,19 +301,19 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
if (toplevel.decoration) |decoration| {
const ssd = true;
_ = decoration.wlr_decoration.setMode(if (ssd) .server_side else .client_side);
- toplevel.view.pending.ssd = ssd;
+ toplevel.window.pending.ssd = ssd;
}
return;
}
- if (!view.mapped) {
+ if (!window.mapped) {
return;
}
{
const state = &toplevel.wlr_toplevel.current;
- view.constraints = .{
+ window.constraints = .{
.min_width = @max(state.min_width, 1),
.max_width = if (state.max_width > 0) @intCast(state.max_width) else math.maxInt(u31),
.min_height = @max(state.min_height, 1),
@@ -335,7 +335,7 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
.{ old_geometry.width, old_geometry.height, toplevel.geometry.width, toplevel.geometry.height },
);
// TODO check tiled state
- if (!view.current.fullscreen) {
+ if (!window.current.fullscreen) {
// It seems that a disappointingly high number of clients have a buggy
// response to configure events. They ack the configure immediately but then
// proceed to make one or more wl_surface.commit requests with the old size
@@ -344,39 +344,39 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
// interest of best serving river's users we will fix up their size here after
// logging a shame message.
log.err("client with app-id '{s}' is buggy and initiated size change while tiled or fullscreen, shame on it", .{
- view.getAppId() orelse "",
+ window.getAppId() orelse "",
});
}
- view.inflight.box.width = toplevel.geometry.width;
- view.inflight.box.height = toplevel.geometry.height;
- view.pending.box.width = toplevel.geometry.width;
- view.pending.box.height = toplevel.geometry.height;
- view.current = view.inflight;
- view.updateSceneState();
+ window.inflight.box.width = toplevel.geometry.width;
+ window.inflight.box.height = toplevel.geometry.height;
+ window.pending.box.width = toplevel.geometry.width;
+ window.pending.box.height = toplevel.geometry.height;
+ window.current = window.inflight;
+ window.updateSceneState();
} else if (old_geometry.x != toplevel.geometry.x or
old_geometry.y != toplevel.geometry.y)
{
// We need to update the surface clip box to reflect the geometry change.
- view.updateSceneState();
+ window.updateSceneState();
}
},
// If the client has not yet acked our configure, we need to send a
// frame done event so that it commits another buffer. These
// buffers won't be rendered since we are still rendering our
// stashed buffer from when the transaction started.
- .inflight => view.sendFrameDone(),
+ .inflight => window.sendFrameDone(),
.acked, .timed_out_acked => {
toplevel.wlr_toplevel.base.getGeometry(&toplevel.geometry);
- if (view.inflight.resizing) {
- view.resizeUpdatePosition(toplevel.geometry.width, toplevel.geometry.height);
+ if (window.inflight.resizing) {
+ window.resizeUpdatePosition(toplevel.geometry.width, toplevel.geometry.height);
}
- view.inflight.box.width = toplevel.geometry.width;
- view.inflight.box.height = toplevel.geometry.height;
- view.pending.box.width = toplevel.geometry.width;
- view.pending.box.height = toplevel.geometry.height;
+ window.inflight.box.width = toplevel.geometry.width;
+ window.inflight.box.height = toplevel.geometry.height;
+ window.pending.box.width = toplevel.geometry.width;
+ window.pending.box.height = toplevel.geometry.height;
switch (toplevel.configure_state) {
.acked => {
@@ -385,8 +385,8 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
},
.timed_out_acked => {
toplevel.configure_state = .idle;
- view.current = view.inflight;
- view.updateSceneState();
+ window.current = window.inflight;
+ window.updateSceneState();
},
else => unreachable,
}
@@ -398,8 +398,8 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
/// for now, perhaps it should be denied in some cases in the future.
fn handleRequestFullscreen(listener: *wl.Listener(void)) void {
const toplevel: *XdgToplevel = @fieldParentPtr("request_fullscreen", listener);
- if (toplevel.view.pending.fullscreen != toplevel.wlr_toplevel.requested.fullscreen) {
- toplevel.view.pending.fullscreen = toplevel.wlr_toplevel.requested.fullscreen;
+ if (toplevel.window.pending.fullscreen != toplevel.wlr_toplevel.requested.fullscreen) {
+ toplevel.window.pending.fullscreen = toplevel.wlr_toplevel.requested.fullscreen;
server.root.applyPending();
}
}
@@ -410,14 +410,14 @@ fn handleRequestMove(
) void {
const toplevel: *XdgToplevel = @fieldParentPtr("request_move", listener);
const seat: *Seat = @ptrFromInt(event.seat.seat.data);
- const view = toplevel.view;
+ const window = toplevel.window;
- if (view.pending.fullscreen) return;
+ if (window.pending.fullscreen) return;
// Moving windows with touch or tablet tool is not yet supported.
if (seat.wlr_seat.validatePointerGrabSerial(null, event.serial)) {
switch (seat.cursor.mode) {
- .passthrough, .down => seat.cursor.startMove(view),
+ .passthrough, .down => seat.cursor.startMove(window),
.move, .resize => {},
}
}
@@ -426,14 +426,14 @@ fn handleRequestMove(
fn handleRequestResize(listener: *wl.Listener(*wlr.XdgToplevel.event.Resize), event: *wlr.XdgToplevel.event.Resize) void {
const toplevel: *XdgToplevel = @fieldParentPtr("request_resize", listener);
const seat: *Seat = @ptrFromInt(event.seat.seat.data);
- const view = toplevel.view;
+ const window = toplevel.window;
- if (view.pending.fullscreen) return;
+ if (window.pending.fullscreen) return;
// Resizing windows with touch or tablet tool is not yet supported.
if (seat.wlr_seat.validatePointerGrabSerial(null, event.serial)) {
switch (seat.cursor.mode) {
- .passthrough, .down => seat.cursor.startResize(view, event.edges),
+ .passthrough, .down => seat.cursor.startResize(window, event.edges),
.move, .resize => {},
}
}
@@ -442,11 +442,11 @@ fn handleRequestResize(listener: *wl.Listener(*wlr.XdgToplevel.event.Resize), ev
/// Called when the client sets / updates its title
fn handleSetTitle(listener: *wl.Listener(void)) void {
const toplevel: *XdgToplevel = @fieldParentPtr("set_title", listener);
- toplevel.view.notifyTitle();
+ toplevel.window.notifyTitle();
}
/// Called when the client sets / updates its app_id
fn handleSetAppId(listener: *wl.Listener(void)) void {
const toplevel: *XdgToplevel = @fieldParentPtr("set_app_id", listener);
- toplevel.view.notifyAppId();
+ toplevel.window.notifyAppId();
}
diff --git a/river/XwaylandOverrideRedirect.zig b/river/XwaylandOverrideRedirect.zig
index ff638a3..28f3480 100644
--- a/river/XwaylandOverrideRedirect.zig
+++ b/river/XwaylandOverrideRedirect.zig
@@ -26,8 +26,8 @@ const server = &@import("main.zig").server;
const util = @import("util.zig");
const SceneNodeData = @import("SceneNodeData.zig");
-const View = @import("View.zig");
-const XwaylandView = @import("XwaylandView.zig");
+const Window = @import("Window.zig");
+const XwaylandWindow = @import("XwaylandWindow.zig");
const log = std.log.scoped(.xwayland);
@@ -139,13 +139,13 @@ pub fn focusIfDesired(override_redirect: *XwaylandOverrideRedirect) void {
override_redirect.xwayland_surface.icccmInputModel() != .none)
{
const seat = server.input_manager.defaultSeat();
- // Keep the parent top-level Xwayland view of any override redirect surface
+ // Keep the parent top-level Xwayland window of any override redirect surface
// activated while that override redirect surface is focused. This ensures
// override redirect menus do not disappear as a result of deactivating
// their parent window.
- if (seat.focused == .view and
- seat.focused.view.impl == .xwayland_view and
- seat.focused.view.impl.xwayland_view.xwayland_surface.pid == override_redirect.xwayland_surface.pid)
+ if (seat.focused == .window and
+ seat.focused.window.impl == .xwayland_window and
+ seat.focused.window.impl.xwayland_window.xwayland_surface.pid == override_redirect.xwayland_surface.pid)
{
seat.keyboardEnterOrLeave(override_redirect.xwayland_surface.surface);
} else {
@@ -168,11 +168,11 @@ fn handleUnmap(listener: *wl.Listener(void)) void {
var seat_it = server.input_manager.seats.first;
while (seat_it) |seat_node| : (seat_it = seat_node.next) {
const seat = &seat_node.data;
- if (seat.focused == .view and seat.focused.view.impl == .xwayland_view and
- seat.focused.view.impl.xwayland_view.xwayland_surface.pid == override_redirect.xwayland_surface.pid and
+ if (seat.focused == .window and seat.focused.window.impl == .xwayland_window and
+ seat.focused.window.impl.xwayland_window.xwayland_surface.pid == override_redirect.xwayland_surface.pid and
seat.wlr_seat.keyboard_state.focused_surface == override_redirect.xwayland_surface.surface)
{
- seat.keyboardEnterOrLeave(seat.focused.view.rootSurface());
+ seat.keyboardEnterOrLeave(seat.focused.window.rootSurface());
}
}
@@ -204,7 +204,7 @@ fn handleSetOverrideRedirect(listener: *wl.Listener(void)) void {
}
handleDestroy(&override_redirect.destroy);
- XwaylandView.create(xwayland_surface) catch {
+ XwaylandWindow.create(xwayland_surface) catch {
log.err("out of memory", .{});
return;
};
diff --git a/river/XwaylandView.zig b/river/XwaylandView.zig
deleted file mode 100644
index c4e6662..0000000
--- a/river/XwaylandView.zig
+++ /dev/null
@@ -1,297 +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 XwaylandView = @This();
-
-const std = @import("std");
-const assert = std.debug.assert;
-const math = std.math;
-
-const wlr = @import("wlroots");
-const wl = @import("wayland").server.wl;
-
-const server = &@import("main.zig").server;
-const util = @import("util.zig");
-
-const Output = @import("Output.zig");
-const View = @import("View.zig");
-const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
-
-const log = std.log.scoped(.xwayland);
-
-/// TODO(zig): get rid of this and use @fieldParentPtr(), https://github.com/ziglang/zig/issues/6611
-view: *View,
-
-xwayland_surface: *wlr.XwaylandSurface,
-/// Created on map and destroyed on unmap
-surface_tree: ?*wlr.SceneTree = null,
-
-// Active over entire lifetime
-destroy: wl.Listener(void) = wl.Listener(void).init(handleDestroy),
-request_configure: wl.Listener(*wlr.XwaylandSurface.event.Configure) =
- wl.Listener(*wlr.XwaylandSurface.event.Configure).init(handleRequestConfigure),
-set_override_redirect: wl.Listener(void) = wl.Listener(void).init(handleSetOverrideRedirect),
-associate: wl.Listener(void) = wl.Listener(void).init(handleAssociate),
-dissociate: wl.Listener(void) = wl.Listener(void).init(handleDissociate),
-
-// Active while the xwayland_surface is associated with a wlr_surface
-map: wl.Listener(void) = wl.Listener(void).init(handleMap),
-unmap: wl.Listener(void) = wl.Listener(void).init(handleUnmap),
-
-// Active while mapped
-set_title: wl.Listener(void) = wl.Listener(void).init(handleSetTitle),
-set_class: wl.Listener(void) = wl.Listener(void).init(handleSetClass),
-set_decorations: wl.Listener(void) = wl.Listener(void).init(handleSetDecorations),
-request_fullscreen: wl.Listener(void) = wl.Listener(void).init(handleRequestFullscreen),
-request_minimize: wl.Listener(*wlr.XwaylandSurface.event.Minimize) =
- wl.Listener(*wlr.XwaylandSurface.event.Minimize).init(handleRequestMinimize),
-
-pub fn create(xwayland_surface: *wlr.XwaylandSurface) error{OutOfMemory}!void {
- const view = try View.create(.{ .xwayland_view = .{
- .view = undefined,
- .xwayland_surface = xwayland_surface,
- } });
- errdefer view.destroy(.assert);
-
- const xwayland_view = &view.impl.xwayland_view;
- xwayland_view.view = view;
-
- // Add listeners that are active over the view's entire lifetime
- xwayland_surface.events.destroy.add(&xwayland_view.destroy);
- xwayland_surface.events.associate.add(&xwayland_view.associate);
- xwayland_surface.events.dissociate.add(&xwayland_view.dissociate);
- xwayland_surface.events.request_configure.add(&xwayland_view.request_configure);
- xwayland_surface.events.set_override_redirect.add(&xwayland_view.set_override_redirect);
-
- if (xwayland_surface.surface) |surface| {
- handleAssociate(&xwayland_view.associate);
- if (surface.mapped) {
- handleMap(&xwayland_view.map);
- }
- }
-}
-
-/// Always returns false as we do not care about frame perfection for Xwayland views.
-pub fn configure(xwayland_view: XwaylandView) bool {
- const inflight = &xwayland_view.view.inflight;
- const current = &xwayland_view.view.current;
-
- if (xwayland_view.xwayland_surface.x == inflight.box.x and
- xwayland_view.xwayland_surface.y == inflight.box.y and
- xwayland_view.xwayland_surface.width == inflight.box.width and
- xwayland_view.xwayland_surface.height == inflight.box.height and
- (inflight.focus != 0) == (current.focus != 0))
- // TODO fullscreen
- {
- return false;
- }
-
- xwayland_view.xwayland_surface.configure(
- math.lossyCast(i16, inflight.box.x),
- math.lossyCast(i16, inflight.box.y),
- math.lossyCast(u16, inflight.box.width),
- math.lossyCast(u16, inflight.box.height),
- );
-
- xwayland_view.setActivated(inflight.focus != 0);
-
- if (false) xwayland_view.xwayland_surface.setFullscreen();
-
- return false;
-}
-
-fn setActivated(xwayland_view: XwaylandView, activated: bool) void {
- // See comment on handleRequestMinimize() for details
- if (activated and xwayland_view.xwayland_surface.minimized) {
- xwayland_view.xwayland_surface.setMinimized(false);
- }
- xwayland_view.xwayland_surface.activate(activated);
- if (activated) {
- xwayland_view.xwayland_surface.restack(null, .above);
- }
-}
-
-fn handleDestroy(listener: *wl.Listener(void)) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("destroy", listener);
-
- // Remove listeners that are active for the entire lifetime of the view
- xwayland_view.destroy.link.remove();
- xwayland_view.associate.link.remove();
- xwayland_view.dissociate.link.remove();
- xwayland_view.request_configure.link.remove();
- xwayland_view.set_override_redirect.link.remove();
-
- const view = xwayland_view.view;
- view.impl = .none;
- view.destroy(.lazy);
-}
-
-fn handleAssociate(listener: *wl.Listener(void)) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("associate", listener);
-
- xwayland_view.xwayland_surface.surface.?.events.map.add(&xwayland_view.map);
- xwayland_view.xwayland_surface.surface.?.events.unmap.add(&xwayland_view.unmap);
-}
-
-fn handleDissociate(listener: *wl.Listener(void)) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("dissociate", listener);
- xwayland_view.map.link.remove();
- xwayland_view.unmap.link.remove();
-}
-
-pub fn handleMap(listener: *wl.Listener(void)) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("map", listener);
- const view = xwayland_view.view;
-
- const xwayland_surface = xwayland_view.xwayland_surface;
- const surface = xwayland_surface.surface.?;
- surface.data = @intFromPtr(&view.tree.node);
-
- // Add listeners that are only active while mapped
- xwayland_surface.events.set_title.add(&xwayland_view.set_title);
- xwayland_surface.events.set_class.add(&xwayland_view.set_class);
- xwayland_surface.events.set_decorations.add(&xwayland_view.set_decorations);
- xwayland_surface.events.request_fullscreen.add(&xwayland_view.request_fullscreen);
- xwayland_surface.events.request_minimize.add(&xwayland_view.request_minimize);
-
- xwayland_view.surface_tree = view.surface_tree.createSceneSubsurfaceTree(surface) catch {
- log.err("out of memory", .{});
- surface.resource.getClient().postNoMemory();
- return;
- };
-
- view.pending.box = .{
- .x = 0,
- .y = 0,
- .width = xwayland_view.xwayland_surface.width,
- .height = xwayland_view.xwayland_surface.height,
- };
- view.inflight.box = view.pending.box;
- view.current.box = view.pending.box;
-
- // This will be overwritten in View.map() if the view is matched by a rule.
- view.pending.ssd = !xwayland_surface.decorations.no_border;
-
- view.pending.fullscreen = xwayland_surface.fullscreen;
-
- view.map() catch {
- log.err("out of memory", .{});
- surface.resource.getClient().postNoMemory();
- };
-}
-
-fn handleUnmap(listener: *wl.Listener(void)) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("unmap", listener);
-
- xwayland_view.xwayland_surface.surface.?.data = 0;
-
- // Remove listeners that are only active while mapped
- xwayland_view.set_title.link.remove();
- xwayland_view.set_class.link.remove();
- xwayland_view.request_fullscreen.link.remove();
- xwayland_view.request_minimize.link.remove();
-
- xwayland_view.view.unmap();
-
- // Don't destroy the surface tree until after View.unmap() has a chance
- // to save buffers for frame perfection.
- xwayland_view.surface_tree.?.node.destroy();
- xwayland_view.surface_tree = null;
-}
-
-fn handleRequestConfigure(
- listener: *wl.Listener(*wlr.XwaylandSurface.event.Configure),
- event: *wlr.XwaylandSurface.event.Configure,
-) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("request_configure", listener);
-
- // If unmapped, let the client do whatever it wants
- if (xwayland_view.xwayland_surface.surface == null or
- !xwayland_view.xwayland_surface.surface.?.mapped)
- {
- xwayland_view.xwayland_surface.configure(event.x, event.y, event.width, event.height);
- return;
- }
-
- // Allow xwayland views to set their own dimensions (but not position) if floating
- xwayland_view.view.pending.box.width = event.width;
- xwayland_view.view.pending.box.height = event.height;
- server.root.applyPending();
-}
-
-fn handleSetOverrideRedirect(listener: *wl.Listener(void)) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("set_override_redirect", listener);
- const xwayland_surface = xwayland_view.xwayland_surface;
-
- log.debug("xwayland surface set override redirect", .{});
-
- assert(xwayland_surface.override_redirect);
-
- if (xwayland_surface.surface) |surface| {
- if (surface.mapped) {
- handleUnmap(&xwayland_view.unmap);
- }
- handleDissociate(&xwayland_view.dissociate);
- }
- handleDestroy(&xwayland_view.destroy);
-
- XwaylandOverrideRedirect.create(xwayland_surface) catch {
- log.err("out of memory", .{});
- return;
- };
-}
-
-fn handleSetTitle(listener: *wl.Listener(void)) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("set_title", listener);
- xwayland_view.view.notifyTitle();
-}
-
-fn handleSetClass(listener: *wl.Listener(void)) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("set_class", listener);
- xwayland_view.view.notifyAppId();
-}
-
-fn handleSetDecorations(listener: *wl.Listener(void)) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("set_decorations", listener);
- const view = xwayland_view.view;
-
- const ssd = !xwayland_view.xwayland_surface.decorations.no_border;
-
- if (view.pending.ssd != ssd) {
- view.pending.ssd = ssd;
- server.root.applyPending();
- }
-}
-
-fn handleRequestFullscreen(listener: *wl.Listener(void)) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("request_fullscreen", listener);
- if (xwayland_view.view.pending.fullscreen != xwayland_view.xwayland_surface.fullscreen) {
- xwayland_view.view.pending.fullscreen = xwayland_view.xwayland_surface.fullscreen;
- server.root.applyPending();
- }
-}
-
-/// Some X11 clients will minimize themselves regardless of how we respond.
-/// Therefore to ensure they don't get stuck in this minimized state we tell
-/// them their request has been honored without actually doing anything and
-/// unminimize them if they gain focus while minimized.
-fn handleRequestMinimize(
- listener: *wl.Listener(*wlr.XwaylandSurface.event.Minimize),
- event: *wlr.XwaylandSurface.event.Minimize,
-) void {
- const xwayland_view: *XwaylandView = @fieldParentPtr("request_minimize", listener);
- xwayland_view.xwayland_surface.setMinimized(event.minimize);
-}
diff --git a/river/XwaylandWindow.zig b/river/XwaylandWindow.zig
new file mode 100644
index 0000000..85751d2
--- /dev/null
+++ b/river/XwaylandWindow.zig
@@ -0,0 +1,297 @@
+// 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 XwaylandWindow = @This();
+
+const std = @import("std");
+const assert = std.debug.assert;
+const math = std.math;
+
+const wlr = @import("wlroots");
+const wl = @import("wayland").server.wl;
+
+const server = &@import("main.zig").server;
+const util = @import("util.zig");
+
+const Output = @import("Output.zig");
+const Window = @import("Window.zig");
+const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
+
+const log = std.log.scoped(.xwayland);
+
+/// TODO(zig): get rid of this and use @fieldParentPtr(), https://github.com/ziglang/zig/issues/6611
+window: *Window,
+
+xwayland_surface: *wlr.XwaylandSurface,
+/// Created on map and destroyed on unmap
+surface_tree: ?*wlr.SceneTree = null,
+
+// Active over entire lifetime
+destroy: wl.Listener(void) = wl.Listener(void).init(handleDestroy),
+request_configure: wl.Listener(*wlr.XwaylandSurface.event.Configure) =
+ wl.Listener(*wlr.XwaylandSurface.event.Configure).init(handleRequestConfigure),
+set_override_redirect: wl.Listener(void) = wl.Listener(void).init(handleSetOverrideRedirect),
+associate: wl.Listener(void) = wl.Listener(void).init(handleAssociate),
+dissociate: wl.Listener(void) = wl.Listener(void).init(handleDissociate),
+
+// Active while the xwayland_surface is associated with a wlr_surface
+map: wl.Listener(void) = wl.Listener(void).init(handleMap),
+unmap: wl.Listener(void) = wl.Listener(void).init(handleUnmap),
+
+// Active while mapped
+set_title: wl.Listener(void) = wl.Listener(void).init(handleSetTitle),
+set_class: wl.Listener(void) = wl.Listener(void).init(handleSetClass),
+set_decorations: wl.Listener(void) = wl.Listener(void).init(handleSetDecorations),
+request_fullscreen: wl.Listener(void) = wl.Listener(void).init(handleRequestFullscreen),
+request_minimize: wl.Listener(*wlr.XwaylandSurface.event.Minimize) =
+ wl.Listener(*wlr.XwaylandSurface.event.Minimize).init(handleRequestMinimize),
+
+pub fn create(xwayland_surface: *wlr.XwaylandSurface) error{OutOfMemory}!void {
+ const window = try Window.create(.{ .xwayland_window = .{
+ .window = undefined,
+ .xwayland_surface = xwayland_surface,
+ } });
+ errdefer window.destroy(.assert);
+
+ const xwayland_window = &window.impl.xwayland_window;
+ xwayland_window.window = window;
+
+ // Add listeners that are active over the window's entire lifetime
+ xwayland_surface.events.destroy.add(&xwayland_window.destroy);
+ xwayland_surface.events.associate.add(&xwayland_window.associate);
+ xwayland_surface.events.dissociate.add(&xwayland_window.dissociate);
+ xwayland_surface.events.request_configure.add(&xwayland_window.request_configure);
+ xwayland_surface.events.set_override_redirect.add(&xwayland_window.set_override_redirect);
+
+ if (xwayland_surface.surface) |surface| {
+ handleAssociate(&xwayland_window.associate);
+ if (surface.mapped) {
+ handleMap(&xwayland_window.map);
+ }
+ }
+}
+
+/// Always returns false as we do not care about frame perfection for Xwayland windows.
+pub fn configure(xwayland_window: XwaylandWindow) bool {
+ const inflight = &xwayland_window.window.inflight;
+ const current = &xwayland_window.window.current;
+
+ if (xwayland_window.xwayland_surface.x == inflight.box.x and
+ xwayland_window.xwayland_surface.y == inflight.box.y and
+ xwayland_window.xwayland_surface.width == inflight.box.width and
+ xwayland_window.xwayland_surface.height == inflight.box.height and
+ (inflight.focus != 0) == (current.focus != 0))
+ // TODO fullscreen
+ {
+ return false;
+ }
+
+ xwayland_window.xwayland_surface.configure(
+ math.lossyCast(i16, inflight.box.x),
+ math.lossyCast(i16, inflight.box.y),
+ math.lossyCast(u16, inflight.box.width),
+ math.lossyCast(u16, inflight.box.height),
+ );
+
+ xwayland_window.setActivated(inflight.focus != 0);
+
+ if (false) xwayland_window.xwayland_surface.setFullscreen();
+
+ return false;
+}
+
+fn setActivated(xwayland_window: XwaylandWindow, activated: bool) void {
+ // See comment on handleRequestMinimize() for details
+ if (activated and xwayland_window.xwayland_surface.minimized) {
+ xwayland_window.xwayland_surface.setMinimized(false);
+ }
+ xwayland_window.xwayland_surface.activate(activated);
+ if (activated) {
+ xwayland_window.xwayland_surface.restack(null, .above);
+ }
+}
+
+fn handleDestroy(listener: *wl.Listener(void)) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("destroy", listener);
+
+ // Remove listeners that are active for the entire lifetime of the window
+ xwayland_window.destroy.link.remove();
+ xwayland_window.associate.link.remove();
+ xwayland_window.dissociate.link.remove();
+ xwayland_window.request_configure.link.remove();
+ xwayland_window.set_override_redirect.link.remove();
+
+ const window = xwayland_window.window;
+ window.impl = .none;
+ window.destroy(.lazy);
+}
+
+fn handleAssociate(listener: *wl.Listener(void)) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("associate", listener);
+
+ xwayland_window.xwayland_surface.surface.?.events.map.add(&xwayland_window.map);
+ xwayland_window.xwayland_surface.surface.?.events.unmap.add(&xwayland_window.unmap);
+}
+
+fn handleDissociate(listener: *wl.Listener(void)) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("dissociate", listener);
+ xwayland_window.map.link.remove();
+ xwayland_window.unmap.link.remove();
+}
+
+pub fn handleMap(listener: *wl.Listener(void)) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("map", listener);
+ const window = xwayland_window.window;
+
+ const xwayland_surface = xwayland_window.xwayland_surface;
+ const surface = xwayland_surface.surface.?;
+ surface.data = @intFromPtr(&window.tree.node);
+
+ // Add listeners that are only active while mapped
+ xwayland_surface.events.set_title.add(&xwayland_window.set_title);
+ xwayland_surface.events.set_class.add(&xwayland_window.set_class);
+ xwayland_surface.events.set_decorations.add(&xwayland_window.set_decorations);
+ xwayland_surface.events.request_fullscreen.add(&xwayland_window.request_fullscreen);
+ xwayland_surface.events.request_minimize.add(&xwayland_window.request_minimize);
+
+ xwayland_window.surface_tree = window.surface_tree.createSceneSubsurfaceTree(surface) catch {
+ log.err("out of memory", .{});
+ surface.resource.getClient().postNoMemory();
+ return;
+ };
+
+ window.pending.box = .{
+ .x = 0,
+ .y = 0,
+ .width = xwayland_window.xwayland_surface.width,
+ .height = xwayland_window.xwayland_surface.height,
+ };
+ window.inflight.box = window.pending.box;
+ window.current.box = window.pending.box;
+
+ // This will be overwritten in Window.map() if the window is matched by a rule.
+ window.pending.ssd = !xwayland_surface.decorations.no_border;
+
+ window.pending.fullscreen = xwayland_surface.fullscreen;
+
+ window.map() catch {
+ log.err("out of memory", .{});
+ surface.resource.getClient().postNoMemory();
+ };
+}
+
+fn handleUnmap(listener: *wl.Listener(void)) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("unmap", listener);
+
+ xwayland_window.xwayland_surface.surface.?.data = 0;
+
+ // Remove listeners that are only active while mapped
+ xwayland_window.set_title.link.remove();
+ xwayland_window.set_class.link.remove();
+ xwayland_window.request_fullscreen.link.remove();
+ xwayland_window.request_minimize.link.remove();
+
+ xwayland_window.window.unmap();
+
+ // Don't destroy the surface tree until after Window.unmap() has a chance
+ // to save buffers for frame perfection.
+ xwayland_window.surface_tree.?.node.destroy();
+ xwayland_window.surface_tree = null;
+}
+
+fn handleRequestConfigure(
+ listener: *wl.Listener(*wlr.XwaylandSurface.event.Configure),
+ event: *wlr.XwaylandSurface.event.Configure,
+) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("request_configure", listener);
+
+ // If unmapped, let the client do whatever it wants
+ if (xwayland_window.xwayland_surface.surface == null or
+ !xwayland_window.xwayland_surface.surface.?.mapped)
+ {
+ xwayland_window.xwayland_surface.configure(event.x, event.y, event.width, event.height);
+ return;
+ }
+
+ // Allow xwayland windows to set their own dimensions (but not position) if floating
+ xwayland_window.window.pending.box.width = event.width;
+ xwayland_window.window.pending.box.height = event.height;
+ server.root.applyPending();
+}
+
+fn handleSetOverrideRedirect(listener: *wl.Listener(void)) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("set_override_redirect", listener);
+ const xwayland_surface = xwayland_window.xwayland_surface;
+
+ log.debug("xwayland surface set override redirect", .{});
+
+ assert(xwayland_surface.override_redirect);
+
+ if (xwayland_surface.surface) |surface| {
+ if (surface.mapped) {
+ handleUnmap(&xwayland_window.unmap);
+ }
+ handleDissociate(&xwayland_window.dissociate);
+ }
+ handleDestroy(&xwayland_window.destroy);
+
+ XwaylandOverrideRedirect.create(xwayland_surface) catch {
+ log.err("out of memory", .{});
+ return;
+ };
+}
+
+fn handleSetTitle(listener: *wl.Listener(void)) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("set_title", listener);
+ xwayland_window.window.notifyTitle();
+}
+
+fn handleSetClass(listener: *wl.Listener(void)) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("set_class", listener);
+ xwayland_window.window.notifyAppId();
+}
+
+fn handleSetDecorations(listener: *wl.Listener(void)) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("set_decorations", listener);
+ const window = xwayland_window.window;
+
+ const ssd = !xwayland_window.xwayland_surface.decorations.no_border;
+
+ if (window.pending.ssd != ssd) {
+ window.pending.ssd = ssd;
+ server.root.applyPending();
+ }
+}
+
+fn handleRequestFullscreen(listener: *wl.Listener(void)) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("request_fullscreen", listener);
+ if (xwayland_window.window.pending.fullscreen != xwayland_window.xwayland_surface.fullscreen) {
+ xwayland_window.window.pending.fullscreen = xwayland_window.xwayland_surface.fullscreen;
+ server.root.applyPending();
+ }
+}
+
+/// Some X11 clients will minimize themselves regardless of how we respond.
+/// Therefore to ensure they don't get stuck in this minimized state we tell
+/// them their request has been honored without actually doing anything and
+/// unminimize them if they gain focus while minimized.
+fn handleRequestMinimize(
+ listener: *wl.Listener(*wlr.XwaylandSurface.event.Minimize),
+ event: *wlr.XwaylandSurface.event.Minimize,
+) void {
+ const xwayland_window: *XwaylandWindow = @fieldParentPtr("request_minimize", listener);
+ xwayland_window.xwayland_surface.setMinimized(event.minimize);
+}