Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
river: delete wlr-layer-shell-v1 support
This is getting in my way far more than I expected while I work on
the river window management protocol implementation.
Although I personally would be happy to see it never return, it should
probably be brought back eventually due to its widespread usage.
build.zig | 2 -
protocol/river-window-management-v1.xml | 43 ----
protocol/wlr-layer-shell-unstable-v1.xml | 390 -------------------------------
river/Cursor.zig | 8 -
river/IdleInhibitManager.zig | 6 -
river/InputPopup.zig | 2 -
river/LayerSurface.zig | 207 ----------------
river/Output.zig | 85 -------
river/Root.zig | 1 -
river/SceneNodeData.zig | 2 -
river/Seat.zig | 25 --
river/Server.zig | 46 ----
river/XdgPopup.zig | 3 +-
13 files changed, 1 insertion(+), 819 deletions(-)
diff --git a/build.zig b/build.zig
index 3766eb4..d189888 100644
--- a/build.zig
+++ b/build.zig
@@ -102,7 +102,6 @@ pub fn build(b: *Build) !void {
scanner.addCustomProtocol("protocol/river-window-management-v1.xml");
scanner.addCustomProtocol("protocol/river-control-unstable-v1.xml");
scanner.addCustomProtocol("protocol/river-layout-v3.xml");
- scanner.addCustomProtocol("protocol/wlr-layer-shell-unstable-v1.xml");
scanner.addCustomProtocol("protocol/wlr-output-power-management-unstable-v1.xml");
// Some of these versions may be out of date with what wlroots implements.
@@ -130,7 +129,6 @@ pub fn build(b: *Build) !void {
scanner.generate("zriver_control_v1", 1);
scanner.generate("river_layout_manager_v3", 2);
- scanner.generate("zwlr_layer_shell_v1", 4);
scanner.generate("zwlr_output_power_manager_v1", 1);
const wayland = b.createModule(.{ .root_source_file = scanner.result });
diff --git a/protocol/river-window-management-v1.xml b/protocol/river-window-management-v1.xml
index 3ad13b9..b3f0ea6 100644
--- a/protocol/river-window-management-v1.xml
+++ b/protocol/river-window-management-v1.xml
@@ -917,31 +917,6 @@
<arg name="width" type="int"/>
<arg name="height" type="int"/>
</event>
-
- <event name="usable_area_hint">
- <description summary="output area intended for window management">
- This event indicates the area of the output that is intended for window
- management. This area may be smaller than the full dimensions of the
- output if there is, for example, a layer-shell client with an exclusive
- zone set (perhaps a status bar).
-
- The window manager is free to ignore this hint and place windows
- wherever it chooses.
-
- This area will always be equal to or smaller than the full area of the
- output. The x and y coordinates are relative to the output's position in
- the compositor's logical coordinate space and always greater than or
- equal to 0. The width and height are always strictly greater than zero
- and less than or equal to the output dimensions.
-
- This event is double-buffered state and will be followed by a
- river_window_manager_v1.update event.
- </description>
- <arg name="x" type="int"/>
- <arg name="y" type="int"/>
- <arg name="width" type="int"/>
- <arg name="height" type="int"/>
- </event>
</interface>
<interface name="river_seat_v1" version="1">
@@ -965,12 +940,6 @@
<description summary="give keyboard focus to a window">
Request that the compositor send keyboard input to the given window.
- Despite this request, the compositor may temporarily give keyboard focus
- to a wlr-layer-shell client requesting exclusive focus or similar if the
- compositor supports such a protocol. In such a case, the compositor
- should return focus to the specified window when the conditions that
- caused the window manager's request to be overruled no longer hold.
-
This request is double-buffered state and will not be applied until the
next river_window_manager_v1.commit request.
</description>
@@ -982,12 +951,6 @@
Request that the compositor send keyboard input to the given shell
surface.
- Despite this request, the compositor may temporarily give keyboard focus
- to a wlr-layer-shell client requesting exclusive focus or similar if the
- compositor supports such a protocol. In such a case, the compositor
- should return focus to the specified shell surface when the conditions
- that caused the window manager's request to be overruled no longer hold.
-
This request is double-buffered state and will not be applied until the
next river_window_manager_v1.commit request.
</description>
@@ -998,12 +961,6 @@
<description summary="clear keyboard focus">
Request that the compositor not send keyboard input to any client.
- Despite this request, the compositor may temporarily give keyboard focus
- to a wlr-layer-shell client requesting exclusive focus or similar if the
- compositor supports such a protocol. In such a case, the compositor
- should again clear focus when the conditions that caused the window
- manager's request to be overruled no longer hold.
-
This request is double-buffered state and will not be applied until the
next river_window_manager_v1.commit request.
</description>
diff --git a/protocol/wlr-layer-shell-unstable-v1.xml b/protocol/wlr-layer-shell-unstable-v1.xml
deleted file mode 100644
index d62fd51..0000000
--- a/protocol/wlr-layer-shell-unstable-v1.xml
+++ /dev/null
@@ -1,390 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<protocol name="wlr_layer_shell_unstable_v1">
- <copyright>
- Copyright © 2017 Drew DeVault
-
- Permission to use, copy, modify, distribute, and sell this
- software and its documentation for any purpose is hereby granted
- without fee, provided that the above copyright notice appear in
- all copies and that both that copyright notice and this permission
- notice appear in supporting documentation, and that the name of
- the copyright holders not be used in advertising or publicity
- pertaining to distribution of the software without specific,
- written prior permission. The copyright holders make no
- representations about the suitability of this software for any
- purpose. It is provided "as is" without express or implied
- warranty.
-
- THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
- SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
- SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
- AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
- THIS SOFTWARE.
- </copyright>
-
- <interface name="zwlr_layer_shell_v1" version="4">
- <description summary="create surfaces that are layers of the desktop">
- Clients can use this interface to assign the surface_layer role to
- wl_surfaces. Such surfaces are assigned to a "layer" of the output and
- rendered with a defined z-depth respective to each other. They may also be
- anchored to the edges and corners of a screen and specify input handling
- semantics. This interface should be suitable for the implementation of
- many desktop shell components, and a broad number of other applications
- that interact with the desktop.
- </description>
-
- <request name="get_layer_surface">
- <description summary="create a layer_surface from a surface">
- Create a layer surface for an existing surface. This assigns the role of
- layer_surface, or raises a protocol error if another role is already
- assigned.
-
- Creating a layer surface from a wl_surface which has a buffer attached
- or committed is a client error, and any attempts by a client to attach
- or manipulate a buffer prior to the first layer_surface.configure call
- must also be treated as errors.
-
- After creating a layer_surface object and setting it up, the client
- must perform an initial commit without any buffer attached.
- The compositor will reply with a layer_surface.configure event.
- The client must acknowledge it and is then allowed to attach a buffer
- to map the surface.
-
- You may pass NULL for output to allow the compositor to decide which
- output to use. Generally this will be the one that the user most
- recently interacted with.
-
- Clients can specify a namespace that defines the purpose of the layer
- surface.
- </description>
- <arg name="id" type="new_id" interface="zwlr_layer_surface_v1"/>
- <arg name="surface" type="object" interface="wl_surface"/>
- <arg name="output" type="object" interface="wl_output" allow-null="true"/>
- <arg name="layer" type="uint" enum="layer" summary="layer to add this surface to"/>
- <arg name="namespace" type="string" summary="namespace for the layer surface"/>
- </request>
-
- <enum name="error">
- <entry name="role" value="0" summary="wl_surface has another role"/>
- <entry name="invalid_layer" value="1" summary="layer value is invalid"/>
- <entry name="already_constructed" value="2" summary="wl_surface has a buffer attached or committed"/>
- </enum>
-
- <enum name="layer">
- <description summary="available layers for surfaces">
- These values indicate which layers a surface can be rendered in. They
- are ordered by z depth, bottom-most first. Traditional shell surfaces
- will typically be rendered between the bottom and top layers.
- Fullscreen shell surfaces are typically rendered at the top layer.
- Multiple surfaces can share a single layer, and ordering within a
- single layer is undefined.
- </description>
-
- <entry name="background" value="0"/>
- <entry name="bottom" value="1"/>
- <entry name="top" value="2"/>
- <entry name="overlay" value="3"/>
- </enum>
-
- <!-- Version 3 additions -->
-
- <request name="destroy" type="destructor" since="3">
- <description summary="destroy the layer_shell object">
- This request indicates that the client will not use the layer_shell
- object any more. Objects that have been created through this instance
- are not affected.
- </description>
- </request>
- </interface>
-
- <interface name="zwlr_layer_surface_v1" version="4">
- <description summary="layer metadata interface">
- An interface that may be implemented by a wl_surface, for surfaces that
- are designed to be rendered as a layer of a stacked desktop-like
- environment.
-
- Layer surface state (layer, size, anchor, exclusive zone,
- margin, interactivity) is double-buffered, and will be applied at the
- time wl_surface.commit of the corresponding wl_surface is called.
-
- Attaching a null buffer to a layer surface unmaps it.
-
- Unmapping a layer_surface means that the surface cannot be shown by the
- compositor until it is explicitly mapped again. The layer_surface
- returns to the state it had right after layer_shell.get_layer_surface.
- The client can re-map the surface by performing a commit without any
- buffer attached, waiting for a configure event and handling it as usual.
- </description>
-
- <request name="set_size">
- <description summary="sets the size of the surface">
- Sets the size of the surface in surface-local coordinates. The
- compositor will display the surface centered with respect to its
- anchors.
-
- If you pass 0 for either value, the compositor will assign it and
- inform you of the assignment in the configure event. You must set your
- anchor to opposite edges in the dimensions you omit; not doing so is a
- protocol error. Both values are 0 by default.
-
- Size is double-buffered, see wl_surface.commit.
- </description>
- <arg name="width" type="uint"/>
- <arg name="height" type="uint"/>
- </request>
-
- <request name="set_anchor">
- <description summary="configures the anchor point of the surface">
- Requests that the compositor anchor the surface to the specified edges
- and corners. If two orthogonal edges are specified (e.g. 'top' and
- 'left'), then the anchor point will be the intersection of the edges
- (e.g. the top left corner of the output); otherwise the anchor point
- will be centered on that edge, or in the center if none is specified.
-
- Anchor is double-buffered, see wl_surface.commit.
- </description>
- <arg name="anchor" type="uint" enum="anchor"/>
- </request>
-
- <request name="set_exclusive_zone">
- <description summary="configures the exclusive geometry of this surface">
- Requests that the compositor avoids occluding an area with other
- surfaces. The compositor's use of this information is
- implementation-dependent - do not assume that this region will not
- actually be occluded.
-
- A positive value is only meaningful if the surface is anchored to one
- edge or an edge and both perpendicular edges. If the surface is not
- anchored, anchored to only two perpendicular edges (a corner), anchored
- to only two parallel edges or anchored to all edges, a positive value
- will be treated the same as zero.
-
- A positive zone is the distance from the edge in surface-local
- coordinates to consider exclusive.
-
- Surfaces that do not wish to have an exclusive zone may instead specify
- how they should interact with surfaces that do. If set to zero, the
- surface indicates that it would like to be moved to avoid occluding
- surfaces with a positive exclusive zone. If set to -1, the surface
- indicates that it would not like to be moved to accommodate for other
- surfaces, and the compositor should extend it all the way to the edges
- it is anchored to.
-
- For example, a panel might set its exclusive zone to 10, so that
- maximized shell surfaces are not shown on top of it. A notification
- might set its exclusive zone to 0, so that it is moved to avoid
- occluding the panel, but shell surfaces are shown underneath it. A
- wallpaper or lock screen might set their exclusive zone to -1, so that
- they stretch below or over the panel.
-
- The default value is 0.
-
- Exclusive zone is double-buffered, see wl_surface.commit.
- </description>
- <arg name="zone" type="int"/>
- </request>
-
- <request name="set_margin">
- <description summary="sets a margin from the anchor point">
- Requests that the surface be placed some distance away from the anchor
- point on the output, in surface-local coordinates. Setting this value
- for edges you are not anchored to has no effect.
-
- The exclusive zone includes the margin.
-
- Margin is double-buffered, see wl_surface.commit.
- </description>
- <arg name="top" type="int"/>
- <arg name="right" type="int"/>
- <arg name="bottom" type="int"/>
- <arg name="left" type="int"/>
- </request>
-
- <enum name="keyboard_interactivity">
- <description summary="types of keyboard interaction possible for a layer shell surface">
- Types of keyboard interaction possible for layer shell surfaces. The
- rationale for this is twofold: (1) some applications are not interested
- in keyboard events and not allowing them to be focused can improve the
- desktop experience; (2) some applications will want to take exclusive
- keyboard focus.
- </description>
-
- <entry name="none" value="0">
- <description summary="no keyboard focus is possible">
- This value indicates that this surface is not interested in keyboard
- events and the compositor should never assign it the keyboard focus.
-
- This is the default value, set for newly created layer shell surfaces.
-
- This is useful for e.g. desktop widgets that display information or
- only have interaction with non-keyboard input devices.
- </description>
- </entry>
- <entry name="exclusive" value="1">
- <description summary="request exclusive keyboard focus">
- Request exclusive keyboard focus if this surface is above the shell surface layer.
-
- For the top and overlay layers, the seat will always give
- exclusive keyboard focus to the top-most layer which has keyboard
- interactivity set to exclusive. If this layer contains multiple
- surfaces with keyboard interactivity set to exclusive, the compositor
- determines the one receiving keyboard events in an implementation-
- defined manner. In this case, no guarantee is made when this surface
- will receive keyboard focus (if ever).
-
- For the bottom and background layers, the compositor is allowed to use
- normal focus semantics.
-
- This setting is mainly intended for applications that need to ensure
- they receive all keyboard events, such as a lock screen or a password
- prompt.
- </description>
- </entry>
- <entry name="on_demand" value="2" since="4">
- <description summary="request regular keyboard focus semantics">
- This requests the compositor to allow this surface to be focused and
- unfocused by the user in an implementation-defined manner. The user
- should be able to unfocus this surface even regardless of the layer
- it is on.
-
- Typically, the compositor will want to use its normal mechanism to
- manage keyboard focus between layer shell surfaces with this setting
- and regular toplevels on the desktop layer (e.g. click to focus).
- Nevertheless, it is possible for a compositor to require a special
- interaction to focus or unfocus layer shell surfaces (e.g. requiring
- a click even if focus follows the mouse normally, or providing a
- keybinding to switch focus between layers).
-
- This setting is mainly intended for desktop shell components (e.g.
- panels) that allow keyboard interaction. Using this option can allow
- implementing a desktop shell that can be fully usable without the
- mouse.
- </description>
- </entry>
- </enum>
-
- <request name="set_keyboard_interactivity">
- <description summary="requests keyboard events">
- Set how keyboard events are delivered to this surface. By default,
- layer shell surfaces do not receive keyboard events; this request can
- be used to change this.
-
- This setting is inherited by child surfaces set by the get_popup
- request.
-
- Layer surfaces receive pointer, touch, and tablet events normally. If
- you do not want to receive them, set the input region on your surface
- to an empty region.
-
- Keyboard interactivity is double-buffered, see wl_surface.commit.
- </description>
- <arg name="keyboard_interactivity" type="uint" enum="keyboard_interactivity"/>
- </request>
-
- <request name="get_popup">
- <description summary="assign this layer_surface as an xdg_popup parent">
- This assigns an xdg_popup's parent to this layer_surface. This popup
- should have been created via xdg_surface::get_popup with the parent set
- to NULL, and this request must be invoked before committing the popup's
- initial state.
-
- See the documentation of xdg_popup for more details about what an
- xdg_popup is and how it is used.
- </description>
- <arg name="popup" type="object" interface="xdg_popup"/>
- </request>
-
- <request name="ack_configure">
- <description summary="ack a configure event">
- When a configure event is received, if a client commits the
- surface in response to the configure event, then the client
- must make an ack_configure request sometime before the commit
- request, passing along the serial of the configure event.
-
- If the client receives multiple configure events before it
- can respond to one, it only has to ack the last configure event.
-
- A client is not required to commit immediately after sending
- an ack_configure request - it may even ack_configure several times
- before its next surface commit.
-
- A client may send multiple ack_configure requests before committing, but
- only the last request sent before a commit indicates which configure
- event the client really is responding to.
- </description>
- <arg name="serial" type="uint" summary="the serial from the configure event"/>
- </request>
-
- <request name="destroy" type="destructor">
- <description summary="destroy the layer_surface">
- This request destroys the layer surface.
- </description>
- </request>
-
- <event name="configure">
- <description summary="suggest a surface change">
- The configure event asks the client to resize its surface.
-
- Clients should arrange their surface for the new states, and then send
- an ack_configure request with the serial sent in this configure event at
- some point before committing the new surface.
-
- The client is free to dismiss all but the last configure event it
- received.
-
- The width and height arguments specify the size of the window in
- surface-local coordinates.
-
- The size is a hint, in the sense that the client is free to ignore it if
- it doesn't resize, pick a smaller size (to satisfy aspect ratio or
- resize in steps of NxM pixels). If the client picks a smaller size and
- is anchored to two opposite anchors (e.g. 'top' and 'bottom'), the
- surface will be centered on this axis.
-
- If the width or height arguments are zero, it means the client should
- decide its own window dimension.
- </description>
- <arg name="serial" type="uint"/>
- <arg name="width" type="uint"/>
- <arg name="height" type="uint"/>
- </event>
-
- <event name="closed">
- <description summary="surface should be closed">
- The closed event is sent by the compositor when the surface will no
- longer be shown. The output may have been destroyed or the user may
- have asked for it to be removed. Further changes to the surface will be
- ignored. The client should destroy the resource after receiving this
- event, and create a new surface if they so choose.
- </description>
- </event>
-
- <enum name="error">
- <entry name="invalid_surface_state" value="0" summary="provided surface state is invalid"/>
- <entry name="invalid_size" value="1" summary="size is invalid"/>
- <entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
- <entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
- </enum>
-
- <enum name="anchor" bitfield="true">
- <entry name="top" value="1" summary="the top edge of the anchor rectangle"/>
- <entry name="bottom" value="2" summary="the bottom edge of the anchor rectangle"/>
- <entry name="left" value="4" summary="the left edge of the anchor rectangle"/>
- <entry name="right" value="8" summary="the right edge of the anchor rectangle"/>
- </enum>
-
- <!-- Version 2 additions -->
-
- <request name="set_layer" since="2">
- <description summary="change the layer of the surface">
- Change the layer that the surface is rendered on.
-
- Layer is double-buffered, see wl_surface.commit.
- </description>
- <arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/>
- </request>
- </interface>
-</protocol>
diff --git a/river/Cursor.zig b/river/Cursor.zig
index e1abbce..68bc102 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -33,7 +33,6 @@ const util = @import("util.zig");
const Config = @import("Config.zig");
const DragIcon = @import("DragIcon.zig");
const InputDevice = @import("InputDevice.zig");
-const LayerSurface = @import("LayerSurface.zig");
const LockSurface = @import("LockSurface.zig");
const Output = @import("Output.zig");
const PointerConstraint = @import("PointerConstraint.zig");
@@ -383,13 +382,6 @@ fn updateKeyboardFocus(cursor: Cursor, result: Root.AtResult) void {
.window => |window| {
cursor.seat.focus(window);
},
- .layer_surface => |layer_surface| {
- // If a keyboard inteactive layer surface has been clicked on,
- // give it keyboard focus.
- if (layer_surface.wlr_layer_surface.current.keyboard_interactive != .none) {
- cursor.seat.setFocusRaw(.{ .layer = layer_surface });
- }
- },
.lock_surface => |lock_surface| {
assert(server.lock_manager.state != .unlocked);
cursor.seat.setFocusRaw(.{ .lock_surface = lock_surface });
diff --git a/river/IdleInhibitManager.zig b/river/IdleInhibitManager.zig
index dfda3ab..7ba4f99 100644
--- a/river/IdleInhibitManager.zig
+++ b/river/IdleInhibitManager.zig
@@ -57,12 +57,6 @@ pub fn checkActive(inhibit_manager: *IdleInhibitManager) void {
inhibited = true;
break;
},
- .layer_surface => |layer_surface| {
- if (layer_surface.wlr_layer_surface.surface.mapped) {
- inhibited = true;
- break;
- }
- },
.lock_surface, .override_redirect => {
inhibited = true;
break;
diff --git a/river/InputPopup.zig b/river/InputPopup.zig
index bee0802..03aa24a 100644
--- a/river/InputPopup.zig
+++ b/river/InputPopup.zig
@@ -109,7 +109,6 @@ pub fn update(input_popup: *InputPopup) void {
const output = switch (focused.data) {
.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
.override_redirect => unreachable,
@@ -117,7 +116,6 @@ pub fn update(input_popup: *InputPopup) void {
const popup_tree = switch (focused.data) {
.window => |window| window.popup_tree,
- .layer_surface => |layer_surface| layer_surface.popup_tree,
.lock_surface => |_| server.root.layers.popups, // XXX Do we need per-lock-surface popup trees?
// Xwayland doesn't use the text-input protocol
.override_redirect => unreachable,
diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig
deleted file mode 100644
index 42765d7..0000000
--- a/river/LayerSurface.zig
+++ /dev/null
@@ -1,207 +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 LayerSurface = @This();
-
-const std = @import("std");
-const assert = std.debug.assert;
-const wlr = @import("wlroots");
-const wl = @import("wayland").server.wl;
-const zwlr = @import("wayland").server.zwlr;
-
-const server = &@import("main.zig").server;
-const util = @import("util.zig");
-
-const Output = @import("Output.zig");
-const SceneNodeData = @import("SceneNodeData.zig");
-const XdgPopup = @import("XdgPopup.zig");
-
-const log = std.log.scoped(.layer_shell);
-
-output: *Output,
-wlr_layer_surface: *wlr.LayerSurfaceV1,
-scene_layer_surface: *wlr.SceneLayerSurfaceV1,
-popup_tree: *wlr.SceneTree,
-
-destroy: wl.Listener(*wlr.LayerSurfaceV1) = wl.Listener(*wlr.LayerSurfaceV1).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),
-
-pub fn create(wlr_layer_surface: *wlr.LayerSurfaceV1) error{OutOfMemory}!void {
- const output: *Output = @ptrFromInt(wlr_layer_surface.output.?.data);
- const layer_surface = try util.gpa.create(LayerSurface);
- errdefer util.gpa.destroy(layer_surface);
-
- const layer_tree = server.root.layerSurfaceTree(wlr_layer_surface.current.layer);
-
- layer_surface.* = .{
- .output = output,
- .wlr_layer_surface = wlr_layer_surface,
- .scene_layer_surface = try layer_tree.createSceneLayerSurfaceV1(wlr_layer_surface),
- .popup_tree = try server.root.layers.popups.createSceneTree(),
- };
-
- try SceneNodeData.attach(&layer_surface.scene_layer_surface.tree.node, .{ .layer_surface = layer_surface });
- try SceneNodeData.attach(&layer_surface.popup_tree.node, .{ .layer_surface = layer_surface });
-
- wlr_layer_surface.surface.data = @intFromPtr(&layer_surface.scene_layer_surface.tree.node);
-
- wlr_layer_surface.events.destroy.add(&layer_surface.destroy);
- wlr_layer_surface.surface.events.map.add(&layer_surface.map);
- wlr_layer_surface.surface.events.unmap.add(&layer_surface.unmap);
- wlr_layer_surface.surface.events.commit.add(&layer_surface.commit);
- wlr_layer_surface.events.new_popup.add(&layer_surface.new_popup);
-}
-
-pub fn destroyPopups(layer_surface: *LayerSurface) void {
- var it = layer_surface.wlr_layer_surface.popups.safeIterator(.forward);
- while (it.next()) |wlr_xdg_popup| wlr_xdg_popup.destroy();
-}
-
-fn handleDestroy(listener: *wl.Listener(*wlr.LayerSurfaceV1), _: *wlr.LayerSurfaceV1) void {
- const layer_surface: *LayerSurface = @fieldParentPtr("destroy", listener);
-
- log.debug("layer surface '{s}' destroyed", .{layer_surface.wlr_layer_surface.namespace});
-
- layer_surface.destroy.link.remove();
- layer_surface.map.link.remove();
- layer_surface.unmap.link.remove();
- layer_surface.commit.link.remove();
-
- layer_surface.destroyPopups();
-
- layer_surface.popup_tree.node.destroy();
-
- // The wlr_surface may outlive the wlr_layer_surface so we must clean up the user data.
- layer_surface.wlr_layer_surface.surface.data = 0;
-
- util.gpa.destroy(layer_surface);
-}
-
-fn handleMap(listener: *wl.Listener(void)) void {
- const layer_surface: *LayerSurface = @fieldParentPtr("map", listener);
- const wlr_surface = layer_surface.wlr_layer_surface;
-
- log.debug("layer surface '{s}' mapped", .{wlr_surface.namespace});
-
- layer_surface.output.arrangeLayers();
-
- const consider = wlr_surface.current.keyboard_interactive == .on_demand and
- (wlr_surface.current.layer == .top or wlr_surface.current.layer == .overlay);
- handleKeyboardInteractiveExclusive(if (consider) layer_surface else null);
-
- server.wm.dirtyPending();
-}
-
-fn handleUnmap(listener: *wl.Listener(void)) void {
- const layer_surface: *LayerSurface = @fieldParentPtr("unmap", listener);
-
- log.debug("layer surface '{s}' unmapped", .{layer_surface.wlr_layer_surface.namespace});
-
- layer_surface.output.arrangeLayers();
- handleKeyboardInteractiveExclusive(null);
- server.wm.dirtyPending();
-}
-
-fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
- const layer_surface: *LayerSurface = @fieldParentPtr("commit", listener);
- const wlr_layer_surface = layer_surface.wlr_layer_surface;
-
- assert(wlr_layer_surface.output != null);
-
- // If the layer was changed, move the LayerSurface to the proper tree.
- if (wlr_layer_surface.current.committed.layer) {
- const tree = server.root.layerSurfaceTree(wlr_layer_surface.current.layer);
- layer_surface.scene_layer_surface.tree.node.reparent(tree);
- }
-
- if (wlr_layer_surface.initial_commit or
- @as(u32, @bitCast(wlr_layer_surface.current.committed)) != 0)
- {
- layer_surface.output.arrangeLayers();
- handleKeyboardInteractiveExclusive(null);
- server.wm.dirtyPending();
- }
-}
-
-/// Focus topmost keyboard-interactivity-exclusive layer surface above normal
-/// content, or if none found, focus the surface given as `consider`.
-/// Requires a call to WindowManager.dirtyPending()
-fn handleKeyboardInteractiveExclusive(consider: ?*LayerSurface) void {
- if (server.lock_manager.state != .unlocked) return;
-
- // Find the topmost layer surface (if any) in the top or overlay layers which
- // requests exclusive keyboard interactivity.
- const to_focus = outer: for ([_]zwlr.LayerShellV1.Layer{ .overlay, .top }) |layer| {
- const tree = server.root.layerSurfaceTree(layer);
- // Iterate in reverse to match rendering order.
- var it = tree.children.iterator(.reverse);
- while (it.next()) |node| {
- assert(node.type == .tree);
- if (@as(?*SceneNodeData, @ptrFromInt(node.data))) |node_data| {
- const layer_surface = node_data.data.layer_surface;
- const wlr_layer_surface = layer_surface.wlr_layer_surface;
- if (wlr_layer_surface.surface.mapped and
- wlr_layer_surface.current.keyboard_interactive == .exclusive)
- {
- break :outer layer_surface;
- }
- }
- }
- } else consider;
-
- if (to_focus) |s| {
- assert(s.wlr_layer_surface.current.keyboard_interactive != .none);
- }
-
- var it = server.input_manager.seats.first;
- while (it) |node| : (it = node.next) {
- const seat = &node.data;
-
- if (true) @panic("TODO");
- if (false) {
- if (to_focus) |s| {
- // If we found a surface that requires focus, grab the focus of all seats.
- seat.setFocusRaw(.{ .layer = s });
- continue;
- }
- }
-
- if (seat.focused == .layer) {
- const current_focus = seat.focused.layer.wlr_layer_surface;
- // If the seat is currently focusing an unmapped layer surface or one
- // without keyboard interactivity, stop focusing that layer surface.
- if (!current_focus.surface.mapped or current_focus.current.keyboard_interactive == .none) {
- seat.setFocusRaw(.{ .none = {} });
- }
- }
- }
-}
-
-fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_xdg_popup: *wlr.XdgPopup) void {
- const layer_surface: *LayerSurface = @fieldParentPtr("new_popup", listener);
-
- XdgPopup.create(
- wlr_xdg_popup,
- layer_surface.popup_tree,
- layer_surface.popup_tree,
- ) catch {
- wlr_xdg_popup.resource.postNoMemory();
- return;
- };
-}
diff --git a/river/Output.zig b/river/Output.zig
index 79a7f0a..a34c1fe 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -30,7 +30,6 @@ const zwlr = wayland.server.zwlr;
const server = &@import("main.zig").server;
const util = @import("util.zig");
-const LayerSurface = @import("LayerSurface.zig");
const LockSurface = @import("LockSurface.zig");
const SceneNodeData = @import("SceneNodeData.zig");
const Window = @import("Window.zig");
@@ -47,11 +46,6 @@ all_link: wl.list.Link,
/// For Root.active_outputs
active_link: wl.list.Link,
-/// 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,
-
/// Tracks the currently presented frame on the output as it pertains to ext-session-lock.
/// The output is initially considered blanked:
/// If using the DRM backend it will be blanked with the initial modeset.
@@ -141,12 +135,6 @@ pub fn create(wlr_output: *wlr.Output) !void {
.scene_output = scene_output,
.all_link = undefined,
.active_link = undefined,
- .usable_box = .{
- .x = 0,
- .y = 0,
- .width = width,
- .height = height,
- },
};
wlr_output.data = @intFromPtr(output);
@@ -163,78 +151,6 @@ pub fn create(wlr_output: *wlr.Output) !void {
output.handleEnableDisable();
}
-/// Arrange all layer surfaces of this output and adjust the usable area.
-/// Will arrange windows as well if the usable area changes.
-/// Requires a call to WindowManager.dirtyPending()
-pub fn arrangeLayers(output: *Output) void {
- var full_box: wlr.Box = .{
- .x = 0,
- .y = 0,
- .width = undefined,
- .height = undefined,
- };
- output.wlr_output.effectiveResolution(&full_box.width, &full_box.height);
-
- // This box is modified as exclusive zones are applied
- var usable_box = full_box;
-
- // Ensure all exclusive zones are applied before arranging surfaces
- // without exclusive zones.
- output.sendLayerConfigures(full_box, &usable_box, .exclusive);
- output.sendLayerConfigures(full_box, &usable_box, .non_exclusive);
-
- output.usable_box = usable_box;
-}
-
-fn sendLayerConfigures(
- output: *Output,
- full_box: wlr.Box,
- usable_box: *wlr.Box,
- mode: enum { exclusive, non_exclusive },
-) void {
- if (true) @panic("XXX");
- for ([_]zwlr.LayerShellV1.Layer{ .background, .bottom, .top, .overlay }) |layer| {
- const tree = output.layerSurfaceTree(layer);
- var it = tree.children.safeIterator(.forward);
- while (it.next()) |node| {
- assert(node.type == .tree);
- if (@as(?*SceneNodeData, @ptrFromInt(node.data))) |node_data| {
- const layer_surface = node_data.data.layer_surface;
-
- const exclusive = layer_surface.wlr_layer_surface.current.exclusive_zone > 0;
- if (exclusive != (mode == .exclusive)) {
- continue;
- }
-
- {
- var new_usable_box = usable_box.*;
-
- layer_surface.scene_layer_surface.configure(&full_box, &new_usable_box);
-
- // Clients can request bogus exclusive zones larger than the output
- // dimensions and river must handle this gracefully. It seems reasonable
- // to close layer shell clients that would cause the usable area of the
- // output to become less than half the width/height of its full dimensions.
- if (new_usable_box.width < @divTrunc(full_box.width, 2) or
- new_usable_box.height < @divTrunc(full_box.height, 2))
- {
- layer_surface.wlr_layer_surface.destroy();
- continue;
- }
-
- usable_box.* = new_usable_box;
- }
-
- layer_surface.popup_tree.node.setPosition(
- layer_surface.scene_layer_surface.tree.node.x,
- layer_surface.scene_layer_surface.tree.node.y,
- );
- layer_surface.scene_layer_surface.tree.node.subsurfaceTreeSetClip(&full_box);
- }
- }
- }
-}
-
fn handleDestroy(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
const output: *Output = @fieldParentPtr("destroy", listener);
@@ -289,7 +205,6 @@ pub fn applyState(output: *Output, state: *wlr.Output.State) error{CommitFailed}
}
if (state.committed.mode) {
- output.arrangeLayers();
if (server.lock_manager.lockSurfaceFromOutput(output)) |s| s.configure();
}
}
diff --git a/river/Root.zig b/river/Root.zig
index 4ecf190..c892ece 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -28,7 +28,6 @@ const server = &@import("main.zig").server;
const util = @import("util.zig");
const DragIcon = @import("DragIcon.zig");
-const LayerSurface = @import("LayerSurface.zig");
const LockSurface = @import("LockSurface.zig");
const Output = @import("Output.zig");
const SceneNodeData = @import("SceneNodeData.zig");
diff --git a/river/SceneNodeData.zig b/river/SceneNodeData.zig
index ec28f45..d830f21 100644
--- a/river/SceneNodeData.zig
+++ b/river/SceneNodeData.zig
@@ -22,7 +22,6 @@ const wl = @import("wayland").server.wl;
const util = @import("util.zig");
-const LayerSurface = @import("LayerSurface.zig");
const LockSurface = @import("LockSurface.zig");
const InputPopup = @import("InputPopup.zig");
const Window = @import("Window.zig");
@@ -31,7 +30,6 @@ const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
pub const Data = union(enum) {
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 ff6bdaf..c1694bd 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -33,7 +33,6 @@ const InputManager = @import("InputManager.zig");
const InputRelay = @import("InputRelay.zig");
const Keyboard = @import("Keyboard.zig");
const KeyboardGroup = @import("KeyboardGroup.zig");
-const LayerSurface = @import("LayerSurface.zig");
const LockSurface = @import("LockSurface.zig");
const Mapping = @import("Mapping.zig");
const Output = @import("Output.zig");
@@ -48,7 +47,6 @@ const log = std.log.scoped(.seat);
pub const FocusTarget = union(enum) {
window: *Window,
override_redirect: if (build_options.xwayland) *XwaylandOverrideRedirect else noreturn,
- layer: *LayerSurface,
lock_surface: *LockSurface,
none: void,
@@ -56,7 +54,6 @@ pub const FocusTarget = union(enum) {
return switch (target) {
.window => |window| window.rootSurface(),
.override_redirect => |override_redirect| override_redirect.xsurface.surface,
- .layer => |layer| layer.wlr_layer_surface.surface,
.lock_surface => |lock_surface| lock_surface.wlr_lock_surface.surface,
.none => null,
};
@@ -134,24 +131,6 @@ 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 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 window.
- if (seat.focused == .layer) {
- const wlr_layer_surface = seat.focused.layer.wlr_layer_surface;
- assert(wlr_layer_surface.surface.mapped);
- switch (wlr_layer_surface.current.keyboard_interactive) {
- .none => {},
- .exclusive => switch (wlr_layer_surface.current.layer) {
- .top, .overlay => return,
- .bottom, .background => if (target == null) return,
- _ => {},
- },
- .on_demand => if (target == null) return,
- _ => {},
- }
- }
-
// Focus the target window or clear the focus if target is null
if (target) |window| {
seat.setFocusRaw(.{ .window = window });
@@ -175,9 +154,6 @@ pub fn setFocusRaw(seat: *Seat, new_focus: FocusTarget) void {
//window.pending.focus -= 1; XXX update focus to send activated state
window.destroyPopups();
},
- .layer => |layer_surface| {
- layer_surface.destroyPopups();
- },
.override_redirect, .lock_surface, .none => {},
}
@@ -187,7 +163,6 @@ pub fn setFocusRaw(seat: *Seat, new_focus: FocusTarget) void {
assert(server.lock_manager.state != .locked);
//target_window.pending.focus += 1; XXX update focus to send activated state
},
- .layer => assert(server.lock_manager.state != .locked),
.lock_surface => assert(server.lock_manager.state != .unlocked),
.override_redirect, .none => {},
}
diff --git a/river/Server.zig b/river/Server.zig
index d712364..079e2f5 100644
--- a/river/Server.zig
+++ b/river/Server.zig
@@ -29,7 +29,6 @@ const util = @import("util.zig");
const Config = @import("Config.zig");
const IdleInhibitManager = @import("IdleInhibitManager.zig");
const InputManager = @import("InputManager.zig");
-const LayerSurface = @import("LayerSurface.zig");
const LockManager = @import("LockManager.zig");
const Output = @import("Output.zig");
const Root = @import("Root.zig");
@@ -70,7 +69,6 @@ cursor_shape_manager: *wlr.CursorShapeManagerV1,
xdg_shell: *wlr.XdgShell,
xdg_decoration_manager: *wlr.XdgDecorationManagerV1,
-layer_shell: *wlr.LayerShellV1,
xdg_activation: *wlr.XdgActivationV1,
data_device_manager: *wlr.DataDeviceManager,
@@ -97,8 +95,6 @@ new_xdg_toplevel: wl.Listener(*wlr.XdgToplevel) =
wl.Listener(*wlr.XdgToplevel).init(handleNewXdgToplevel),
new_toplevel_decoration: wl.Listener(*wlr.XdgToplevelDecorationV1) =
wl.Listener(*wlr.XdgToplevelDecorationV1).init(handleNewToplevelDecoration),
-new_layer_surface: wl.Listener(*wlr.LayerSurfaceV1) =
- wl.Listener(*wlr.LayerSurfaceV1).init(handleNewLayerSurface),
request_activate: wl.Listener(*wlr.XdgActivationV1.event.RequestActivate) =
wl.Listener(*wlr.XdgActivationV1.event.RequestActivate).init(handleRequestActivate),
request_set_cursor_shape: wl.Listener(*wlr.CursorShapeManagerV1.event.RequestSetShape) =
@@ -141,7 +137,6 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void {
.xdg_shell = try wlr.XdgShell.create(wl_server, 5),
.xdg_decoration_manager = try wlr.XdgDecorationManagerV1.create(wl_server),
- .layer_shell = try wlr.LayerShellV1.create(wl_server, 4),
.xdg_activation = try wlr.XdgActivationV1.create(wl_server),
.data_device_manager = try wlr.DataDeviceManager.create(wl_server),
@@ -185,7 +180,6 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void {
server.xdg_shell.events.new_toplevel.add(&server.new_xdg_toplevel);
server.xdg_decoration_manager.events.new_toplevel_decoration.add(&server.new_toplevel_decoration);
- server.layer_shell.events.new_surface.add(&server.new_layer_surface);
server.xdg_activation.events.request_activate.add(&server.request_activate);
server.cursor_shape_manager.events.request_set_shape.add(&server.request_set_cursor_shape);
@@ -199,7 +193,6 @@ pub fn deinit(server: *Server) void {
server.new_xdg_toplevel.link.remove();
server.new_toplevel_decoration.link.remove();
- server.new_layer_surface.link.remove();
server.request_activate.link.remove();
server.request_set_cursor_shape.link.remove();
@@ -310,7 +303,6 @@ fn allowlist(server: *Server, global: *const wl.Global) bool {
/// Returns true if the global is blocked for security contexts
fn blocklist(server: *Server, global: *const wl.Global) bool {
return global == server.security_context_manager.global or
- global == server.layer_shell.global or
global == server.foreign_toplevel_manager.global or
global == server.screencopy_manager.global or
global == server.export_dmabuf_manager.global or
@@ -348,44 +340,6 @@ fn handleNewToplevelDecoration(
XdgDecoration.init(wlr_decoration);
}
-fn handleNewLayerSurface(_: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: *wlr.LayerSurfaceV1) void {
- log.debug(
- "new layer surface: namespace {s}, layer {s}, anchor {b:0>4}, size {},{}, margin {},{},{},{}, exclusive_zone {}",
- .{
- wlr_layer_surface.namespace,
- @tagName(wlr_layer_surface.current.layer),
- @as(u32, @bitCast(wlr_layer_surface.current.anchor)),
- wlr_layer_surface.current.desired_width,
- wlr_layer_surface.current.desired_height,
- wlr_layer_surface.current.margin.top,
- wlr_layer_surface.current.margin.right,
- wlr_layer_surface.current.margin.bottom,
- wlr_layer_surface.current.margin.left,
- wlr_layer_surface.current.exclusive_zone,
- },
- );
-
- // If the new layer surface does not have an output assigned to it, use the
- // first output or close the surface if none are available.
- if (wlr_layer_surface.output == null) {
- if (true) @panic("TODO");
-
- const output = null orelse {
- log.err("no output available for layer surface '{s}'", .{wlr_layer_surface.namespace});
- wlr_layer_surface.destroy();
- return;
- };
-
- log.debug("new layer surface had null output, assigning it to output '{s}'", .{output.wlr_output.name});
- wlr_layer_surface.output = output.wlr_output;
- }
-
- LayerSurface.create(wlr_layer_surface) catch {
- wlr_layer_surface.resource.postNoMemory();
- return;
- };
-}
-
fn handleNewXwaylandSurface(_: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wlr.XwaylandSurface) void {
log.debug(
"new xwayland surface: title='{?s}', class='{?s}', override redirect={}",
diff --git a/river/XdgPopup.zig b/river/XdgPopup.zig
index b14e1e5..07bc363 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 Window or LayerSurface popup_tree.
+/// The root of the surface tree, i.e. the Window's popup_tree
root: *wlr.SceneTree,
tree: *wlr.SceneTree,
@@ -97,7 +97,6 @@ fn handleReposition(listener: *wl.Listener(void)) void {
const output = switch (SceneNodeData.fromNode(&xdg_popup.root.node).?.data) {
.window => |_| @panic("TODO"),
- .layer_surface => |layer_surface| layer_surface.output,
else => unreachable,
};