git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commite576d48bfb9a9c01b39c6dfa7fc6798952448d45
parent2dfdc9f20b
authorIsaac Freund <[email protected]>
date2024-09-16 21:39
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,
     };