commit 38ed525193cd2c56466581181b93c3caf1f53dcb Author: Blendi Date: Mon May 4 20:28:10 2026 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8742321 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# SPDX-FileCopyrightText: © 2026 FireFly +# SPDX-License-Identifier: 0BSD +tinyrwm/protocol/*.lua diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb4929d --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ + + +# tinyrwm.lua + +Tiny river window manager implemented in Lua. + +## Dependencies + +System dependencies: +- lua (5.4 tested) +- luarocks +- libwayland +- libxkbcommon + +The lua-ecosystem dependencies should be handled by luarocks. + +## Building + +To fetch lua dependencies, build, and install to `~/.luarocks/bin`, run: + +```sh +eval $(luarocks --path bin) +luarocks --local make +``` + +## Running + +Make sure libxkbcommon.so and libwayland-client.so are present in +`LD_LIBRARY_PATH` (and `river` and `foot` in your `PATH`). You should be able +to run river with the installed Lua tinyrwm with + +```sh +river -c ~/.luarocks/bin/tinyrwm +``` diff --git a/planar-dev-1.rockspec b/planar-dev-1.rockspec new file mode 100644 index 0000000..4feb23c --- /dev/null +++ b/planar-dev-1.rockspec @@ -0,0 +1,44 @@ +-- SPDX-FileCopyrightText: © 2026 FireFly +-- SPDX-License-Identifier: 0BSD + +package = "planar" +version = "dev-1" +rockspec_format = "3.0" + +source = { + url = "", +} + +description = { + summary = "stupid stupid", + homepage = "", + license = "0BSD", +} + +dependencies = { + "lua == 5.4", + "cffi-lua >= 0.2.4", + "firefly/wau", + "luaposix", +} + +external_dependencies = { + -- runtime dependencies: ensure these are in your LD_LIBRARY_PATH + -- XKBCOMMON = { library = "libxkbcommon.so" }, + -- WAYLAND = { library = "libwayland-client.so" }, +} + +build = { + type = "command", + build_command = [[ + for f in planar/protocol/*.xml; do + wau-scanner <$f >${f%%.xml}.lua + done + ]], + install_command = [[ + # mimic build.type == "builtin" behaviour + install -Dm644 planar/xkbcommon.lua $(LUADIR)/planar/xkbcommon.lua + install -Dm644 -t $(LUADIR)/planar/protocol planar/protocol/*.lua + install -Dm755 planar.lua $(BINDIR)/planar + ]], +} diff --git a/planar.lua b/planar.lua new file mode 100755 index 0000000..6390bc3 --- /dev/null +++ b/planar.lua @@ -0,0 +1,538 @@ +#! /usr/bin/env lua +-- SPDX-FileCopyrightText: © 2026 FireFly +-- SPDX-License-Identifier: 0BSD + +local wau = require("wau") +local xkbcommon = require("planar.xkbcommon") +local posix = require("posix") + +wau:require("planar.protocol.river-window-management-v1") +wau:require("planar.protocol.river-xkb-bindings-v1") + +local globals = {} +local required_globals = { + ["river_window_manager_v1"] = 4, + ["river_xkb_bindings_v1"] = 1, +} + +local Mods = wau.river_seat_v1.Modifiers + +local xkb_bindings = { + {"space", Mods.MOD1, "spawn-foot"}, + {"q", Mods.MOD1, "close"}, + {"r", Mods.MOD1, "reset-view"}, + {"Escape", Mods.MOD1, "exit"}, +} + +local pointer_bindings = { + {"left", Mods.MOD1, "move"}, + {"right", Mods.MOD1, "resize"}, +} + +local wm = { + outputs = {}, + seats = {}, + -- Windows are kept in rendering order; last window is topmost + windows = {}, + cam = {x = 0, y = 0, dirty = false}, +} + +local function table_index_of(tbl, sought) + for i, v in ipairs(tbl) do + if v == sought then return i end + end + return 0 +end + +local function table_filter_inplace(tbl, pred) + local removed = 0 + for i=1,#tbl do + if pred(tbl[i]) then + tbl[i - removed] = tbl[i] + else + removed = removed + 1 + end + if removed > 0 then tbl[i] = nil end + end + return tbl +end + + +---- Output --------------------------- +local Output = { mt = {}, listener = {} } +Output.mt.__index = Output + +function Output.create(obj) + local output = { obj = obj } + setmetatable(output, Output.mt) + obj:set_user_data(output) + obj:add_listener(Output.listener) + return output +end + +function Output:maybe_destroy() + if self.removed then + self.obj:destroy() + else + return self + end +end + +function Output.listener:removed() + self:get_user_data().removed = true +end + +---- Window --------------------------- +local Window = { mt = {}, listener = {} } +Window.mt.__index = Window + +function Window.create(obj) + local window = { + obj = obj, + node = obj:get_node(), + new = true, + } + setmetatable(window, Window.mt) + obj:set_user_data(window) + obj:add_listener(Window.listener) + return window +end + +function Window:maybe_destroy() + if self.closed then + self.obj:destroy() + self.node:destroy() + else + return self + end +end + +function Window:manage() + if self.new then + for i = 1,#wm.outputs do + local output = wm.outputs[i] + for k,v in pairs(output) do print(k,v) end + end + + self.new = nil + self:set_position(wm.cam.x, wm.cam.y) + self.obj:propose_dimensions(0, 0) + end + + local move = self.pointer_move_requested + if move ~= nil then + self.pointer_move_requested = nil + move.seat:pointer_move(self) + end + + local resize = self.pointer_resize_requested + if resize ~= nil then + self.pointer_resize_requested = nil + resize.seat:pointer_resize(self, resize.edges) + end +end + +function Window:set_position(x, y) + self.node:set_position(x - wm.cam.x, y - wm.cam.y) + self.x = x + self.y = y +end + +function Window.listener:closed() + self:get_user_data().closed = true +end +function Window.listener:dimensions(width, height) + local window = self:get_user_data() + window.width = width + window.height = height +end +function Window.listener:pointer_move_requested(seat) + self:get_user_data().pointer_move_requested = { + seat = seat:get_user_data(), + } +end +function Window.listener:pointer_resize_requested(seat, edges) + local Edges = wau.river_window_v1.Edges + self:get_user_data().pointer_resize_requested = { + seat = seat:get_user_data(), + edges = { + left = (edges & Edges.LEFT) ~= 0, + right = (edges & Edges.RIGHT) ~= 0, + top = (edges & Edges.TOP) ~= 0, + bottom = (edges & Edges.BOTTOM) ~= 0, + }, + } +end + + +---- Seat ----------------------------- +local Seat = { mt = {}, listener = {} } +Seat.mt.__index = Seat + +function Seat.create(obj) + local seat = { + obj = obj, + new = true, + xkb_bindings = {}, + pointer_bindings = {}, + } + setmetatable(seat, Seat.mt) + obj:set_user_data(seat) + obj:add_listener(Seat.listener) + return seat +end + +function Seat:focus(window) + if window == nil and #wm.windows > 0 then + -- Fall back to topmost window + window = wm.windows[#wm.windows] + end + + if window then + if self.focused ~= window then + self.obj:focus_window(window.obj) + self.focused = window + -- Move to top + local i = table_index_of(wm.windows, window) + table.remove(wm.windows, i) + table.insert(wm.windows, window) + window.node:place_top() + end + else + self.obj:clear_focus() + self.focused = nil + end +end + +function Seat:pointer_move(window) + if window then + if self.op == nil then + self:focus(window) + self.obj:op_start_pointer() + self.op = { + type = "move", + window = window, + start = { x = window.x, y = window.y }, + dx = 0, + dy = 0, + } + end + else + if self.op == nil then + self:focus(window) + self.obj:op_start_pointer() + self.op = { + type = "world_move", + dx = 0, + dy = 0, + pdx = 0, + pdy = 0 + } + end + end +end + +function Seat:pointer_resize(window, edges) + if self.op == nil then + self:focus(window) + window.obj:inform_resize_start() + self.obj:op_start_pointer() + self.op = { + type = "resize", + window = window, + edges = edges, + start = { + x = window.x, + y = window.y, + width = window.width, + height = window.height, + }, + dx = 0, + dy = 0, + } + end +end + +function Seat:action(action) + if action == "spawn-foot" then + if posix.unistd.fork() == 0 then + posix.unistd.execp("foot", {}) + end + elseif action == "reset-view" then + wm.cam.x = 0 + wm.cam.y = 0 + wm.cam.dirty = true; + elseif action == "close" then + if self.focused ~= nil then + self.focused.obj:close() + end + elseif action == "focus-next" then + self:focus(wm.windows[1]) + elseif action == "move" then + -- if self.hovered ~= nil then + self:pointer_move(self.hovered) + -- end + elseif action == "resize" then + if self.hovered ~= nil then + self:pointer_resize(self.hovered, { bottom = true, right = true }) + end + elseif action == "exit" then + globals["river_window_manager_v1"]:exit_session() + else + print("Seat:action: unimplemented", action) + end +end + +function Seat:add_pointer_binding(button, mods, action) + -- From /usr/include/linux/input-event-codes.h + local button_code = ({ left = 0x110, right = 0x111 })[button] + local obj = self.obj:get_pointer_binding(button_code, mods) + local binding = { obj = obj } + + obj:add_listener { + ["pressed"] = function (_) + self.pending_action = action + end, + } + obj:enable() + table.insert(self.pointer_bindings, binding) +end + +function Seat:add_xkb_binding(key, mods, action) + local keysym = xkbcommon.keysym(key) + local obj = globals["river_xkb_bindings_v1"]:get_xkb_binding( + self.obj, keysym, mods) + local binding = { obj = obj } + + obj:add_listener { + ["pressed"] = function (_) + self.pending_action = action + end, + } + obj:enable() + table.insert(self.xkb_bindings, binding) +end + +function Seat:manage() + if self.new then + self.new = nil + + for _, tbl in ipairs(xkb_bindings) do + self:add_xkb_binding(table.unpack(tbl)) + end + + for _, tbl in ipairs(pointer_bindings) do + self:add_pointer_binding(table.unpack(tbl)) + end + end + + if self.focused and self.focused.closed then + self.focused = nil + end + + self:focus(self.interacted) + self.interacted = nil + + if self.pending_action ~= nil then + self:action(self.pending_action) + self.pending_action = nil + end + + if self.op then + local op, window = self.op, self.op.window + local window = self.op.window + + if window and window.closed then + self.obj:op_end() + self.op = nil + + elseif self.op_release then + if window and op.type == "resize" then + window.obj:inform_resize_end() + end + self.obj:op_end() + self.op = nil + + elseif window and op.type == "resize" then + local width = math.max( + 1, + op.edges.left and (op.start.width - op.dx) or + op.edges.right and (op.start.width + op.dx) or + op.start.width + ) + local height = math.max( + 1, + op.edges.top and (op.start.height - op.dy) or + op.edges.bottom and (op.start.height + op.dy) or + op.start.height + ) + window.obj:propose_dimensions(width, height) + end + end + + self.op_release = nil +end + +function Seat:render() + if self.op then + local op, window = self.op, self.op.window + if window and self.op.type == "move" then + window:set_position( + op.start.x + op.dx, + op.start.y + op.dy + ) + elseif window and self.op.type == "resize" then + local x = op.edges.left + and (op.start.x + (op.start.width - window.width)) + or op.start.x + local y = op.edges.top + and (op.start.y + (op.start.height - window.height)) + or op.start.y + window:set_position(x, y) + elseif self.op.type == "world_move" then + local adx, ady = op.dx - op.pdx, op.dy - op.pdy + + wm.cam.x = wm.cam.x - adx -- TODO: make sure should be minus + wm.cam.y = wm.cam.y - ady + + wm.cam.dirty = true; + + op.pdx, op.pdy = op.dx, op.dy + end + end +end + +function Seat:maybe_destroy() + if self.removed then + for _, binding in ipairs(self.xkb_bindings) do + binding.obj:destroy() + end + for _, binding in ipairs(self.pointer_bindings) do + binding.obj:destroy() + end + self.obj:destroy() + else + return self + end +end + +function Seat.listener.removed(self) + self:get_user_data().removed = true +end +function Seat.listener.pointer_enter(self, window) + self:get_user_data().hovered = window:get_user_data() +end +function Seat.listener.pointer_leave(self) + self:get_user_data().hovered = nil +end +function Seat.listener.window_interaction(self, window) + self:get_user_data().interacted = window:get_user_data() +end +function Seat.listener.op_delta(self, dx, dy) + local seat = self:get_user_data() + seat.op.dx = dx + seat.op.dy = dy +end +function Seat.listener.op_release(self) + self:get_user_data().op_release = true +end + + +---- wm ------------------------------- +local function wm_manage() + table_filter_inplace(wm.outputs, Output.maybe_destroy) + table_filter_inplace(wm.windows, Window.maybe_destroy) + table_filter_inplace(wm.seats, Seat.maybe_destroy) + + for _, window in ipairs(wm.windows) do + window:manage() + end + + for _, seat in ipairs(wm.seats) do + seat:manage() + end + + globals["river_window_manager_v1"]:manage_finish() +end + +local function wm_render() + if wm.cam.dirty then + for i = 1,#wm.windows do + local window = wm.windows[i] + + window.node:set_position(window.x - wm.cam.x, window.y - wm.cam.y); + end + wm.cam.dirty = false; + end + + for _, seat in ipairs(wm.seats) do + seat:render() + end + + globals["river_window_manager_v1"]:render_finish() +end + +local wm_handlers = { + ["unavailable"] = function (self) + io.stderr:write("another window manager is already running\n") + os.exit(1) + end, + ["finished"] = function (self) + os.exit(0) + end, + ["manage_start"] = wm_manage, + ["render_start"] = wm_render, + ["output"] = function (self, obj) + table.insert(wm.outputs, Output.create(obj)) + end, + ["seat"] = function (self, obj) + table.insert(wm.seats, Seat.create(obj)) + end, + ["window"] = function (self, obj) + table.insert(wm.windows, Window.create(obj)) + end, +} + + +---- Entry point ---------------------- +display = wau.wl_display.connect() +assert(display, "Failed to connect to wayland compositor") + +-- Ensure we exit nonzero if an event handler errors +local function handle_callback_error(proxy, name, func, err) + io.stderr:write(("-- Error calling event handler for %s %q:") + :format(tostring(proxy), name)) + io.stderr:write(("%s\n"):format(tostring(err))) + os.exit(1) +end +wau.wl_proxy.set_error_callback(handle_callback_error) + +-- Avoid passing WAYLAND_DEBUG to our children +posix.stdlib.setenv("WAYLAND_DEBUG", nil) + +-- Ensure children are automatically reaped +posix.signal.signal(posix.signal.SIGCHLD, posix.signal.SIG_IGN) + +local registry = display:get_registry() +registry:add_listener { + ["global"] = function (self, name, iface, version) + local required_version = required_globals[iface] + if required_version ~= nil then + assert(required_version <= version, + ("wayland compositor supported %s version too old (need %d, got %d)") + :format(iface, required_version, version)) + globals[iface] = self:bind(name, wau[iface], required_version) + end + end, +} + +display:roundtrip() + +for k in pairs(required_globals) do + assert(globals[k] ~= nil, ("wayland compositor does not support %s"):format(k)) +end + +globals["river_window_manager_v1"]:add_listener(wm_handlers) + +while display:dispatch() do end + diff --git a/planar/protocol/river-window-management-v1.lua b/planar/protocol/river-window-management-v1.lua new file mode 100644 index 0000000..2b65ce8 --- /dev/null +++ b/planar/protocol/river-window-management-v1.lua @@ -0,0 +1,2107 @@ +-- Auto generated by the wau-scanner v0 + +--- river_window_management_v1 +-- @module river_window_management_v1 + +-- SPDX-FileCopyrightText: © 2024 Isaac Freund +-- SPDX-License-Identifier: MIT +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to +-- deal in the Software without restriction, including without limitation the +-- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +-- sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- The above copyright notice and this permission notice shall be included in +-- all copies or substantial portions of the Software. +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +-- IN THE SOFTWARE. +return function(wau) + +local interfaces = { + "river_window_manager_v1", + "river_window_v1", + "river_decoration_v1", + "river_shell_surface_v1", + "river_node_v1", + "river_output_v1", + "river_seat_v1", + "river_pointer_binding_v1", +} + +for _, iface in ipairs(interfaces) do + wau[iface] = wau.wl_interface.new() +end + +--- window manager global interface +-- +-- This global interface should only be advertised to the window manager +-- process. Only one window management client may be active at a time. The +-- compositor should use the unavailable event if necessary to enforce this. +-- There are two disjoint categories of state managed by this protocol: +-- Window management state influences the communication between the +-- compositor and individual windows (e.g. xdg_toplevels). Window management +-- state includes window dimensions, fullscreen state, keyboard focus, +-- keyboard bindings, and more. +-- Rendering state only affects the rendered output of the compositor and +-- does not influence communication between the compositor and individual +-- windows. Rendering state includes the position and rendering order of +-- windows, shell surfaces, decoration surfaces, borders, and more. +-- Window management state may only be modified by the window manager as part +-- of a manage sequence. A manage sequence is started with the manage_start +-- event and ended with the manage_finish request. It is a protocol error to +-- modify window management state outside of a manage sequence. +-- A manage sequence is always followed by at least one render sequence. A +-- render sequence is started with the render_start event and ended with the +-- render_finish request. +-- Rendering state may be modified by the window manager during a manage +-- sequence or a render sequence. Regardless of when the rendering state is +-- modified, it is applied with the next render_finish request. It is a +-- protocol error to modify rendering state outside of a manage or render +-- sequence. +-- The server will start a manage sequence by sending new state and the +-- manage_start event as soon as possible whenever there is a change in state +-- that must be communicated with the window manager. +-- If the window manager client needs to ensure a manage sequence is started +-- due to a state change the compositor is not aware of, it may send the +-- manage_dirty request. +-- The server will start a render sequence by sending new state and the +-- render_start event as soon as possible whenever there is a change in +-- window dimensions that must be communicated with the window manager. +-- Multiple render sequences may be made consecutively without a manage +-- sequence in between, for example if a window independently changes its own +-- dimensions. +-- To summarize, the main loop of this protocol is as follows: +-- 1. The server sends events indicating all changes since the last +-- manage sequence followed by the manage_start event. +-- 2. The client sends requests modifying window management state or +-- rendering state (as defined above) followed by the manage_finish +-- request. +-- 3. The server sends new state to windows and waits for responses. +-- 4. The server sends new window dimensions to the client followed by the +-- render_start event. +-- 5. The client sends requests modifying rendering state (as defined above) +-- followed by the render_finish request. +-- 6. If window dimensions change, loop back to step 4. +-- If state that requires a manage sequence changes or if the client makes +-- a manage_dirty request, loop back to step 1. +-- For the purposes of frame perfection, the server may delay rendering new +-- state committed by the windows in step 3 until after step 5 is finished. +-- It is a protocol error for the client to make a manage_finish or +-- render_finish request that violates this ordering. +-- @type river_window_manager_v1 +wau.river_window_manager_v1:init { + name = "river_window_manager_v1", + version = 4, + methods = { + --- stop sending events + -- + -- This request indicates that the client no longer wishes to receive + -- events on this object. + -- The Wayland protocol is asynchronous, which means the server may send + -- further events until the stop request is processed. The client must wait + -- for a river_window_manager_v1.finished event before destroying this + -- object. + -- @function river_window_manager_v1:stop + -- @treturn river_window_manager_v1 self + { + name = "stop", + signature = "", + types = { }, + }, + --- destroy the river_window_manager_v1 object + -- + -- This request should be called after the finished event has been received + -- to complete destruction of the object. + -- If a client wishes to destroy this object it should send a + -- river_window_manager_v1.stop request and wait for a + -- river_window_manager_v1.finished event. Once the finished event is + -- received it is safe to destroy this object and any other objects created + -- through this interface. + -- @function river_window_manager_v1:destroy + -- @treturn river_window_manager_v1 self + { + name = "destroy", + signature = "", + types = { }, + type = "destructor" + }, + --- finish a manage sequence + -- + -- This request indicates that the client has made all changes to window + -- management state it wishes to include in the current manage sequence and + -- that the server should atomically send these state changes to the + -- windows and continue with the manage sequence. + -- After sending this request, it is a protocol error for the client to + -- make further changes to window management state until the next + -- manage_start event is received. + -- See the description of the river_window_manager_v1 interface for a + -- complete overview of the manage/render sequence loop. + -- @function river_window_manager_v1:manage_finish + -- @treturn river_window_manager_v1 self + { + name = "manage_finish", + signature = "", + types = { }, + }, + --- ensure a manage sequence is started + -- + -- This request ensures a manage sequence is started and that a + -- manage_start event is sent by the server. If this request is made during + -- an ongoing manage sequence, a new manage sequence will be started as + -- soon as the current one is completed. + -- The client may want to use this request due to an internal state change + -- that the compositor is not aware of (e.g. a dbus event) which should + -- affect window management or rendering state. + -- @function river_window_manager_v1:manage_dirty + -- @treturn river_window_manager_v1 self + { + name = "manage_dirty", + signature = "", + types = { }, + }, + --- finish a render sequence + -- + -- This request indicates that the client has made all changes to rendering + -- state it wishes to include in the current manage sequence and that the + -- server should atomically apply and display these state changes to the + -- user. + -- After sending this request, it is a protocol error for the client to + -- make further changes to rendering state until the next manage_start or + -- render_start event is received, whichever comes first. + -- See the description of the river_window_manager_v1 interface for a + -- complete overview of the manage/render sequence loop. + -- @function river_window_manager_v1:render_finish + -- @treturn river_window_manager_v1 self + { + name = "render_finish", + signature = "", + types = { }, + }, + --- assign the river_shell_surface_v1 surface role + -- + -- Create a new shell surface for window manager UI and assign the + -- river_shell_surface_v1 role to the surface. + -- Providing a wl_surface which already has a role or already has a buffer + -- attached or committed is a protocol error. + -- @function river_window_manager_v1:get_shell_surface + -- @treturn river_shell_surface_v1 + -- @tparam wl_surface surface base surface + { + name = "get_shell_surface", + signature = "no", + types = { wau.river_shell_surface_v1, wau.wl_surface, }, + }, + --- exit the Wayland session + -- + -- End the current Wayland session and exit the compositor. + -- All Wayland clients running in the current session, including + -- the window manager, will be disconnected. + -- Window managers should only make this request if the user explicitly + -- asks to exit the Wayland session, not for example on normal window + -- manager termination. + -- @function river_window_manager_v1:exit_session + -- @treturn river_window_manager_v1 self + { + name = "exit_session", + signature = "4", + types = { }, + }, + }, + events = { + --- window management unavailable + -- + -- This event indicates that window management is not available to the + -- client, perhaps due to another window management client already running. + -- The circumstances causing this event to be sent are compositor policy. + -- If sent, this event is guaranteed to be the first and only event sent by + -- the server. + -- The server will send no further events on this object. The client should + -- destroy this object and all objects created through this interface. + -- @event river_window_manager_v1:unavailable + { + name = "unavailable", + signature = "", + types = { }, + }, + --- the server has finished with the window manager + -- + -- This event indicates that the server will send no further events on this + -- object. The client should destroy the object. See + -- river_window_manager_v1.destroy for more information. + -- @event river_window_manager_v1:finished + { + name = "finished", + signature = "", + types = { }, + }, + --- start a manage sequence + -- + -- This event indicates that the server has sent events indicating all + -- state changes since the last manage sequence. + -- In response to this event, the client should make requests modifying + -- window management state as it chooses. Then, the client must make the + -- manage_finish request. + -- See the description of the river_window_manager_v1 interface for a + -- complete overview of the manage/render sequence loop. + -- @event river_window_manager_v1:manage_start + { + name = "manage_start", + signature = "", + types = { }, + }, + --- start a render sequence + -- + -- This event indicates that the server has sent all river_node_v1.position + -- and river_window_v1.dimensions events necessary. + -- In response to this event, the client should make requests modifying + -- rendering state as it chooses. Then, the client must make the + -- render_finish request. + -- See the description of the river_window_manager_v1 interface for a + -- complete overview of the manage/render sequence loop. + -- @event river_window_manager_v1:render_start + { + name = "render_start", + signature = "", + types = { }, + }, + --- the session has been locked + -- + -- This event indicates that the session has been locked. + -- The window manager may wish to restrict which key bindings are available + -- while locked or otherwise use this information. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_manager_v1:session_locked + { + name = "session_locked", + signature = "", + types = { }, + }, + --- the session has been unlocked + -- + -- This event indicates that the session has been unlocked. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_manager_v1:session_unlocked + { + name = "session_unlocked", + signature = "", + types = { }, + }, + --- new window + -- + -- A new window has been created. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_manager_v1:window + -- @tparam river_window_v1 id new window + { + name = "window", + signature = "n", + types = { wau.river_window_v1, }, + }, + --- new output + -- + -- A new logical output has been created, perhaps due to a new physical + -- monitor being plugged in or perhaps due to a change in configuration. + -- This event will be followed by river_output_v1.position and dimensions + -- events as well as a manage_start event after all other new state has + -- been sent by the server. + -- @event river_window_manager_v1:output + -- @tparam river_output_v1 id new output + { + name = "output", + signature = "n", + types = { wau.river_output_v1, }, + }, + --- new seat + -- + -- A new seat has been created. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_manager_v1:seat + -- @tparam river_seat_v1 id new seat + { + name = "seat", + signature = "n", + types = { wau.river_seat_v1, }, + }, + }, + enums = { + --- error + -- @enum river_window_manager_v1.Error + -- @param SEQUENCE_ORDER 0 request violates manage/render sequence ordering + -- @param ROLE 1 given wl_surface already has a role + -- @param UNRESPONSIVE 2 window manager unresponsive + ["error"] = { + ["sequence_order"] = 0, + ["role"] = 1, + ["unresponsive"] = 2, + }, + }, + methods_opcode = { + ["stop"] = 0, + ["destroy"] = 1, + ["manage_finish"] = 2, + ["manage_dirty"] = 3, + ["render_finish"] = 4, + ["get_shell_surface"] = 5, + ["exit_session"] = 6, + }, +} + +--- a logical window +-- +-- This represents a logical window. For example, a window may correspond to +-- an xdg_toplevel or Xwayland window. +-- A newly created window will not be displayed until the window manager +-- makes a propose_dimensions or fullscreen request as part of a manage +-- sequence, the server replies with a dimensions event as part of a render +-- sequence, and that render sequence is finished. +-- @type river_window_v1 +wau.river_window_v1:init { + name = "river_window_v1", + version = 4, + methods = { + --- destroy the window object + -- + -- This request indicates that the client will no longer use the window + -- object and that it may be safely destroyed. + -- This request should be made after the river_window_v1.closed event or + -- river_window_manager_v1.finished is received to complete destruction of + -- the window. + -- @function river_window_v1:destroy + -- @treturn river_window_v1 self + { + name = "destroy", + signature = "", + types = { }, + type = "destructor" + }, + --- request that the window be closed + -- + -- Request that the window be closed. The window may ignore this request or + -- only close after some delay, perhaps opening a dialog asking the user to + -- save their work or similar. + -- The server will send a river_window_v1.closed event if/when the window + -- has been closed. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:close + -- @treturn river_window_v1 self + { + name = "close", + signature = "", + types = { }, + }, + --- get the window's render list node + -- + -- Get the node in the render list corresponding to the window. + -- It is a protocol error to make this request more than once for a single + -- window. + -- @function river_window_v1:get_node + -- @treturn river_node_v1 + { + name = "get_node", + signature = "n", + types = { wau.river_node_v1, }, + }, + --- propose window dimensions + -- + -- This request proposes dimensions for the window in the compositor's + -- logical coordinate space. + -- The width and height must be greater than or equal to zero. If the width + -- or height is zero the window will be allowed to decide its own + -- dimensions. + -- The window may not take the exact dimensions proposed. The actual + -- dimensions taken by the window will be sent in a subsequent + -- river_window_v1.dimensions event. For example, a terminal emulator may + -- only allow dimensions that are multiple of the cell size. + -- When a propose_dimensions request is made, the server must send a + -- dimensions event in response as soon as possible. It may not be possible + -- to send a dimensions event in the very next render sequence if, for + -- example, the window takes too long to respond to the proposed + -- dimensions. In this case, the server will send the dimensions event in a + -- future render sequence. + -- Note that the dimensions of a river_window_v1 refer to the dimensions of + -- the window content and are unaffected by the presence of borders or + -- decoration surfaces. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:propose_dimensions + -- @tparam int width proposed content width + -- @tparam int height proposed content height + -- @treturn river_window_v1 self + { + name = "propose_dimensions", + signature = "ii", + types = { 0, 0, }, + }, + --- request that the window be hidden + -- + -- Request that the window be hidden. Has no effect if the window is + -- already hidden. Hides any window borders and decorations as well. + -- Newly created windows are considered shown unless explicitly hidden with + -- the hide request. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:hide + -- @treturn river_window_v1 self + { + name = "hide", + signature = "", + types = { }, + }, + --- request that the window be shown + -- + -- Request that the window be shown. Has no effect if the window is not + -- hidden. Does not guarantee that the window is visible as it may be + -- completely obscured by other windows placed above it for example. + -- Newly created windows are considered shown unless explicitly hidden with + -- the hide request. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:show + -- @treturn river_window_v1 self + { + name = "show", + signature = "", + types = { }, + }, + --- tell the client to use CSD + -- + -- Tell the client to use client side decoration and draw its own title + -- bar, borders, etc. + -- This is the default if neither this request nor the use_ssd request is + -- ever made. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:use_csd + -- @treturn river_window_v1 self + { + name = "use_csd", + signature = "", + types = { }, + }, + --- tell the client to use SSD + -- + -- Tell the client to use server side decoration and not draw any client + -- side decorations. + -- This request will have no effect if the client only supports client side + -- decoration, see the decoration_hint event. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:use_ssd + -- @treturn river_window_v1 self + { + name = "use_ssd", + signature = "", + types = { }, + }, + --- set window borders + -- + -- This request decorates the window with borders drawn by the compositor + -- on the specified edges of the window. Borders are drawn above the window + -- content. + -- Corners are drawn only between borders on adjacent edges. If e.g. the + -- left edge has a border and the top edge does not, the border drawn on + -- the left edge will not extend vertically beyond the top edge of the + -- window. + -- Borders are not drawn while the window is fullscreen. + -- The color is defined by four 32-bit RGBA values. Unless specified in + -- another protocol extension, the RGBA values use pre-multiplied alpha. + -- Setting the edges to none or the width to 0 disables the borders. + -- Setting a negative width is a protocol error. + -- This request completely overrides all previous set_borders requests. + -- Only the most recent set_borders request has an effect. + -- Note that the position/dimensions of a river_window_v1 refer to the + -- position/dimensions of the window content and are unaffected by the + -- presence of borders or decoration surfaces. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:set_borders + -- @tparam uint edges border edges + -- @tparam int width border width + -- @tparam uint r 32-bit red value + -- @tparam uint g 32-bit green value + -- @tparam uint b 32-bit blue value + -- @tparam uint a 32-bit alpha value + -- @treturn river_window_v1 self + { + name = "set_borders", + signature = "uiuuuu", + types = { 0, 0, 0, 0, 0, 0, }, + }, + --- set window tiled state + -- + -- Inform the window that it is part of a tiled layout and adjacent to + -- other elements in the tiled layout on the given edges. + -- The window should use this information to change the style of its client + -- side decorations and avoid drawing e.g. drop shadows outside of the + -- window dimensions on the tiled edges. + -- Setting the edges argument to none informs the window that it is not + -- part of a tiled layout. If this request is never made, the window is + -- informed that it is not part of a tiled layout. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:set_tiled + -- @tparam uint edges tiled edges + -- @treturn river_window_v1 self + { + name = "set_tiled", + signature = "u", + types = { 0, }, + }, + --- create a decoration above the window in z-order + -- + -- Create a decoration surface and assign the river_decoration_v1 role to + -- the surface. The created decoration is placed above the window in + -- rendering order, see the description of river_decoration_v1. + -- Providing a wl_surface which already has a role or already has a buffer + -- attached or committed is a protocol error. + -- @function river_window_v1:get_decoration_above + -- @treturn river_decoration_v1 + -- @tparam wl_surface surface base surface + { + name = "get_decoration_above", + signature = "no", + types = { wau.river_decoration_v1, wau.wl_surface, }, + }, + --- create a decoration below the window in z-order + -- + -- Create a decoration surface and assign the river_decoration_v1 role to + -- the surface. The created decoration is placed below the window in + -- rendering order, see the description of river_decoration_v1. + -- Providing a wl_surface which already has a role or already has a buffer + -- attached or committed is a protocol error. + -- @function river_window_v1:get_decoration_below + -- @treturn river_decoration_v1 + -- @tparam wl_surface surface base surface + { + name = "get_decoration_below", + signature = "no", + types = { wau.river_decoration_v1, wau.wl_surface, }, + }, + --- inform the window it is being resized + -- + -- Inform the window that it is being resized. The window manager should + -- use this request to inform windows that are the target of an interactive + -- resize for example. + -- The window manager remains responsible for handling the position and + -- dimensions of the window while it is resizing. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:inform_resize_start + -- @treturn river_window_v1 self + { + name = "inform_resize_start", + signature = "", + types = { }, + }, + --- inform the window it no longer being resized + -- + -- Inform the window that it is no longer being resized. The window manager + -- should use this request to inform windows that are the target of an + -- interactive resize that the interactive resize has ended for example. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:inform_resize_end + -- @treturn river_window_v1 self + { + name = "inform_resize_end", + signature = "", + types = { }, + }, + --- inform window of supported capabilities + -- + -- This request informs the window of the capabilities supported by the + -- window manager. If the window manager, for example, ignores requests to + -- be maximized from the window it should not tell the window that it + -- supports the maximize capability. + -- The window might use this information to, for example, only show a + -- maximize button if the window manager supports the maximize capability. + -- The window manager client should use this request to set capabilities + -- for all new windows. If this request is never made, the compositor will + -- inform windows that all capabilities are supported. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:set_capabilities + -- @tparam uint caps supported capabilities + -- @treturn river_window_v1 self + { + name = "set_capabilities", + signature = "u", + types = { 0, }, + }, + --- inform the window that it is maximized + -- + -- Inform the window that it is maximized. The window might use this + -- information to adapt the style of its client-side window decorations for + -- example. + -- The window manager remains responsible for handling the position and + -- dimensions of the window while it is maximized. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:inform_maximized + -- @treturn river_window_v1 self + { + name = "inform_maximized", + signature = "", + types = { }, + }, + --- inform the window that it is unmaximized + -- + -- Inform the window that it is unmaximized. The window might use this + -- information to adapt the style of its client-side window decorations for + -- example. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:inform_unmaximized + -- @treturn river_window_v1 self + { + name = "inform_unmaximized", + signature = "", + types = { }, + }, + --- inform the window that it is fullscreen + -- + -- Inform the window that it is fullscreen. The window might use this + -- information to adapt the style of its client-side window decorations for + -- example. + -- This request does not affect the size/position of the window or cause it + -- to become the only window rendered, see the river_window_v1.fullscreen + -- and exit_fullscreen requests for that. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:inform_fullscreen + -- @treturn river_window_v1 self + { + name = "inform_fullscreen", + signature = "", + types = { }, + }, + --- inform the window that it is not fullscreen + -- + -- Inform the window that it is not fullscreen. The window might use this + -- information to adapt the style of its client-side window decorations for + -- example. + -- This request does not affect the size/position of the window or cause it + -- to become the only window rendered, see the river_window_v1.fullscreen + -- and exit_fullscreen requests for that. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:inform_not_fullscreen + -- @treturn river_window_v1 self + { + name = "inform_not_fullscreen", + signature = "", + types = { }, + }, + --- make the window fullscreen + -- + -- Make the window fullscreen on the given output. If multiple windows are + -- fullscreen on the same output at the same time only the "top" window in + -- rendering order shall be displayed. + -- All river_shell_surface_v1 objects above the top fullscreen window in + -- the rendering order will continue to be rendered. + -- The compositor will handle the position and dimensions of the window + -- while it is fullscreen. The set_position and propose_dimensions requests + -- shall not affect the current position and dimensions of a fullscreen + -- window. + -- When a fullscreen request is made, the server must send a dimensions + -- event in response as soon as possible. It may not be possible to send a + -- dimensions event in the very next render sequence if, for example, the + -- window takes too long to respond. In this case, the server will send the + -- dimensions event in a future render sequence. + -- The compositor will clip window content, decoration surfaces, and + -- borders to the given output's dimensions while the window is fullscreen. + -- The effects of set_clip_box and set_content_clip_box are ignored while + -- the window is fullscreen. + -- If the output on which a window is currently fullscreen is removed, the + -- windowing state is modified as if there were an exit_fullscreen request + -- made in the same manage sequence as the river_output_v1.removed event. + -- This request does not inform the window that it is fullscreen, see the + -- river_window_v1.inform_fullscreen and inform_not_fullscreen requests. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:fullscreen + -- @tparam river_output_v1 output fullscreen output + -- @treturn river_window_v1 self + { + name = "fullscreen", + signature = "o", + types = { wau.river_output_v1, }, + }, + --- make the window not fullscreen + -- + -- Make the window not fullscreen. + -- The position and dimensions are undefined after this request is made + -- until a manage sequence in which the window manager makes the + -- propose_dimensions and set_position requests is completed. + -- The window manager should make propose_dimensions and set_position + -- requests in the same manage sequence as the exit_fullscreen request for + -- frame perfection. + -- This request does not inform the window that it is fullscreen, see the + -- river_window_v1.inform_fullscreen and inform_not_fullscreen requests. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:exit_fullscreen + -- @treturn river_window_v1 self + { + name = "exit_fullscreen", + signature = "", + types = { }, + }, + --- clip the window to a given box + -- + -- Clip the window, including borders and decoration surfaces, to the box + -- specified by the x, y, width, and height arguments. The x/y position of + -- the box is relative to the top left corner of the window. + -- The width and height arguments must be greater than or equal to 0. + -- Setting a clip box with 0 width or height disables clipping. + -- The clip box is ignored while the window is fullscreen. + -- Both set_clip_box and set_content_clip_box may be enabled simultaneously. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:set_clip_box + -- @tparam int x x relative to top left window corner + -- @tparam int y y relative to top left window corner + -- @tparam int width clip box width + -- @tparam int height clip box height + -- @treturn river_window_v1 self + { + name = "set_clip_box", + signature = "2iiii", + types = { 0, 0, 0, 0, }, + }, + --- clip the window content to a given box + -- + -- Clip the content of the window, excluding borders and decoration + -- surfaces, to the box specified by the x, y, width, and height arguments. + -- The x/y position of the box is relative to the top left corner of the + -- window. + -- Borders drawn by the compositor (see set_borders) are placed around the + -- intersection of the window content (as defined by the dimensions event) + -- and the content clip box when content clipping is enabled. + -- The width and height arguments must be greater than or equal to 0. + -- Setting a box with 0 width or height disables content clipping. + -- The content clip box is ignored while the window is fullscreen. + -- Both set_clip_box and set_content_clip_box may be enabled simultaneously. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:set_content_clip_box + -- @tparam int x x relative to top left window corner + -- @tparam int y y relative to top left window corner + -- @tparam int width clip box width + -- @tparam int height clip box height + -- @treturn river_window_v1 self + { + name = "set_content_clip_box", + signature = "3iiii", + types = { 0, 0, 0, 0, }, + }, + --- recommend maximum dimensions to the window + -- + -- Recommend that the window keep its dimensions within a given + -- maximum width/height. This recommendation is only a hint and the window + -- may ignore it. + -- Setting the width and height to 0 indicates that there are no bounds + -- and is equivalent to having never made this request. + -- Setting width or height to a negative value is a protocol error. + -- The server should communicate this hint to an xdg_toplevel window with + -- the xdg_toplevel.configure_bounds event for example. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_window_v1:set_dimension_bounds + -- @tparam int max_width maximum width + -- @tparam int max_height maximum height + -- @treturn river_window_v1 self + { + name = "set_dimension_bounds", + signature = "4ii", + types = { 0, 0, }, + }, + }, + events = { + --- the window has been closed + -- + -- The window has been closed by the server, perhaps due to an + -- xdg_toplevel.close request or similar. + -- The server will send no further events on this object and ignore any + -- request other than river_window_v1.destroy made after this event is + -- sent. The client should destroy this object with the + -- river_window_v1.destroy request to free up resources. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:closed + { + name = "closed", + signature = "", + types = { }, + }, + --- the window's preferred min/max dimensions + -- + -- This event informs the window manager of the window's preferred min/max + -- dimensions. These preferences are a hint, and the window manager is free + -- to propose dimensions outside of these bounds. + -- All min/max width/height values must be strictly greater than or equal + -- to 0. A value of 0 indicates that the window has no preference for that + -- value. + -- The min_width/min_height must be strictly less than or equal to the + -- max_width/max_height. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:dimensions_hint + -- @tparam int min_width minimum width + -- @tparam int min_height minimum height + -- @tparam int max_width maximum width + -- @tparam int max_height maximum height + { + name = "dimensions_hint", + signature = "iiii", + types = { 0, 0, 0, 0, }, + }, + --- window dimensions + -- + -- This event indicates the dimensions of the window in the compositor's + -- logical coordinate space. The width and height must be strictly greater + -- than zero. + -- Note that the dimensions of a river_window_v1 refer to the dimensions of + -- the window content and are unaffected by the presence of borders or + -- decoration surfaces. + -- This event is sent as part of a render sequence before the render_start + -- event. + -- It may be sent due to a propose_dimensions or fullscreen request in a + -- previous manage sequence or because a window independently decides to + -- change its dimensions. + -- The window will not be displayed until the first dimensions event is + -- received and the render sequence is finished. + -- @event river_window_v1:dimensions + -- @tparam int width window content width + -- @tparam int height window content height + { + name = "dimensions", + signature = "ii", + types = { 0, 0, }, + }, + --- the window set an application ID + -- + -- The window set an application ID. + -- The app_id argument will be null if the window has never set an + -- application ID or if the window cleared its application ID. (Xwayland + -- windows may do this for example, though xdg-toplevels may not.) + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:app_id + -- @tparam string app_id window application ID + { + name = "app_id", + signature = "?s", + types = { 0, }, + }, + --- the window set a title + -- + -- The window set a title. + -- The title argument will be null if the window has never set a title or + -- if the window cleared its title. (Xwayland windows may do this for + -- example, though xdg-toplevels may not.) + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:title + -- @tparam string title window title + { + name = "title", + signature = "?s", + types = { 0, }, + }, + --- the window set a parent + -- + -- The window set a parent window. If this event is never received or if + -- the parent argument is null then the window has no parent. + -- A surface with a parent set might be a dialog, file picker, or similar + -- for the parent window. + -- Child windows should generally be rendered directly above their parent. + -- The compositor must guarantee that there are no loops in the window + -- tree: a parent must not be the descendant of one of its children. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:parent + -- @tparam river_window_v1 parent parent window, if any + { + name = "parent", + signature = "?o", + types = { wau.river_window_v1, }, + }, + --- supported/preferred decoration style + -- + -- Information from the window about the supported and preferred client + -- side/server side decoration options. + -- This event may be sent multiple times over the lifetime of the window if + -- the window changes its preferences. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:decoration_hint + -- @tparam uint hint decoration hint + { + name = "decoration_hint", + signature = "u", + types = { 0, }, + }, + --- window requested interactive pointer move + -- + -- This event informs the window manager that the window has requested to + -- be interactively moved using the pointer. The seat argument indicates the + -- seat for the move. + -- The xdg-shell protocol for example allows windows to request that an + -- interactive move be started, perhaps when a client-side rendered + -- titlebar is dragged. + -- The window manager may use the river_seat_v1.op_start_pointer request to + -- interactively move the window or ignore this event entirely. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:pointer_move_requested + -- @tparam river_seat_v1 seat requested seat + { + name = "pointer_move_requested", + signature = "o", + types = { wau.river_seat_v1, }, + }, + --- window requested interactive pointer resize + -- + -- This event informs the window manager that the window has requested to + -- be interactively resized using the pointer. The seat argument indicates + -- the seat for the resize. + -- The edges argument indicates which edges the window has requested to be + -- resized from. The edges argument will never be none and will never have + -- both top and bottom or both left and right edges set. + -- The xdg-shell protocol for example allows windows to request that an + -- interactive resize be started, perhaps when the corner of client-side + -- rendered decorations is dragged. + -- The window manager may use the river_seat_v1.op_start_pointer request to + -- interactively resize the window or ignore this event entirely. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:pointer_resize_requested + -- @tparam river_seat_v1 seat requested seat + -- @tparam uint edges requested edges + { + name = "pointer_resize_requested", + signature = "ou", + types = { wau.river_seat_v1, 0, }, + }, + --- window requested that the window menu be shown + -- + -- The xdg-shell protocol for example allows windows to request that a + -- window menu be shown, for example when the user right clicks on client + -- side window decorations. + -- A window menu might include options to maximize or minimize the window. + -- The window manager is free to ignore this request and decide what the + -- window menu contains if it does choose to show one. + -- The x and y arguments indicate where the window requested that the + -- window menu be shown. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:show_window_menu_requested + -- @tparam int x x offset from top left corner + -- @tparam int y y offset from top left corner + { + name = "show_window_menu_requested", + signature = "ii", + types = { 0, 0, }, + }, + --- the window requested to be maximized + -- + -- The xdg-shell protocol for example allows windows to request to be + -- maximized. + -- The window manager is free to honor this request using + -- river_window_v1.inform_maximize or ignore it. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:maximize_requested + { + name = "maximize_requested", + signature = "", + types = { }, + }, + --- the window requested to be unmaximized + -- + -- The xdg-shell protocol for example allows windows to request to be + -- unmaximized. + -- The window manager is free to honor this request using + -- river_window_v1.inform_unmaximized or ignore it. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:unmaximize_requested + { + name = "unmaximize_requested", + signature = "", + types = { }, + }, + --- the window requested to be fullscreen + -- + -- The xdg-shell protocol for example allows windows to request that they + -- be made fullscreen and allows them to provide an optional output hint. + -- If the output argument is null, the window has no preference and the + -- window manager should choose an output. + -- The window manager is free to honor this request using + -- river_window_v1.fullscreen or ignore it. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:fullscreen_requested + -- @tparam river_output_v1 output fullscreen output requested + { + name = "fullscreen_requested", + signature = "?o", + types = { wau.river_output_v1, }, + }, + --- the window requested to exit fullscreen + -- + -- The xdg-shell protocol for example allows windows to request to exit + -- fullscreen. + -- The window manager is free to honor this request using + -- river_window_v1.exit_fullscreen or ignore it. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:exit_fullscreen_requested + { + name = "exit_fullscreen_requested", + signature = "", + types = { }, + }, + --- the window requested to be minimized + -- + -- The xdg-shell protocol for example allows windows to request to be + -- minimized. + -- The window manager is free to ignore this request, hide the window, or + -- do whatever else it chooses. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:minimize_requested + { + name = "minimize_requested", + signature = "", + types = { }, + }, + --- unreliable PID of the window's creator + -- + -- This event gives an unreliable PID of the process that created the + -- window. Obtaining this information is inherently racy due to PID reuse. + -- Therefore, this PID must not be used for anything security sensitive. + -- Note also that a single process may create multiple windows, so there is + -- not necessarily a 1-to-1 mapping from PID to window. Multiple windows + -- may have the same PID. + -- This event is sent once when the river_window_v1 is created and never + -- sent again. + -- @event river_window_v1:unreliable_pid + -- @tparam int unreliable_pid unreliable PID + { + name = "unreliable_pid", + signature = "2i", + types = { 0, }, + }, + --- presentation hint set by the window + -- + -- This event communicates the window's preferred presentation mode. + -- This event will be followed by a render_start event after all other new + -- state has been sent by the server. + -- @event river_window_v1:presentation_hint + -- @tparam uint hint presentation hint + { + name = "presentation_hint", + signature = "4u", + types = { 0, }, + }, + --- unique window identifier + -- + -- The identifier is a string that contains up to 32 printable ASCII bytes. + -- The identifier must not be an empty string. + -- It is compositor policy how the identifier is generated, but the following + -- properties must be upheld: + -- 1. The identifier must uniquely identify the window. Two windows must not + -- share the same identifier. + -- 2. The identifier must not be reused. This avoids races around window + -- creation/destruction when identifiers are used in out-of-band IPC. + -- If the compositor implements the ext-foreign-toplevel-list-v1 protocol, + -- the river_window_v1.identifier event must match the corresponding + -- ext_foreign_toplevel_handle_v1.identifier event. + -- This event is sent once when the river_window_v1 is created and never + -- sent again. + -- @event river_window_v1:identifier + -- @tparam string identifier unique identifier + { + name = "identifier", + signature = "4s", + types = { 0, }, + }, + }, + enums = { + --- error + -- @enum river_window_v1.Error + -- @param NODE_EXISTS 0 window already has a node object + -- @param INVALID_DIMENSIONS 1 proposed dimensions out of bounds + -- @param INVALID_BORDER 2 invalid arg to set_borders + -- @param INVALID_CLIP_BOX 3 invalid arg to set_clip_box + ["error"] = { + ["node_exists"] = 0, + ["invalid_dimensions"] = 1, + ["invalid_border"] = 2, + ["invalid_clip_box"] = 3, + }, + --- decoration_hint + -- @enum river_window_v1.DecorationHint + -- @param ONLY_SUPPORTS_CSD 0 only supports client side decoration + -- @param PREFERS_CSD 1 client side decoration preferred, both CSD and SSD supported + -- @param PREFERS_SSD 2 server side decoration preferred, both CSD and SSD supported + -- @param NO_PREFERENCE 3 no preference, both CSD and SSD supported + ["decoration_hint"] = { + ["only_supports_csd"] = 0, + ["prefers_csd"] = 1, + ["prefers_ssd"] = 2, + ["no_preference"] = 3, + }, + --- edges + -- @enum river_window_v1.Edges + -- @param NONE 0 + -- @param TOP 1 + -- @param BOTTOM 2 + -- @param LEFT 4 + -- @param RIGHT 8 + ["edges"] = { + ["none"] = 0, + ["top"] = 1, + ["bottom"] = 2, + ["left"] = 4, + ["right"] = 8, + }, + --- capabilities + -- @enum river_window_v1.Capabilities + -- @param WINDOW_MENU 1 + -- @param MAXIMIZE 2 + -- @param FULLSCREEN 4 + -- @param MINIMIZE 8 + ["capabilities"] = { + ["window_menu"] = 1, + ["maximize"] = 2, + ["fullscreen"] = 4, + ["minimize"] = 8, + }, + }, + methods_opcode = { + ["destroy"] = 0, + ["close"] = 1, + ["get_node"] = 2, + ["propose_dimensions"] = 3, + ["hide"] = 4, + ["show"] = 5, + ["use_csd"] = 6, + ["use_ssd"] = 7, + ["set_borders"] = 8, + ["set_tiled"] = 9, + ["get_decoration_above"] = 10, + ["get_decoration_below"] = 11, + ["inform_resize_start"] = 12, + ["inform_resize_end"] = 13, + ["set_capabilities"] = 14, + ["inform_maximized"] = 15, + ["inform_unmaximized"] = 16, + ["inform_fullscreen"] = 17, + ["inform_not_fullscreen"] = 18, + ["fullscreen"] = 19, + ["exit_fullscreen"] = 20, + ["set_clip_box"] = 21, + ["set_content_clip_box"] = 22, + ["set_dimension_bounds"] = 23, + }, +} + +--- a window decoration +-- +-- The rendering order of windows with decorations is follows: +-- 1. Decorations created with get_decoration_below at the bottom +-- 2. Window content +-- 3. Borders configured with river_window_v1.set_borders +-- 4. Decorations created with get_decoration_above at the top +-- The relative ordering of decoration surfaces above/below a window is +-- undefined by this protocol and left up to the compositor. +-- @type river_decoration_v1 +wau.river_decoration_v1:init { + name = "river_decoration_v1", + version = 4, + methods = { + --- destroy the decoration object + -- + -- This request indicates that the client will no longer use the decoration + -- object and that it may be safely destroyed. + -- @function river_decoration_v1:destroy + -- @treturn river_decoration_v1 self + { + name = "destroy", + signature = "", + types = { }, + type = "destructor" + }, + --- set offset from the window's top left corner + -- + -- This request sets the offset of the decoration surface from the top left + -- corner of the window. + -- If this request is never sent, the x and y offsets are undefined by this + -- protocol and left up to the compositor. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_decoration_v1:set_offset + -- @tparam int x x relative to top left window corner + -- @tparam int y y relative to top left window corner + -- @treturn river_decoration_v1 self + { + name = "set_offset", + signature = "ii", + types = { 0, 0, }, + }, + --- sync next commit with other rendering state + -- + -- Synchronize application of the next wl_surface.commit request on the + -- decoration surface with rest of the state atomically applied with the + -- next river_window_manager_v1.render_finish request. + -- The client must make a wl_surface.commit request on the decoration + -- surface after this request and before the render_finish request, failure + -- to do so is a protocol error. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_decoration_v1:sync_next_commit + -- @treturn river_decoration_v1 self + { + name = "sync_next_commit", + signature = "", + types = { }, + }, + }, + events = { + }, + enums = { + --- error + -- @enum river_decoration_v1.Error + -- @param NO_COMMIT 0 failed to commit the surface before the window manager commit + ["error"] = { + ["no_commit"] = 0, + }, + }, + methods_opcode = { + ["destroy"] = 0, + ["set_offset"] = 1, + ["sync_next_commit"] = 2, + }, +} + +--- a surface for window manager UI +-- +-- The window manager might use a shell surface to display a status bar, +-- background image, desktop notifications, launcher, desktop menu, or +-- whatever else it wants. +-- @type river_shell_surface_v1 +wau.river_shell_surface_v1:init { + name = "river_shell_surface_v1", + version = 4, + methods = { + --- destroy the shell surface object + -- + -- This request indicates that the client will no longer use the shell + -- surface object and that it may be safely destroyed. + -- @function river_shell_surface_v1:destroy + -- @treturn river_shell_surface_v1 self + { + name = "destroy", + signature = "", + types = { }, + type = "destructor" + }, + --- get the shell surface's render list node + -- + -- Get the node in the render list corresponding to the shell surface. + -- It is a protocol error to make this request more than once for a single + -- shell surface. + -- @function river_shell_surface_v1:get_node + -- @treturn river_node_v1 + { + name = "get_node", + signature = "n", + types = { wau.river_node_v1, }, + }, + --- sync next surface commit to window manager commit + -- + -- Synchronize application of the next wl_surface.commit request on the + -- shell surface with rest of the rendering state atomically applied with + -- the next river_window_manager_v1.render_finish request. + -- The client must make a wl_surface.commit request on the shell surface + -- after this request and before the render_finish request, failure to do + -- so is a protocol error. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_shell_surface_v1:sync_next_commit + -- @treturn river_shell_surface_v1 self + { + name = "sync_next_commit", + signature = "", + types = { }, + }, + }, + events = { + }, + enums = { + --- error + -- @enum river_shell_surface_v1.Error + -- @param NODE_EXISTS 0 shell surface already has a node object + -- @param NO_COMMIT 1 failed to commit the surface before the window manager commit + ["error"] = { + ["node_exists"] = 0, + ["no_commit"] = 1, + }, + }, + methods_opcode = { + ["destroy"] = 0, + ["get_node"] = 1, + ["sync_next_commit"] = 2, + }, +} + +--- a node in the render list +-- +-- The render list is a list of nodes that determines the rendering order of +-- the compositor. Nodes may correspond to windows or shell surfaces. The +-- relative ordering of nodes may be changed with the place_above and +-- place_below requests, changing the rendering order. +-- The initial position of a node in the render list is undefined, the window +-- manager client must use the place_above or place_below request to +-- guarantee a specific rendering order. +-- @type river_node_v1 +wau.river_node_v1:init { + name = "river_node_v1", + version = 4, + methods = { + --- destroy the decoration object + -- + -- This request indicates that the client will no longer use the node + -- object and that it may be safely destroyed. + -- @function river_node_v1:destroy + -- @treturn river_node_v1 self + { + name = "destroy", + signature = "", + types = { }, + type = "destructor" + }, + --- set absolute position of the node + -- + -- Set the absolute position of the node in the compositor's logical + -- coordinate space. The x and y coordinates may be positive or negative. + -- Note that the position of a river_window_v1 refers to the position of + -- the window content and is unaffected by the presence of borders or + -- decoration surfaces. + -- If this request is never sent, the position of the node is undefined by + -- this protocol and left up to the compositor. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_node_v1:set_position + -- @tparam int x global x coordinate + -- @tparam int y global y coordinate + -- @treturn river_node_v1 self + { + name = "set_position", + signature = "ii", + types = { 0, 0, }, + }, + --- place node above all other nodes + -- + -- This request places the node above all other nodes in the compositor's + -- render list. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_node_v1:place_top + -- @treturn river_node_v1 self + { + name = "place_top", + signature = "", + types = { }, + }, + --- place node below all other nodes + -- + -- This request places the node below all other nodes in the compositor's + -- render list. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_node_v1:place_bottom + -- @treturn river_node_v1 self + { + name = "place_bottom", + signature = "", + types = { }, + }, + --- place node above another node + -- + -- This request places the node directly above another node in the + -- compositor's render list. + -- Attempting to place a node above itself has no effect. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_node_v1:place_above + -- @tparam river_node_v1 other other node + -- @treturn river_node_v1 self + { + name = "place_above", + signature = "o", + types = { wau.river_node_v1, }, + }, + --- place node below another node + -- + -- This request places the node directly below another node in the + -- compositor's render list. + -- Attempting to place a node below itself has no effect. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_node_v1:place_below + -- @tparam river_node_v1 other other node + -- @treturn river_node_v1 self + { + name = "place_below", + signature = "o", + types = { wau.river_node_v1, }, + }, + }, + events = { + }, + enums = { + }, + methods_opcode = { + ["destroy"] = 0, + ["set_position"] = 1, + ["place_top"] = 2, + ["place_bottom"] = 3, + ["place_above"] = 4, + ["place_below"] = 5, + }, +} + +--- a logical output +-- +-- An area in the compositor's logical coordinate space that should be +-- treated as a single output for window management purposes. This area may +-- correspond to a single physical output or multiple physical outputs in the +-- case of mirroring or tiled monitors depending on the hardware and +-- compositor configuration. +-- @type river_output_v1 +wau.river_output_v1:init { + name = "river_output_v1", + version = 4, + methods = { + --- destroy the output object + -- + -- This request indicates that the client will no longer use the output + -- object and that it may be safely destroyed. + -- This request should be made after the river_output_v1.removed event is + -- received to complete destruction of the output. + -- @function river_output_v1:destroy + -- @treturn river_output_v1 self + { + name = "destroy", + signature = "", + types = { }, + type = "destructor" + }, + --- set the preferred presentation mode + -- + -- Set the preferred presentation mode of the output. The compositor should + -- always respect the preference of the window manager if possible. If this + -- request is never made, the preferred presentation mode is vsync. + -- This request modifies rendering state and may only be made as part of a + -- render sequence, see the river_window_manager_v1 description. + -- @function river_output_v1:set_presentation_mode + -- @tparam uint mode preferred presentation mode + -- @treturn river_output_v1 self + { + name = "set_presentation_mode", + signature = "4u", + types = { 0, }, + }, + }, + events = { + --- the output is removed + -- + -- This event indicates that the logical output is no longer conceptually + -- part of window management space. + -- The server will send no further events on this object and ignore any + -- request (other than river_output_v1.destroy) made after this event is + -- sent. The client should destroy this object with the + -- river_output_v1.destroy request to free up resources. + -- This event may be sent because a corresponding physical output has been + -- physically unplugged or because some output configuration has changed. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_output_v1:removed + { + name = "removed", + signature = "", + types = { }, + }, + --- corresponding wl_output + -- + -- The wl_output object corresponding to the river_output_v1. The argument + -- is the global name of the wl_output advertised with wl_registry.global. + -- It is guaranteed that the corresponding wl_output is advertised before + -- this event is sent. + -- This event is sent exactly once. The wl_output associated with a + -- river_output_v1 cannot change. It is guaranteed that there is a 1-to-1 + -- mapping between wl_output and river_output_v1 objects. + -- The global_remove event for the corresponding wl_output may be sent + -- before the river_output_v1.remove event. This is due to the fact that + -- river_output_v1 state changes are synced to the river window management + -- manage sequence while changes to globals are not. + -- Rationale: The window manager may need information provided by the + -- wl_output interface such as the name/description. It also may need the + -- wl_output object to start screencopy for example. + -- @event river_output_v1:wl_output + -- @tparam uint name name of the wl_output global + { + name = "wl_output", + signature = "u", + types = { 0, }, + }, + --- output position + -- + -- This event indicates the position of the output in the compositor's + -- logical coordinate space. The x and y coordinates may be positive or + -- negative. + -- This event is sent once when the river_output_v1 is created and again + -- whenever the position changes. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- The server must guarantee that the position and dimensions events do not + -- cause the areas of multiple logical outputs to overlap when the + -- corresponding manage_start event is received. + -- @event river_output_v1:position + -- @tparam int x global x coordinate + -- @tparam int y global y coordinate + { + name = "position", + signature = "ii", + types = { 0, 0, }, + }, + --- output dimensions + -- + -- This event indicates the dimensions of the output in the compositor's + -- logical coordinate space. The width and height will always be strictly + -- greater than zero. + -- This event is sent once when the river_output_v1 is created and again + -- whenever the dimensions change. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- The server must guarantee that the position and dimensions events do not + -- cause the areas of multiple logical outputs to overlap when the + -- corresponding manage_start event is received. + -- @event river_output_v1:dimensions + -- @tparam int width output width + -- @tparam int height output height + { + name = "dimensions", + signature = "ii", + types = { 0, 0, }, + }, + }, + enums = { + --- error + -- @enum river_output_v1.Error + -- @param INVALID_PRESENTATION_MODE 0 invalid presentation mode enum value + ["error"] = { + ["invalid_presentation_mode"] = 0, + }, + --- presentation_mode + -- @enum river_output_v1.PresentationMode + -- @param VSYNC 0 + -- @param ASYNC 1 + ["presentation_mode"] = { + ["vsync"] = 0, + ["async"] = 1, + }, + }, + methods_opcode = { + ["destroy"] = 0, + ["set_presentation_mode"] = 1, + }, +} + +--- a window management seat +-- +-- This object represents a single user's collection of input devices. It +-- allows the window manager to route keyboard input to windows, get +-- high-level information about pointer input, define pointer bindings, etc. +-- For keyboard bindings, see the river-xkb-bindings-v1 protocol. +-- Since version 4: The cursor surface/shape set by the window manager on the +-- wl_pointer of this seat is used when no client has pointer focus, for +-- example during a pointer operation. Since the window manager is allowed to +-- set cursor surface/shape even when it does not have pointer focus, the +-- compositor must ignore the serial argument of wl_pointer.set_cursor and +-- wp_cursor_shape_device_v1.set_shape requests made by the window manager. +-- The most recent cursor surface/shape set by the window manager is +-- remembered by the compositor and restored whenever no client has pointer +-- focus. If the window manager never sets a cursor surface/shape, the +-- "default" shape is used. +-- @type river_seat_v1 +wau.river_seat_v1:init { + name = "river_seat_v1", + version = 4, + methods = { + --- destroy the seat object + -- + -- This request indicates that the client will no longer use the seat + -- object and that it may be safely destroyed. + -- This request should be made after the river_seat_v1.removed event is + -- received to complete destruction of the seat. + -- @function river_seat_v1:destroy + -- @treturn river_seat_v1 self + { + name = "destroy", + signature = "", + types = { }, + type = "destructor" + }, + --- give keyboard focus to a window + -- + -- Request that the compositor send keyboard input to the given window. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_seat_v1:focus_window + -- @tparam river_window_v1 window window to focus + -- @treturn river_seat_v1 self + { + name = "focus_window", + signature = "o", + types = { wau.river_window_v1, }, + }, + --- give keyboard focus to a shell_surface + -- + -- Request that the compositor send keyboard input to the given shell + -- surface. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_seat_v1:focus_shell_surface + -- @tparam river_shell_surface_v1 shell_surface shell surface to focus + -- @treturn river_seat_v1 self + { + name = "focus_shell_surface", + signature = "o", + types = { wau.river_shell_surface_v1, }, + }, + --- clear keyboard focus + -- + -- Request that the compositor not send keyboard input to any client. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_seat_v1:clear_focus + -- @treturn river_seat_v1 self + { + name = "clear_focus", + signature = "", + types = { }, + }, + --- start an interactive pointer operation + -- + -- Start an interactive pointer operation. During the operation, op_delta + -- events will be sent based on pointer input. + -- When all pointer buttons are released, the op_release event is sent. + -- The pointer operation continues until the op_end request is made during + -- a manage sequence and that manage sequence is finished. + -- The window manager may use this operation to implement interactive + -- move/resize of windows by setting the position of windows and proposing + -- dimensions based off of the op_delta events. + -- This request is ignored if an operation is already in progress. + -- The compositor must ensure that no client has pointer focus from this + -- seat during the pointer operation. This means that the window manager + -- has control over the pointer's cursor surface/shape during the pointer + -- operation. See the river_seat_v1 description. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_seat_v1:op_start_pointer + -- @treturn river_seat_v1 self + { + name = "op_start_pointer", + signature = "", + types = { }, + }, + --- end an interactive operation + -- + -- End an interactive operation. + -- This request is ignored if there is no operation in progress. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_seat_v1:op_end + -- @treturn river_seat_v1 self + { + name = "op_end", + signature = "", + types = { }, + }, + --- define a new pointer binding + -- + -- Define a pointer binding in terms of a pointer button, keyboard + -- modifiers, and other configurable properties. + -- The button argument is a Linux input event code defined in the + -- linux/input-event-codes.h header file (e.g. BTN_RIGHT). + -- The new pointer binding is not enabled until initial configuration is + -- completed and the enable request is made during a manage sequence. + -- @function river_seat_v1:get_pointer_binding + -- @treturn river_pointer_binding_v1 + -- @tparam uint button a Linux input event code + -- @tparam uint modifiers keyboard modifiers + { + name = "get_pointer_binding", + signature = "nuu", + types = { wau.river_pointer_binding_v1, 0, 0, }, + }, + --- set the xcursor theme for the seat + -- + -- Set the XCursor theme for the seat. This theme is used for cursors + -- rendered by the compositor, but not necessarily for cursors rendered by + -- clients. + -- Note: The window manager may also wish to set the XCURSOR_THEME and + -- XCURSOR_SIZE environment variable for programs it starts. + -- @function river_seat_v1:set_xcursor_theme + -- @tparam string name xcursor theme name + -- @tparam uint size cursor size + -- @treturn river_seat_v1 self + { + name = "set_xcursor_theme", + signature = "2su", + types = { 0, 0, }, + }, + --- warp the pointer to a given position + -- + -- Warp the pointer to the given position in the compositor's logical + -- coordinate space. + -- If the given position is outside the bounds of all outputs, the pointer + -- will be warped to the closest point inside an output instead. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_seat_v1:pointer_warp + -- @tparam int x global x coordinate + -- @tparam int y global y coordinate + -- @treturn river_seat_v1 self + { + name = "pointer_warp", + signature = "3ii", + types = { 0, 0, }, + }, + }, + events = { + --- the seat is removed + -- + -- This event indicates that seat is no longer in use and should be + -- destroyed. + -- The server will send no further events on this object and ignore any + -- request (other than river_seat_v1.destroy) made after this event is + -- sent. The client should destroy this object with the + -- river_seat_v1.destroy request to free up resources. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_seat_v1:removed + { + name = "removed", + signature = "", + types = { }, + }, + --- corresponding wl_seat + -- + -- The wl_seat object corresponding to the river_seat_v1. The argument is + -- the global name of the wl_seat advertised with wl_registry.global. + -- It is guaranteed that the corresponding wl_seat is advertised before + -- this event is sent. + -- This event is sent exactly once. The wl_seat associated with a + -- river_seat_v1 cannot change. It is guaranteed that there is a 1-to-1 + -- mapping between wl_seat and river_seat_v1 objects. + -- The global_remove event for the corresponding wl_seat may be sent before + -- the river_seat_v1.remove event. This is due to the fact that + -- river_seat_v1 state changes are synced to the river window management + -- manage sequence while changes to globals are not. + -- Rationale: The window manager may want to trigger window management + -- state changes based on normal input events received by its shell + -- surfaces for example. + -- @event river_seat_v1:wl_seat + -- @tparam uint name name of the wl_seat global + { + name = "wl_seat", + signature = "u", + types = { 0, }, + }, + --- pointer entered a window + -- + -- The seat's pointer entered the given window's area. + -- The area of a window is defined to include the area defined by the + -- window dimensions, borders configured using river_window_v1.set_borders, + -- and the input regions of decoration surfaces. In particular, it does not + -- include input regions of surfaces belonging to the window that extend + -- outside the window dimensions. + -- The pointer of a seat may only enter a single window at a time. When the + -- pointer moves between windows, the pointer_leave event for the old + -- window must be sent before the pointer_enter event for the new window. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_seat_v1:pointer_enter + -- @tparam river_window_v1 window window entered + { + name = "pointer_enter", + signature = "o", + types = { wau.river_window_v1, }, + }, + --- pointer left the entered window + -- + -- The seat's pointer left the window for which pointer_enter was most + -- recently sent. See pointer_enter for details. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_seat_v1:pointer_leave + { + name = "pointer_leave", + signature = "", + types = { }, + }, + --- a window has been interacted with + -- + -- A window has been interacted with beyond the pointer merely passing over + -- it. This event might be sent due to a pointer button press or due to a + -- touch/tablet tool interaction with the window. + -- There are no guarantees regarding how this event is sent in relation to + -- the pointer_enter and pointer_leave events as the interaction may use + -- touch or tablet tool input. + -- Rationale: this event gives window managers necessary information to + -- determine when to send keyboard focus, raise a window that already has + -- keyboard focus, etc. Rather than expose all pointer, touch, and tablet + -- events to window managers, a policy over mechanism approach is taken. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_seat_v1:window_interaction + -- @tparam river_window_v1 window window interacted with + { + name = "window_interaction", + signature = "o", + types = { wau.river_window_v1, }, + }, + --- a shell surface has been interacted with + -- + -- A shell surface has been interacted with beyond the pointer merely + -- passing over it. This event might be sent due to a pointer button press + -- or due to a touch/tablet tool interaction with the shell_surface. + -- There are no guarantees regarding how this event is sent in relation to + -- the pointer_enter and pointer_leave events as the interaction may use + -- touch or tablet tool input. + -- Rationale: While the shell surface does receive all wl_pointer, + -- wl_touch, etc. input events for the surface directly, these events do + -- not necessarily trigger a manage sequence and therefore do not allow the + -- window manager to update focus or perform other actions in response to + -- the input in a race-free way. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_seat_v1:shell_surface_interaction + -- @tparam river_shell_surface_v1 shell_surface shell surface interacted with + { + name = "shell_surface_interaction", + signature = "o", + types = { wau.river_shell_surface_v1, }, + }, + --- total cumulative motion since op start + -- + -- This event indicates the total change in position since the start of the + -- operation of the pointer/touch point/etc. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_seat_v1:op_delta + -- @tparam int dx total change in x + -- @tparam int dy total change in y + { + name = "op_delta", + signature = "ii", + types = { 0, 0, }, + }, + --- operation input has been released + -- + -- The input driving the current interactive operation has been released. + -- For a pointer op for example, all pointer buttons have been released. + -- Depending on the op type, op_delta events may continue to be sent until + -- the op is ended with the op_end request. + -- This event is sent at most once during an interactive operation. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_seat_v1:op_release + { + name = "op_release", + signature = "", + types = { }, + }, + --- The current position of the pointer + -- + -- The current position of the pointer in the compositor's logical + -- coordinate space. + -- This state is special in that a change in pointer position alone must + -- not cause the compositor to start a manage sequence. + -- Assuming the seat has a pointer, this event must be sent in every manage + -- sequence unless there is no change in x/y position since the last time this + -- event was sent. + -- @event river_seat_v1:pointer_position + -- @tparam int x global x coordinate + -- @tparam int y global y coordinate + { + name = "pointer_position", + signature = "2ii", + types = { 0, 0, }, + }, + }, + enums = { + --- a set of keyboard modifiers + -- + -- This enum is used to describe the keyboard modifiers that must be held + -- down to trigger a key binding or pointer binding. + -- Note that river and wlroots use the values 2 and 16 for capslock and + -- numlock internally. It doesn't make sense to use locked modifiers for + -- bindings however so these values are not included in this enum. + -- @enum river_seat_v1.Modifiers + -- @param NONE 0 + -- @param SHIFT 1 + -- @param CTRL 4 + -- @param MOD1 8 commonly called alt + -- @param MOD3 32 + -- @param MOD4 64 commonly called super or logo + -- @param MOD5 128 + ["modifiers"] = { + ["none"] = 0, + ["shift"] = 1, + ["ctrl"] = 4, + ["mod1"] = 8, + ["mod3"] = 32, + ["mod4"] = 64, + ["mod5"] = 128, + }, + }, + methods_opcode = { + ["destroy"] = 0, + ["focus_window"] = 1, + ["focus_shell_surface"] = 2, + ["clear_focus"] = 3, + ["op_start_pointer"] = 4, + ["op_end"] = 5, + ["get_pointer_binding"] = 6, + ["set_xcursor_theme"] = 7, + ["pointer_warp"] = 8, + }, +} + +--- configure a pointer binding, receive trigger events +-- +-- This object allows the window manager to configure a pointer binding and +-- receive events when the binding is triggered. +-- The new pointer binding is not enabled until the enable request is made +-- during a manage sequence. +-- Normally, all pointer button events are sent to the surface with pointer +-- focus by the compositor. Pointer button events that trigger a pointer +-- binding are not sent to the surface with pointer focus. +-- If multiple pointer bindings would be triggered by a single physical +-- pointer event on the compositor side, it is compositor policy which +-- pointer binding(s) will receive press/release events or if all of the +-- matched pointer bindings receive press/release events. +-- @type river_pointer_binding_v1 +wau.river_pointer_binding_v1:init { + name = "river_pointer_binding_v1", + version = 4, + methods = { + --- destroy the pointer binding object + -- + -- This request indicates that the client will no longer use the pointer + -- binding object and that it may be safely destroyed. + -- @function river_pointer_binding_v1:destroy + -- @treturn river_pointer_binding_v1 self + { + name = "destroy", + signature = "", + types = { }, + type = "destructor" + }, + --- enable the pointer binding + -- + -- This request should be made after all initial configuration has been + -- completed and the window manager wishes the pointer binding to be able + -- to be triggered. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_pointer_binding_v1:enable + -- @treturn river_pointer_binding_v1 self + { + name = "enable", + signature = "", + types = { }, + }, + --- disable the pointer binding + -- + -- This request may be used to temporarily disable the pointer binding. It + -- may be later re-enabled with the enable request. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_pointer_binding_v1:disable + -- @treturn river_pointer_binding_v1 self + { + name = "disable", + signature = "", + types = { }, + }, + }, + events = { + --- the bound pointer button has been pressed + -- + -- This event indicates that the pointer button triggering the binding has + -- been pressed. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- The compositor should wait for the manage sequence to complete before + -- processing further input events. This allows the window manager client + -- to, for example, modify key bindings and keyboard focus without racing + -- against future input events. The window manager should of course respond + -- as soon as possible as the capacity of the compositor to buffer incoming + -- input events is finite. + -- @event river_pointer_binding_v1:pressed + { + name = "pressed", + signature = "", + types = { }, + }, + --- the bound pointer button has been released + -- + -- This event indicates that the pointer button triggering the binding has + -- been released. + -- Releasing the modifiers for the binding without releasing the pointer + -- button does not trigger the release event. This event is sent when the + -- pointer button is released, even if the modifiers have changed since the + -- pressed event. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- The compositor should wait for the manage sequence to complete before + -- processing further input events. This allows the window manager client + -- to, for example, modify key bindings and keyboard focus without racing + -- against future input events. The window manager should of course respond + -- as soon as possible as the capacity of the compositor to buffer incoming + -- input events is finite. + -- @event river_pointer_binding_v1:released + { + name = "released", + signature = "", + types = { }, + }, + }, + enums = { + }, + methods_opcode = { + ["destroy"] = 0, + ["enable"] = 1, + ["disable"] = 2, + }, +} + +end diff --git a/planar/protocol/river-window-management-v1.xml b/planar/protocol/river-window-management-v1.xml new file mode 100644 index 0000000..64bfa58 --- /dev/null +++ b/planar/protocol/river-window-management-v1.xml @@ -0,0 +1,1854 @@ + + + + SPDX-FileCopyrightText: © 2024 Isaac Freund + SPDX-License-Identifier: MIT + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + + + + This protocol allows a single "window manager" client to determine the + window management policy of the compositor. State is globally + double-buffered allowing for frame perfect state changes involving multiple + windows. + + The key words "must", "must not", "required", "shall", "shall not", + "should", "should not", "recommended", "may", and "optional" in this + document are to be interpreted as described in IETF RFC 2119. + + + + + This global interface should only be advertised to the window manager + process. Only one window management client may be active at a time. The + compositor should use the unavailable event if necessary to enforce this. + + There are two disjoint categories of state managed by this protocol: + + Window management state influences the communication between the + compositor and individual windows (e.g. xdg_toplevels). Window management + state includes window dimensions, fullscreen state, keyboard focus, + keyboard bindings, and more. + + Rendering state only affects the rendered output of the compositor and + does not influence communication between the compositor and individual + windows. Rendering state includes the position and rendering order of + windows, shell surfaces, decoration surfaces, borders, and more. + + Window management state may only be modified by the window manager as part + of a manage sequence. A manage sequence is started with the manage_start + event and ended with the manage_finish request. It is a protocol error to + modify window management state outside of a manage sequence. + + A manage sequence is always followed by at least one render sequence. A + render sequence is started with the render_start event and ended with the + render_finish request. + + Rendering state may be modified by the window manager during a manage + sequence or a render sequence. Regardless of when the rendering state is + modified, it is applied with the next render_finish request. It is a + protocol error to modify rendering state outside of a manage or render + sequence. + + The server will start a manage sequence by sending new state and the + manage_start event as soon as possible whenever there is a change in state + that must be communicated with the window manager. + + If the window manager client needs to ensure a manage sequence is started + due to a state change the compositor is not aware of, it may send the + manage_dirty request. + + The server will start a render sequence by sending new state and the + render_start event as soon as possible whenever there is a change in + window dimensions that must be communicated with the window manager. + Multiple render sequences may be made consecutively without a manage + sequence in between, for example if a window independently changes its own + dimensions. + + To summarize, the main loop of this protocol is as follows: + + 1. The server sends events indicating all changes since the last + manage sequence followed by the manage_start event. + + 2. The client sends requests modifying window management state or + rendering state (as defined above) followed by the manage_finish + request. + + 3. The server sends new state to windows and waits for responses. + + 4. The server sends new window dimensions to the client followed by the + render_start event. + + 5. The client sends requests modifying rendering state (as defined above) + followed by the render_finish request. + + 6. If window dimensions change, loop back to step 4. + If state that requires a manage sequence changes or if the client makes + a manage_dirty request, loop back to step 1. + + For the purposes of frame perfection, the server may delay rendering new + state committed by the windows in step 3 until after step 5 is finished. + + It is a protocol error for the client to make a manage_finish or + render_finish request that violates this ordering. + + + + + + + + + + + This event indicates that window management is not available to the + client, perhaps due to another window management client already running. + The circumstances causing this event to be sent are compositor policy. + + If sent, this event is guaranteed to be the first and only event sent by + the server. + + The server will send no further events on this object. The client should + destroy this object and all objects created through this interface. + + + + + + This request indicates that the client no longer wishes to receive + events on this object. + + The Wayland protocol is asynchronous, which means the server may send + further events until the stop request is processed. The client must wait + for a river_window_manager_v1.finished event before destroying this + object. + + + + + + This event indicates that the server will send no further events on this + object. The client should destroy the object. See + river_window_manager_v1.destroy for more information. + + + + + + This request should be called after the finished event has been received + to complete destruction of the object. + + If a client wishes to destroy this object it should send a + river_window_manager_v1.stop request and wait for a + river_window_manager_v1.finished event. Once the finished event is + received it is safe to destroy this object and any other objects created + through this interface. + + + + + + This event indicates that the server has sent events indicating all + state changes since the last manage sequence. + + In response to this event, the client should make requests modifying + window management state as it chooses. Then, the client must make the + manage_finish request. + + See the description of the river_window_manager_v1 interface for a + complete overview of the manage/render sequence loop. + + + + + + This request indicates that the client has made all changes to window + management state it wishes to include in the current manage sequence and + that the server should atomically send these state changes to the + windows and continue with the manage sequence. + + After sending this request, it is a protocol error for the client to + make further changes to window management state until the next + manage_start event is received. + + See the description of the river_window_manager_v1 interface for a + complete overview of the manage/render sequence loop. + + + + + + This request ensures a manage sequence is started and that a + manage_start event is sent by the server. If this request is made during + an ongoing manage sequence, a new manage sequence will be started as + soon as the current one is completed. + + The client may want to use this request due to an internal state change + that the compositor is not aware of (e.g. a dbus event) which should + affect window management or rendering state. + + + + + + This event indicates that the server has sent all river_node_v1.position + and river_window_v1.dimensions events necessary. + + In response to this event, the client should make requests modifying + rendering state as it chooses. Then, the client must make the + render_finish request. + + See the description of the river_window_manager_v1 interface for a + complete overview of the manage/render sequence loop. + + + + + + This request indicates that the client has made all changes to rendering + state it wishes to include in the current manage sequence and that the + server should atomically apply and display these state changes to the + user. + + After sending this request, it is a protocol error for the client to + make further changes to rendering state until the next manage_start or + render_start event is received, whichever comes first. + + See the description of the river_window_manager_v1 interface for a + complete overview of the manage/render sequence loop. + + + + + + This event indicates that the session has been locked. + + The window manager may wish to restrict which key bindings are available + while locked or otherwise use this information. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + This event indicates that the session has been unlocked. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + A new window has been created. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + A new logical output has been created, perhaps due to a new physical + monitor being plugged in or perhaps due to a change in configuration. + + This event will be followed by river_output_v1.position and dimensions + events as well as a manage_start event after all other new state has + been sent by the server. + + + + + + + A new seat has been created. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + Create a new shell surface for window manager UI and assign the + river_shell_surface_v1 role to the surface. + + Providing a wl_surface which already has a role or already has a buffer + attached or committed is a protocol error. + + + + + + + + End the current Wayland session and exit the compositor. + All Wayland clients running in the current session, including + the window manager, will be disconnected. + + Window managers should only make this request if the user explicitly + asks to exit the Wayland session, not for example on normal window + manager termination. + + + + + + + This represents a logical window. For example, a window may correspond to + an xdg_toplevel or Xwayland window. + + A newly created window will not be displayed until the window manager + makes a propose_dimensions or fullscreen request as part of a manage + sequence, the server replies with a dimensions event as part of a render + sequence, and that render sequence is finished. + + + + + + + + + + + + This request indicates that the client will no longer use the window + object and that it may be safely destroyed. + + This request should be made after the river_window_v1.closed event or + river_window_manager_v1.finished is received to complete destruction of + the window. + + + + + + The window has been closed by the server, perhaps due to an + xdg_toplevel.close request or similar. + + The server will send no further events on this object and ignore any + request other than river_window_v1.destroy made after this event is + sent. The client should destroy this object with the + river_window_v1.destroy request to free up resources. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + Request that the window be closed. The window may ignore this request or + only close after some delay, perhaps opening a dialog asking the user to + save their work or similar. + + The server will send a river_window_v1.closed event if/when the window + has been closed. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + Get the node in the render list corresponding to the window. + + It is a protocol error to make this request more than once for a single + window. + + + + + + + This event informs the window manager of the window's preferred min/max + dimensions. These preferences are a hint, and the window manager is free + to propose dimensions outside of these bounds. + + All min/max width/height values must be strictly greater than or equal + to 0. A value of 0 indicates that the window has no preference for that + value. + + The min_width/min_height must be strictly less than or equal to the + max_width/max_height. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + + + + This event indicates the dimensions of the window in the compositor's + logical coordinate space. The width and height must be strictly greater + than zero. + + Note that the dimensions of a river_window_v1 refer to the dimensions of + the window content and are unaffected by the presence of borders or + decoration surfaces. + + This event is sent as part of a render sequence before the render_start + event. + + It may be sent due to a propose_dimensions or fullscreen request in a + previous manage sequence or because a window independently decides to + change its dimensions. + + The window will not be displayed until the first dimensions event is + received and the render sequence is finished. + + + + + + + + This request proposes dimensions for the window in the compositor's + logical coordinate space. + + The width and height must be greater than or equal to zero. If the width + or height is zero the window will be allowed to decide its own + dimensions. + + The window may not take the exact dimensions proposed. The actual + dimensions taken by the window will be sent in a subsequent + river_window_v1.dimensions event. For example, a terminal emulator may + only allow dimensions that are multiple of the cell size. + + When a propose_dimensions request is made, the server must send a + dimensions event in response as soon as possible. It may not be possible + to send a dimensions event in the very next render sequence if, for + example, the window takes too long to respond to the proposed + dimensions. In this case, the server will send the dimensions event in a + future render sequence. + + Note that the dimensions of a river_window_v1 refer to the dimensions of + the window content and are unaffected by the presence of borders or + decoration surfaces. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + + Request that the window be hidden. Has no effect if the window is + already hidden. Hides any window borders and decorations as well. + + Newly created windows are considered shown unless explicitly hidden with + the hide request. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + Request that the window be shown. Has no effect if the window is not + hidden. Does not guarantee that the window is visible as it may be + completely obscured by other windows placed above it for example. + + Newly created windows are considered shown unless explicitly hidden with + the hide request. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + The window set an application ID. + + The app_id argument will be null if the window has never set an + application ID or if the window cleared its application ID. (Xwayland + windows may do this for example, though xdg-toplevels may not.) + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + The window set a title. + + The title argument will be null if the window has never set a title or + if the window cleared its title. (Xwayland windows may do this for + example, though xdg-toplevels may not.) + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + The window set a parent window. If this event is never received or if + the parent argument is null then the window has no parent. + + A surface with a parent set might be a dialog, file picker, or similar + for the parent window. + + Child windows should generally be rendered directly above their parent. + + The compositor must guarantee that there are no loops in the window + tree: a parent must not be the descendant of one of its children. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + + + + + + + + Information from the window about the supported and preferred client + side/server side decoration options. + + This event may be sent multiple times over the lifetime of the window if + the window changes its preferences. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + Tell the client to use client side decoration and draw its own title + bar, borders, etc. + + This is the default if neither this request nor the use_ssd request is + ever made. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + Tell the client to use server side decoration and not draw any client + side decorations. + + This request will have no effect if the client only supports client side + decoration, see the decoration_hint event. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + + + + + + + + This request decorates the window with borders drawn by the compositor + on the specified edges of the window. Borders are drawn above the window + content. + + Corners are drawn only between borders on adjacent edges. If e.g. the + left edge has a border and the top edge does not, the border drawn on + the left edge will not extend vertically beyond the top edge of the + window. + + Borders are not drawn while the window is fullscreen. + + The color is defined by four 32-bit RGBA values. Unless specified in + another protocol extension, the RGBA values use pre-multiplied alpha. + + Setting the edges to none or the width to 0 disables the borders. + Setting a negative width is a protocol error. + + This request completely overrides all previous set_borders requests. + Only the most recent set_borders request has an effect. + + Note that the position/dimensions of a river_window_v1 refer to the + position/dimensions of the window content and are unaffected by the + presence of borders or decoration surfaces. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + + + + + + + Inform the window that it is part of a tiled layout and adjacent to + other elements in the tiled layout on the given edges. + + The window should use this information to change the style of its client + side decorations and avoid drawing e.g. drop shadows outside of the + window dimensions on the tiled edges. + + Setting the edges argument to none informs the window that it is not + part of a tiled layout. If this request is never made, the window is + informed that it is not part of a tiled layout. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + Create a decoration surface and assign the river_decoration_v1 role to + the surface. The created decoration is placed above the window in + rendering order, see the description of river_decoration_v1. + + Providing a wl_surface which already has a role or already has a buffer + attached or committed is a protocol error. + + + + + + + + Create a decoration surface and assign the river_decoration_v1 role to + the surface. The created decoration is placed below the window in + rendering order, see the description of river_decoration_v1. + + Providing a wl_surface which already has a role or already has a buffer + attached or committed is a protocol error. + + + + + + + + This event informs the window manager that the window has requested to + be interactively moved using the pointer. The seat argument indicates the + seat for the move. + + The xdg-shell protocol for example allows windows to request that an + interactive move be started, perhaps when a client-side rendered + titlebar is dragged. + + The window manager may use the river_seat_v1.op_start_pointer request to + interactively move the window or ignore this event entirely. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + This event informs the window manager that the window has requested to + be interactively resized using the pointer. The seat argument indicates + the seat for the resize. + + The edges argument indicates which edges the window has requested to be + resized from. The edges argument will never be none and will never have + both top and bottom or both left and right edges set. + + The xdg-shell protocol for example allows windows to request that an + interactive resize be started, perhaps when the corner of client-side + rendered decorations is dragged. + + The window manager may use the river_seat_v1.op_start_pointer request to + interactively resize the window or ignore this event entirely. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + + Inform the window that it is being resized. The window manager should + use this request to inform windows that are the target of an interactive + resize for example. + + The window manager remains responsible for handling the position and + dimensions of the window while it is resizing. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + Inform the window that it is no longer being resized. The window manager + should use this request to inform windows that are the target of an + interactive resize that the interactive resize has ended for example. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + + + + + + + This request informs the window of the capabilities supported by the + window manager. If the window manager, for example, ignores requests to + be maximized from the window it should not tell the window that it + supports the maximize capability. + + The window might use this information to, for example, only show a + maximize button if the window manager supports the maximize capability. + + The window manager client should use this request to set capabilities + for all new windows. If this request is never made, the compositor will + inform windows that all capabilities are supported. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + The xdg-shell protocol for example allows windows to request that a + window menu be shown, for example when the user right clicks on client + side window decorations. + + A window menu might include options to maximize or minimize the window. + + The window manager is free to ignore this request and decide what the + window menu contains if it does choose to show one. + + The x and y arguments indicate where the window requested that the + window menu be shown. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + + The xdg-shell protocol for example allows windows to request to be + maximized. + + The window manager is free to honor this request using + river_window_v1.inform_maximize or ignore it. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + The xdg-shell protocol for example allows windows to request to be + unmaximized. + + The window manager is free to honor this request using + river_window_v1.inform_unmaximized or ignore it. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + Inform the window that it is maximized. The window might use this + information to adapt the style of its client-side window decorations for + example. + + The window manager remains responsible for handling the position and + dimensions of the window while it is maximized. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + Inform the window that it is unmaximized. The window might use this + information to adapt the style of its client-side window decorations for + example. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + The xdg-shell protocol for example allows windows to request that they + be made fullscreen and allows them to provide an optional output hint. + + If the output argument is null, the window has no preference and the + window manager should choose an output. + + The window manager is free to honor this request using + river_window_v1.fullscreen or ignore it. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + The xdg-shell protocol for example allows windows to request to exit + fullscreen. + + The window manager is free to honor this request using + river_window_v1.exit_fullscreen or ignore it. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + Inform the window that it is fullscreen. The window might use this + information to adapt the style of its client-side window decorations for + example. + + This request does not affect the size/position of the window or cause it + to become the only window rendered, see the river_window_v1.fullscreen + and exit_fullscreen requests for that. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + Inform the window that it is not fullscreen. The window might use this + information to adapt the style of its client-side window decorations for + example. + + This request does not affect the size/position of the window or cause it + to become the only window rendered, see the river_window_v1.fullscreen + and exit_fullscreen requests for that. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + Make the window fullscreen on the given output. If multiple windows are + fullscreen on the same output at the same time only the "top" window in + rendering order shall be displayed. + + All river_shell_surface_v1 objects above the top fullscreen window in + the rendering order will continue to be rendered. + + The compositor will handle the position and dimensions of the window + while it is fullscreen. The set_position and propose_dimensions requests + shall not affect the current position and dimensions of a fullscreen + window. + + When a fullscreen request is made, the server must send a dimensions + event in response as soon as possible. It may not be possible to send a + dimensions event in the very next render sequence if, for example, the + window takes too long to respond. In this case, the server will send the + dimensions event in a future render sequence. + + The compositor will clip window content, decoration surfaces, and + borders to the given output's dimensions while the window is fullscreen. + The effects of set_clip_box and set_content_clip_box are ignored while + the window is fullscreen. + + If the output on which a window is currently fullscreen is removed, the + windowing state is modified as if there were an exit_fullscreen request + made in the same manage sequence as the river_output_v1.removed event. + + This request does not inform the window that it is fullscreen, see the + river_window_v1.inform_fullscreen and inform_not_fullscreen requests. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + Make the window not fullscreen. + + The position and dimensions are undefined after this request is made + until a manage sequence in which the window manager makes the + propose_dimensions and set_position requests is completed. + + The window manager should make propose_dimensions and set_position + requests in the same manage sequence as the exit_fullscreen request for + frame perfection. + + This request does not inform the window that it is fullscreen, see the + river_window_v1.inform_fullscreen and inform_not_fullscreen requests. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + The xdg-shell protocol for example allows windows to request to be + minimized. + + The window manager is free to ignore this request, hide the window, or + do whatever else it chooses. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + Clip the window, including borders and decoration surfaces, to the box + specified by the x, y, width, and height arguments. The x/y position of + the box is relative to the top left corner of the window. + + The width and height arguments must be greater than or equal to 0. + + Setting a clip box with 0 width or height disables clipping. + + The clip box is ignored while the window is fullscreen. + + Both set_clip_box and set_content_clip_box may be enabled simultaneously. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + + + + + This event gives an unreliable PID of the process that created the + window. Obtaining this information is inherently racy due to PID reuse. + Therefore, this PID must not be used for anything security sensitive. + + Note also that a single process may create multiple windows, so there is + not necessarily a 1-to-1 mapping from PID to window. Multiple windows + may have the same PID. + + This event is sent once when the river_window_v1 is created and never + sent again. + + + + + + + Clip the content of the window, excluding borders and decoration + surfaces, to the box specified by the x, y, width, and height arguments. + The x/y position of the box is relative to the top left corner of the + window. + + Borders drawn by the compositor (see set_borders) are placed around the + intersection of the window content (as defined by the dimensions event) + and the content clip box when content clipping is enabled. + + The width and height arguments must be greater than or equal to 0. + + Setting a box with 0 width or height disables content clipping. + + The content clip box is ignored while the window is fullscreen. + + Both set_clip_box and set_content_clip_box may be enabled simultaneously. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + + + + + This event communicates the window's preferred presentation mode. + + This event will be followed by a render_start event after all other new + state has been sent by the server. + + + + + + + The identifier is a string that contains up to 32 printable ASCII bytes. + The identifier must not be an empty string. + + It is compositor policy how the identifier is generated, but the following + properties must be upheld: + + 1. The identifier must uniquely identify the window. Two windows must not + share the same identifier. + + 2. The identifier must not be reused. This avoids races around window + creation/destruction when identifiers are used in out-of-band IPC. + + If the compositor implements the ext-foreign-toplevel-list-v1 protocol, + the river_window_v1.identifier event must match the corresponding + ext_foreign_toplevel_handle_v1.identifier event. + + This event is sent once when the river_window_v1 is created and never + sent again. + + + + + + + Recommend that the window keep its dimensions within a given + maximum width/height. This recommendation is only a hint and the window + may ignore it. + + Setting the width and height to 0 indicates that there are no bounds + and is equivalent to having never made this request. + + Setting width or height to a negative value is a protocol error. + + The server should communicate this hint to an xdg_toplevel window with + the xdg_toplevel.configure_bounds event for example. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + + + The rendering order of windows with decorations is follows: + + 1. Decorations created with get_decoration_below at the bottom + 2. Window content + 3. Borders configured with river_window_v1.set_borders + 4. Decorations created with get_decoration_above at the top + + The relative ordering of decoration surfaces above/below a window is + undefined by this protocol and left up to the compositor. + + + + + + + + + This request indicates that the client will no longer use the decoration + object and that it may be safely destroyed. + + + + + + This request sets the offset of the decoration surface from the top left + corner of the window. + + If this request is never sent, the x and y offsets are undefined by this + protocol and left up to the compositor. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + + + Synchronize application of the next wl_surface.commit request on the + decoration surface with rest of the state atomically applied with the + next river_window_manager_v1.render_finish request. + + The client must make a wl_surface.commit request on the decoration + surface after this request and before the render_finish request, failure + to do so is a protocol error. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + + The window manager might use a shell surface to display a status bar, + background image, desktop notifications, launcher, desktop menu, or + whatever else it wants. + + + + + + + + + + This request indicates that the client will no longer use the shell + surface object and that it may be safely destroyed. + + + + + + Get the node in the render list corresponding to the shell surface. + + It is a protocol error to make this request more than once for a single + shell surface. + + + + + + + Synchronize application of the next wl_surface.commit request on the + shell surface with rest of the rendering state atomically applied with + the next river_window_manager_v1.render_finish request. + + The client must make a wl_surface.commit request on the shell surface + after this request and before the render_finish request, failure to do + so is a protocol error. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + + The render list is a list of nodes that determines the rendering order of + the compositor. Nodes may correspond to windows or shell surfaces. The + relative ordering of nodes may be changed with the place_above and + place_below requests, changing the rendering order. + + The initial position of a node in the render list is undefined, the window + manager client must use the place_above or place_below request to + guarantee a specific rendering order. + + + + + This request indicates that the client will no longer use the node + object and that it may be safely destroyed. + + + + + + Set the absolute position of the node in the compositor's logical + coordinate space. The x and y coordinates may be positive or negative. + + Note that the position of a river_window_v1 refers to the position of + the window content and is unaffected by the presence of borders or + decoration surfaces. + + If this request is never sent, the position of the node is undefined by + this protocol and left up to the compositor. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + + + This request places the node above all other nodes in the compositor's + render list. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + This request places the node below all other nodes in the compositor's + render list. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + This request places the node directly above another node in the + compositor's render list. + + Attempting to place a node above itself has no effect. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + + This request places the node directly below another node in the + compositor's render list. + + Attempting to place a node below itself has no effect. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + + + An area in the compositor's logical coordinate space that should be + treated as a single output for window management purposes. This area may + correspond to a single physical output or multiple physical outputs in the + case of mirroring or tiled monitors depending on the hardware and + compositor configuration. + + + + + This request indicates that the client will no longer use the output + object and that it may be safely destroyed. + + This request should be made after the river_output_v1.removed event is + received to complete destruction of the output. + + + + + + This event indicates that the logical output is no longer conceptually + part of window management space. + + The server will send no further events on this object and ignore any + request (other than river_output_v1.destroy) made after this event is + sent. The client should destroy this object with the + river_output_v1.destroy request to free up resources. + + This event may be sent because a corresponding physical output has been + physically unplugged or because some output configuration has changed. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + The wl_output object corresponding to the river_output_v1. The argument + is the global name of the wl_output advertised with wl_registry.global. + + It is guaranteed that the corresponding wl_output is advertised before + this event is sent. + + This event is sent exactly once. The wl_output associated with a + river_output_v1 cannot change. It is guaranteed that there is a 1-to-1 + mapping between wl_output and river_output_v1 objects. + + The global_remove event for the corresponding wl_output may be sent + before the river_output_v1.remove event. This is due to the fact that + river_output_v1 state changes are synced to the river window management + manage sequence while changes to globals are not. + + Rationale: The window manager may need information provided by the + wl_output interface such as the name/description. It also may need the + wl_output object to start screencopy for example. + + + + + + + This event indicates the position of the output in the compositor's + logical coordinate space. The x and y coordinates may be positive or + negative. + + This event is sent once when the river_output_v1 is created and again + whenever the position changes. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + The server must guarantee that the position and dimensions events do not + cause the areas of multiple logical outputs to overlap when the + corresponding manage_start event is received. + + + + + + + + This event indicates the dimensions of the output in the compositor's + logical coordinate space. The width and height will always be strictly + greater than zero. + + This event is sent once when the river_output_v1 is created and again + whenever the dimensions change. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + The server must guarantee that the position and dimensions events do not + cause the areas of multiple logical outputs to overlap when the + corresponding manage_start event is received. + + + + + + + + + + + + + Output page-flips should be synchronized to the vertical blanking + period, eliminating tearing. This is the default presentation mode. + + + + + Output page-flips should not be synchronized to the vertical blanking + period, visual screen tearing may occur. + + + + + + + Set the preferred presentation mode of the output. The compositor should + always respect the preference of the window manager if possible. If this + request is never made, the preferred presentation mode is vsync. + + This request modifies rendering state and may only be made as part of a + render sequence, see the river_window_manager_v1 description. + + + + + + + + This object represents a single user's collection of input devices. It + allows the window manager to route keyboard input to windows, get + high-level information about pointer input, define pointer bindings, etc. + + For keyboard bindings, see the river-xkb-bindings-v1 protocol. + + Since version 4: The cursor surface/shape set by the window manager on the + wl_pointer of this seat is used when no client has pointer focus, for + example during a pointer operation. Since the window manager is allowed to + set cursor surface/shape even when it does not have pointer focus, the + compositor must ignore the serial argument of wl_pointer.set_cursor and + wp_cursor_shape_device_v1.set_shape requests made by the window manager. + + The most recent cursor surface/shape set by the window manager is + remembered by the compositor and restored whenever no client has pointer + focus. If the window manager never sets a cursor surface/shape, the + "default" shape is used. + + + + + This request indicates that the client will no longer use the seat + object and that it may be safely destroyed. + + This request should be made after the river_seat_v1.removed event is + received to complete destruction of the seat. + + + + + + This event indicates that seat is no longer in use and should be + destroyed. + + The server will send no further events on this object and ignore any + request (other than river_seat_v1.destroy) made after this event is + sent. The client should destroy this object with the + river_seat_v1.destroy request to free up resources. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + The wl_seat object corresponding to the river_seat_v1. The argument is + the global name of the wl_seat advertised with wl_registry.global. + + It is guaranteed that the corresponding wl_seat is advertised before + this event is sent. + + This event is sent exactly once. The wl_seat associated with a + river_seat_v1 cannot change. It is guaranteed that there is a 1-to-1 + mapping between wl_seat and river_seat_v1 objects. + + The global_remove event for the corresponding wl_seat may be sent before + the river_seat_v1.remove event. This is due to the fact that + river_seat_v1 state changes are synced to the river window management + manage sequence while changes to globals are not. + + Rationale: The window manager may want to trigger window management + state changes based on normal input events received by its shell + surfaces for example. + + + + + + + Request that the compositor send keyboard input to the given window. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + Request that the compositor send keyboard input to the given shell + surface. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + Request that the compositor not send keyboard input to any client. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + The seat's pointer entered the given window's area. + + The area of a window is defined to include the area defined by the + window dimensions, borders configured using river_window_v1.set_borders, + and the input regions of decoration surfaces. In particular, it does not + include input regions of surfaces belonging to the window that extend + outside the window dimensions. + + The pointer of a seat may only enter a single window at a time. When the + pointer moves between windows, the pointer_leave event for the old + window must be sent before the pointer_enter event for the new window. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + The seat's pointer left the window for which pointer_enter was most + recently sent. See pointer_enter for details. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + A window has been interacted with beyond the pointer merely passing over + it. This event might be sent due to a pointer button press or due to a + touch/tablet tool interaction with the window. + + There are no guarantees regarding how this event is sent in relation to + the pointer_enter and pointer_leave events as the interaction may use + touch or tablet tool input. + + Rationale: this event gives window managers necessary information to + determine when to send keyboard focus, raise a window that already has + keyboard focus, etc. Rather than expose all pointer, touch, and tablet + events to window managers, a policy over mechanism approach is taken. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + A shell surface has been interacted with beyond the pointer merely + passing over it. This event might be sent due to a pointer button press + or due to a touch/tablet tool interaction with the shell_surface. + + There are no guarantees regarding how this event is sent in relation to + the pointer_enter and pointer_leave events as the interaction may use + touch or tablet tool input. + + Rationale: While the shell surface does receive all wl_pointer, + wl_touch, etc. input events for the surface directly, these events do + not necessarily trigger a manage sequence and therefore do not allow the + window manager to update focus or perform other actions in response to + the input in a race-free way. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + Start an interactive pointer operation. During the operation, op_delta + events will be sent based on pointer input. + + When all pointer buttons are released, the op_release event is sent. + + The pointer operation continues until the op_end request is made during + a manage sequence and that manage sequence is finished. + + The window manager may use this operation to implement interactive + move/resize of windows by setting the position of windows and proposing + dimensions based off of the op_delta events. + + This request is ignored if an operation is already in progress. + + The compositor must ensure that no client has pointer focus from this + seat during the pointer operation. This means that the window manager + has control over the pointer's cursor surface/shape during the pointer + operation. See the river_seat_v1 description. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + This event indicates the total change in position since the start of the + operation of the pointer/touch point/etc. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + + The input driving the current interactive operation has been released. + For a pointer op for example, all pointer buttons have been released. + + Depending on the op type, op_delta events may continue to be sent until + the op is ended with the op_end request. + + This event is sent at most once during an interactive operation. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + End an interactive operation. + + This request is ignored if there is no operation in progress. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + This enum is used to describe the keyboard modifiers that must be held + down to trigger a key binding or pointer binding. + + Note that river and wlroots use the values 2 and 16 for capslock and + numlock internally. It doesn't make sense to use locked modifiers for + bindings however so these values are not included in this enum. + + + + + + + + + + + + + Define a pointer binding in terms of a pointer button, keyboard + modifiers, and other configurable properties. + + The button argument is a Linux input event code defined in the + linux/input-event-codes.h header file (e.g. BTN_RIGHT). + + The new pointer binding is not enabled until initial configuration is + completed and the enable request is made during a manage sequence. + + + + + + + + + Set the XCursor theme for the seat. This theme is used for cursors + rendered by the compositor, but not necessarily for cursors rendered by + clients. + + Note: The window manager may also wish to set the XCURSOR_THEME and + XCURSOR_SIZE environment variable for programs it starts. + + + + + + + + The current position of the pointer in the compositor's logical + coordinate space. + + This state is special in that a change in pointer position alone must + not cause the compositor to start a manage sequence. + + Assuming the seat has a pointer, this event must be sent in every manage + sequence unless there is no change in x/y position since the last time this + event was sent. + + + + + + + + Warp the pointer to the given position in the compositor's logical + coordinate space. + + If the given position is outside the bounds of all outputs, the pointer + will be warped to the closest point inside an output instead. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + + + This object allows the window manager to configure a pointer binding and + receive events when the binding is triggered. + + The new pointer binding is not enabled until the enable request is made + during a manage sequence. + + Normally, all pointer button events are sent to the surface with pointer + focus by the compositor. Pointer button events that trigger a pointer + binding are not sent to the surface with pointer focus. + + If multiple pointer bindings would be triggered by a single physical + pointer event on the compositor side, it is compositor policy which + pointer binding(s) will receive press/release events or if all of the + matched pointer bindings receive press/release events. + + + + + This request indicates that the client will no longer use the pointer + binding object and that it may be safely destroyed. + + + + + + This request should be made after all initial configuration has been + completed and the window manager wishes the pointer binding to be able + to be triggered. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + This request may be used to temporarily disable the pointer binding. It + may be later re-enabled with the enable request. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + This event indicates that the pointer button triggering the binding has + been pressed. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + The compositor should wait for the manage sequence to complete before + processing further input events. This allows the window manager client + to, for example, modify key bindings and keyboard focus without racing + against future input events. The window manager should of course respond + as soon as possible as the capacity of the compositor to buffer incoming + input events is finite. + + + + + + This event indicates that the pointer button triggering the binding has + been released. + + Releasing the modifiers for the binding without releasing the pointer + button does not trigger the release event. This event is sent when the + pointer button is released, even if the modifiers have changed since the + pressed event. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + The compositor should wait for the manage sequence to complete before + processing further input events. This allows the window manager client + to, for example, modify key bindings and keyboard focus without racing + against future input events. The window manager should of course respond + as soon as possible as the capacity of the compositor to buffer incoming + input events is finite. + + + + diff --git a/planar/protocol/river-xkb-bindings-v1.lua b/planar/protocol/river-xkb-bindings-v1.lua new file mode 100644 index 0000000..44d1676 --- /dev/null +++ b/planar/protocol/river-xkb-bindings-v1.lua @@ -0,0 +1,341 @@ +-- Auto generated by the wau-scanner v0 + +--- river_xkb_bindings_v1 +-- @module river_xkb_bindings_v1 + +-- SPDX-FileCopyrightText: © 2025 Isaac Freund +-- SPDX-License-Identifier: MIT +-- Permission is hereby granted, free of charge, to any person obtaining a copy +-- of this software and associated documentation files (the "Software"), to +-- deal in the Software without restriction, including without limitation the +-- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +-- sell copies of the Software, and to permit persons to whom the Software is +-- furnished to do so, subject to the following conditions: +-- The above copyright notice and this permission notice shall be included in +-- all copies or substantial portions of the Software. +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +-- IN THE SOFTWARE. +return function(wau) + +local interfaces = { + "river_xkb_bindings_v1", + "river_xkb_binding_v1", + "river_xkb_bindings_seat_v1", +} + +for _, iface in ipairs(interfaces) do + wau[iface] = wau.wl_interface.new() +end + +--- xkbcommon bindings global interface +-- +-- This global interface should only be advertised to the client if the +-- river_window_manager_v1 global is also advertised. +-- @type river_xkb_bindings_v1 +wau.river_xkb_bindings_v1:init { + name = "river_xkb_bindings_v1", + version = 2, + methods = { + --- destroy the river_xkb_bindings_v1 object + -- + -- This request indicates that the client will no longer use the + -- river_xkb_bindings_v1 object. + -- @function river_xkb_bindings_v1:destroy + -- @treturn river_xkb_bindings_v1 self + { + name = "destroy", + signature = "", + types = { }, + type = "destructor" + }, + --- define a new xkbcommon key binding + -- + -- Define a key binding for the given seat in terms of an xkbcommon keysym + -- and other configurable properties. + -- The new key binding is not enabled until initial configuration is + -- completed and the enable request is made during a manage sequence. + -- @function river_xkb_bindings_v1:get_xkb_binding + -- @tparam river_seat_v1 seat + -- @treturn river_xkb_binding_v1 + -- @tparam uint keysym an xkbcommon keysym + -- @tparam uint modifiers + { + name = "get_xkb_binding", + signature = "onuu", + types = { wau.river_seat_v1, wau.river_xkb_binding_v1, 0, 0, }, + }, + --- manage seat-specific state + -- + -- Create an object to manage seat-specific xkb bindings state. + -- It is a protocol error to make this request more than once for a given + -- river_seat_v1 object. + -- @function river_xkb_bindings_v1:get_seat + -- @treturn river_xkb_bindings_seat_v1 + -- @tparam river_seat_v1 seat + { + name = "get_seat", + signature = "2no", + types = { wau.river_xkb_bindings_seat_v1, wau.river_seat_v1, }, + }, + }, + events = { + }, + enums = { + --- error + -- @enum river_xkb_bindings_v1.Error + -- @param OBJECT_ALREADY_CREATED 0 + ["error"] = { + ["object_already_created"] = 0, + }, + }, + methods_opcode = { + ["destroy"] = 0, + ["get_xkb_binding"] = 1, + ["get_seat"] = 2, + }, +} + +--- configure a xkb key binding, receive trigger events +-- +-- This object allows the window manager to configure a xkbcommon key binding +-- and receive events when the key binding is triggered. +-- The new key binding is not enabled until the enable request is made during +-- a manage sequence. +-- Normally, all key events are sent to the surface with keyboard focus by +-- the compositor. Key events that trigger a key binding are not sent to the +-- surface with keyboard focus. +-- If multiple key bindings would be triggered by a single physical key event +-- on the compositor side, it is compositor policy which key binding(s) will +-- receive press/release events or if all of the matched key bindings receive +-- press/release events. +-- Key bindings might be matched by the same physical key event due to shared +-- keysym and modifiers. The layout override feature may also cause the same +-- physical key event to trigger two key bindings with different keysyms and +-- different layout overrides configured. +-- @type river_xkb_binding_v1 +wau.river_xkb_binding_v1:init { + name = "river_xkb_binding_v1", + version = 2, + methods = { + --- destroy the xkb binding object + -- + -- This request indicates that the client will no longer use the xkb key + -- binding object and that it may be safely destroyed. + -- @function river_xkb_binding_v1:destroy + -- @treturn river_xkb_binding_v1 self + { + name = "destroy", + signature = "", + types = { }, + type = "destructor" + }, + --- override currently active xkb layout + -- + -- Specify an xkb layout that should be used to translate key events for + -- the purpose of triggering this key binding irrespective of the currently + -- active xkb layout. + -- The layout argument is a 0-indexed xkbcommon layout number for the + -- keyboard that generated the key event. + -- If this request is never made, the currently active xkb layout of the + -- keyboard that generated the key event will be used. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_xkb_binding_v1:set_layout_override + -- @tparam uint layout 0-indexed xkbcommon layout + -- @treturn river_xkb_binding_v1 self + { + name = "set_layout_override", + signature = "u", + types = { 0, }, + }, + --- enable the key binding + -- + -- This request should be made after all initial configuration has been + -- completed and the window manager wishes the key binding to be able to be + -- triggered. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_xkb_binding_v1:enable + -- @treturn river_xkb_binding_v1 self + { + name = "enable", + signature = "", + types = { }, + }, + --- disable the key binding + -- + -- This request may be used to temporarily disable the key binding. It may + -- be later re-enabled with the enable request. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_xkb_binding_v1:disable + -- @treturn river_xkb_binding_v1 self + { + name = "disable", + signature = "", + types = { }, + }, + }, + events = { + --- the key triggering the binding has been pressed + -- + -- This event indicates that the physical key triggering the binding has + -- been pressed. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- The compositor should wait for the manage sequence to complete before + -- processing further input events. This allows the window manager client + -- to, for example, modify key bindings and keyboard focus without racing + -- against future input events. The window manager should of course respond + -- as soon as possible as the capacity of the compositor to buffer incoming + -- input events is finite. + -- @event river_xkb_binding_v1:pressed + { + name = "pressed", + signature = "", + types = { }, + }, + --- the key triggering the binding has been released + -- + -- This event indicates that the physical key triggering the binding has + -- been released. + -- Releasing the modifiers for the binding without releasing the "main" + -- physical key that produces the bound keysym does not trigger the release + -- event. This event is sent when the "main" key is released, even if the + -- modifiers have changed since the pressed event. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- The compositor should wait for the manage sequence to complete before + -- processing further input events. This allows the window manager client + -- to, for example, modify key bindings and keyboard focus without racing + -- against future input events. The window manager should of course respond + -- as soon as possible as the capacity of the compositor to buffer incoming + -- input events is finite. + -- @event river_xkb_binding_v1:released + { + name = "released", + signature = "", + types = { }, + }, + --- repeating should be stopped + -- + -- This event indicates that repeating should be stopped for the binding if + -- the window manager has been repeating some action since the pressed + -- event. + -- This event is generally sent when some other (possible unbound) key is + -- pressed after the pressed event is sent and before the released event + -- is sent for this binding. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_xkb_binding_v1:stop_repeat + { + name = "stop_repeat", + signature = "2", + types = { }, + }, + }, + enums = { + }, + methods_opcode = { + ["destroy"] = 0, + ["set_layout_override"] = 1, + ["enable"] = 2, + ["disable"] = 3, + }, +} + +--- xkb bindings seat +-- +-- This object manages xkb bindings state associated with a specific seat. +-- @type river_xkb_bindings_seat_v1 +wau.river_xkb_bindings_seat_v1:init { + name = "river_xkb_bindings_seat_v1", + version = 2, + methods = { + --- destroy the object + -- + -- This request indicates that the client will no longer use the object and + -- that it may be safely destroyed. + -- @function river_xkb_bindings_seat_v1:destroy + -- @treturn river_xkb_bindings_seat_v1 self + { + name = "destroy", + signature = "2", + types = { }, + type = "destructor" + }, + --- ensure the next key press event is eaten + -- + -- Ensure that the next non-modifier key press and corresponding release + -- events for this seat are not sent to the currently focused surface. + -- If the next non-modifier key press triggers a binding, the + -- pressed/released events are sent to the river_xkb_binding_v1 object as + -- usual. + -- If the next non-modifier key press does not trigger a binding, the + -- ate_unbound_key event is sent instead. + -- Rationale: the window manager may wish to implement "chorded" + -- keybindings where triggering a binding activates a "submap" with a + -- different set of keybindings. Without a way to eat the next key + -- press event, there is no good way for the window manager to know that it + -- should error out and exit the submap when a key not bound in the submap + -- is pressed. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_xkb_bindings_seat_v1:ensure_next_key_eaten + -- @treturn river_xkb_bindings_seat_v1 self + { + name = "ensure_next_key_eaten", + signature = "2", + types = { }, + }, + --- cancel an ensure_next_key_eaten request + -- + -- This requests cancels the effect of the latest ensure_next_key_eaten + -- request if no key has been eaten due to the request yet. This request + -- has no effect if a key has already been eaten or no + -- ensure_next_key_eaten was made. + -- Rationale: the window manager may wish cancel an uncompleted "chorded" + -- keybinding after a timeout of a few seconds. Note that since this + -- timeout use-case requires the window manager to trigger a manage sequence + -- with the river_window_manager_v1.manage_dirty request it is possible that + -- the ate_unbound_key key event may be sent before the window manager has + -- a chance to make the cancel_ensure_next_key_eaten request. + -- This request modifies window management state and may only be made as + -- part of a manage sequence, see the river_window_manager_v1 description. + -- @function river_xkb_bindings_seat_v1:cancel_ensure_next_key_eaten + -- @treturn river_xkb_bindings_seat_v1 self + { + name = "cancel_ensure_next_key_eaten", + signature = "2", + types = { }, + }, + }, + events = { + --- an unbound key press event was eaten + -- + -- An unbound key press event was eaten due to the ensure_next_key_eaten + -- request. + -- This event will be followed by a manage_start event after all other new + -- state has been sent by the server. + -- @event river_xkb_bindings_seat_v1:ate_unbound_key + { + name = "ate_unbound_key", + signature = "2", + types = { }, + }, + }, + enums = { + }, + methods_opcode = { + ["destroy"] = 0, + ["ensure_next_key_eaten"] = 1, + ["cancel_ensure_next_key_eaten"] = 2, + }, +} + +end diff --git a/planar/protocol/river-xkb-bindings-v1.xml b/planar/protocol/river-xkb-bindings-v1.xml new file mode 100644 index 0000000..de4f100 --- /dev/null +++ b/planar/protocol/river-xkb-bindings-v1.xml @@ -0,0 +1,268 @@ + + + + SPDX-FileCopyrightText: © 2025 Isaac Freund + SPDX-License-Identifier: MIT + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to + deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + + + + This protocol allows the river-window-management-v1 window manager to + define key bindings in terms of xkbcommon keysyms and other configurable + properties. + + The key words "must", "must not", "required", "shall", "shall not", + "should", "should not", "recommended", "may", and "optional" in this + document are to be interpreted as described in IETF RFC 2119. + + + + + This global interface should only be advertised to the client if the + river_window_manager_v1 global is also advertised. + + + + + + + + + This request indicates that the client will no longer use the + river_xkb_bindings_v1 object. + + + + + + Define a key binding for the given seat in terms of an xkbcommon keysym + and other configurable properties. + + The new key binding is not enabled until initial configuration is + completed and the enable request is made during a manage sequence. + + + + + + + + + + Create an object to manage seat-specific xkb bindings state. + + It is a protocol error to make this request more than once for a given + river_seat_v1 object. + + + + + + + + + This object allows the window manager to configure a xkbcommon key binding + and receive events when the key binding is triggered. + + The new key binding is not enabled until the enable request is made during + a manage sequence. + + Normally, all key events are sent to the surface with keyboard focus by + the compositor. Key events that trigger a key binding are not sent to the + surface with keyboard focus. + + If multiple key bindings would be triggered by a single physical key event + on the compositor side, it is compositor policy which key binding(s) will + receive press/release events or if all of the matched key bindings receive + press/release events. + + Key bindings might be matched by the same physical key event due to shared + keysym and modifiers. The layout override feature may also cause the same + physical key event to trigger two key bindings with different keysyms and + different layout overrides configured. + + + + + This request indicates that the client will no longer use the xkb key + binding object and that it may be safely destroyed. + + + + + + Specify an xkb layout that should be used to translate key events for + the purpose of triggering this key binding irrespective of the currently + active xkb layout. + + The layout argument is a 0-indexed xkbcommon layout number for the + keyboard that generated the key event. + + If this request is never made, the currently active xkb layout of the + keyboard that generated the key event will be used. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + + This request should be made after all initial configuration has been + completed and the window manager wishes the key binding to be able to be + triggered. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + This request may be used to temporarily disable the key binding. It may + be later re-enabled with the enable request. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + This event indicates that the physical key triggering the binding has + been pressed. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + The compositor should wait for the manage sequence to complete before + processing further input events. This allows the window manager client + to, for example, modify key bindings and keyboard focus without racing + against future input events. The window manager should of course respond + as soon as possible as the capacity of the compositor to buffer incoming + input events is finite. + + + + + + This event indicates that the physical key triggering the binding has + been released. + + Releasing the modifiers for the binding without releasing the "main" + physical key that produces the bound keysym does not trigger the release + event. This event is sent when the "main" key is released, even if the + modifiers have changed since the pressed event. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + The compositor should wait for the manage sequence to complete before + processing further input events. This allows the window manager client + to, for example, modify key bindings and keyboard focus without racing + against future input events. The window manager should of course respond + as soon as possible as the capacity of the compositor to buffer incoming + input events is finite. + + + + + + This event indicates that repeating should be stopped for the binding if + the window manager has been repeating some action since the pressed + event. + + This event is generally sent when some other (possible unbound) key is + pressed after the pressed event is sent and before the released event + is sent for this binding. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + + + + This object manages xkb bindings state associated with a specific seat. + + + + + This request indicates that the client will no longer use the object and + that it may be safely destroyed. + + + + + + Ensure that the next non-modifier key press and corresponding release + events for this seat are not sent to the currently focused surface. + + If the next non-modifier key press triggers a binding, the + pressed/released events are sent to the river_xkb_binding_v1 object as + usual. + + If the next non-modifier key press does not trigger a binding, the + ate_unbound_key event is sent instead. + + Rationale: the window manager may wish to implement "chorded" + keybindings where triggering a binding activates a "submap" with a + different set of keybindings. Without a way to eat the next key + press event, there is no good way for the window manager to know that it + should error out and exit the submap when a key not bound in the submap + is pressed. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + This requests cancels the effect of the latest ensure_next_key_eaten + request if no key has been eaten due to the request yet. This request + has no effect if a key has already been eaten or no + ensure_next_key_eaten was made. + + Rationale: the window manager may wish cancel an uncompleted "chorded" + keybinding after a timeout of a few seconds. Note that since this + timeout use-case requires the window manager to trigger a manage sequence + with the river_window_manager_v1.manage_dirty request it is possible that + the ate_unbound_key key event may be sent before the window manager has + a chance to make the cancel_ensure_next_key_eaten request. + + This request modifies window management state and may only be made as + part of a manage sequence, see the river_window_manager_v1 description. + + + + + + An unbound key press event was eaten due to the ensure_next_key_eaten + request. + + This event will be followed by a manage_start event after all other new + state has been sent by the server. + + + + diff --git a/planar/xkbcommon.lua b/planar/xkbcommon.lua new file mode 100644 index 0000000..ba1343c --- /dev/null +++ b/planar/xkbcommon.lua @@ -0,0 +1,26 @@ +-- SPDX-FileCopyrightText: © 2026 FireFly +-- SPDX-License-Identifier: 0BSD + +local ffi = require("cffi") + +local M = {} + +local raw = ffi.load("xkbcommon") + +ffi.cdef [[ + typedef uint32_t xkb_keysym_t; + + enum xkb_keysym_flags { + XKB_KEYSYM_NO_FLAGS = 0, + XKB_KEYSYM_CASE_INSENSITIVE = (1 << 0) + }; + + xkb_keysym_t + xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags); +]] + +function M.keysym(name, flags) + return raw.xkb_keysym_from_name(name, flags or 0) +end + +return M