Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
build: update to wlroots 0.20
.builds/alpine.yml | 2 +-
.builds/archlinux.yml | 2 +-
.builds/freebsd.yml | 2 +-
README.md | 2 +-
build.zig | 4 +-
build.zig.zon | 4 +-
protocol/upstream/virtual-keyboard-unstable-v1.xml | 114 +++++++++++++++++++++
river/Cursor.zig | 5 +-
river/InputManager.zig | 4 +-
river/InputRelay.zig | 17 +--
river/TextInput.zig | 16 +--
11 files changed, 139 insertions(+), 33 deletions(-)
diff --git a/.builds/alpine.yml b/.builds/alpine.yml
index dde76c2..16f1257 100644
--- a/.builds/alpine.yml
+++ b/.builds/alpine.yml
@@ -36,7 +36,7 @@ sources:
tasks:
- install_deps: |
cd wlroots
- git checkout 0.19.0
+ git checkout 0.20.0
meson setup build --auto-features=enabled -Drenderers=gles2 \
-Dcolor-management=disabled -Dlibliftoff=disabled \
-Dexamples=false -Dwerror=false -Db_ndebug=false \
diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml
index 4627e20..521daca 100644
--- a/.builds/archlinux.yml
+++ b/.builds/archlinux.yml
@@ -33,7 +33,7 @@ sources:
tasks:
- install_deps: |
cd wlroots
- git checkout 0.19.0
+ git checkout 0.20.0
meson setup build --auto-features=enabled -Drenderers=gles2 \
-Dcolor-management=disabled -Dlibliftoff=disabled \
-Dexamples=false -Dwerror=false -Db_ndebug=false \
diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml
index c179cc7..ac7d064 100644
--- a/.builds/freebsd.yml
+++ b/.builds/freebsd.yml
@@ -38,7 +38,7 @@ sources:
tasks:
- install_deps: |
cd wlroots
- git checkout 0.19.0
+ git checkout 0.20.0
meson setup build --auto-features=enabled -Drenderers=gles2 \
-Dallocators=gbm \
-Dcolor-management=disabled -Dlibliftoff=disabled \
diff --git a/README.md b/README.md
index aabd407..bf898af 100644
--- a/README.md
+++ b/README.md
@@ -69,7 +69,7 @@ distribution.
- [zig](https://ziglang.org/download/) 0.15
- wayland
- wayland-protocols
-- [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) 0.19
+- [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) 0.20
- xkbcommon 1.12 or newer
- libevdev
- pixman
diff --git a/build.zig b/build.zig
index a03318a..1433d42 100644
--- a/build.zig
+++ b/build.zig
@@ -92,6 +92,7 @@ pub fn build(b: *Build) !void {
scanner.addCustomProtocol(b.path("protocol/upstream/wlr-layer-shell-unstable-v1.xml"));
scanner.addCustomProtocol(b.path("protocol/upstream/wlr-output-power-management-unstable-v1.xml"));
+ scanner.addCustomProtocol(b.path("protocol/upstream/virtual-keyboard-unstable-v1.xml"));
// Some of these versions may be out of date with what wlroots implements.
// This is not a problem in practice though as long as river successfully compiles.
@@ -123,6 +124,7 @@ pub fn build(b: *Build) !void {
scanner.generate("zwlr_output_power_manager_v1", 1);
scanner.generate("zwlr_layer_shell_v1", 4);
+ scanner.generate("zwp_virtual_keyboard_manager_v1", 1);
const wayland = b.createModule(.{ .root_source_file = scanner.result });
@@ -138,7 +140,7 @@ pub fn build(b: *Build) !void {
// exposed to the wlroots module for @cImport() to work. This seems to be
// the best way to do so with the current std.Build API.
wlroots.resolved_target = target;
- const wlroots_pkgconf = "wlroots-0.19";
+ const wlroots_pkgconf = "wlroots-0.20";
wlroots.linkSystemLibrary(wlroots_pkgconf, .{});
const flags = b.createModule(.{ .root_source_file = b.path("common/flags.zig") });
diff --git a/build.zig.zon b/build.zig.zon
index ba3ea2e..1f10100 100644
--- a/build.zig.zon
+++ b/build.zig.zon
@@ -20,8 +20,8 @@
.hash = "wayland-0.5.0-lQa1knz8AQCh08NA8BeQrwJB9U3CfqcVAdHZYGRKIGuu",
},
.wlroots = .{
- .url = "https://codeberg.org/ifreund/zig-wlroots/archive/v0.19.4.tar.gz",
- .hash = "wlroots-0.19.4-jmOlcqQMBABhKYH6NMSnoK1sohTbhc97_JP-hGg2UZaK",
+ .url = "git+https://codeberg.org/ifreund/zig-wlroots?ref=master#6ffee8b21d24e0e4aadcf204f65ebe7ad3c3bacf",
+ .hash = "wlroots-0.20.0-dev-jmOlclseBABjKSxVH4TVkN4Fm-moidbybTStGsujJU_m",
},
.xkbcommon = .{
.url = "https://codeberg.org/ifreund/zig-xkbcommon/archive/v0.4.0.tar.gz",
diff --git a/protocol/upstream/virtual-keyboard-unstable-v1.xml b/protocol/upstream/virtual-keyboard-unstable-v1.xml
new file mode 100644
index 0000000..1ac03fe
--- /dev/null
+++ b/protocol/upstream/virtual-keyboard-unstable-v1.xml
@@ -0,0 +1,114 @@
+<!-- SPDX-License-Identifier: MIT -->
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="virtual_keyboard_unstable_v1">
+ <copyright>
+ Copyright © 2008-2011 Kristian Høgsberg
+ Copyright © 2010-2013 Intel Corporation
+ Copyright © 2012-2013 Collabora, Ltd.
+ Copyright © 2018 Purism SPC
+
+ 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 (including the next
+ paragraph) 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.
+ </copyright>
+
+ <interface name="zwp_virtual_keyboard_v1" version="1">
+ <description summary="virtual keyboard">
+ The virtual keyboard provides an application with requests which emulate
+ the behaviour of a physical keyboard.
+
+ This interface can be used by clients on its own to provide raw input
+ events, or it can accompany the input method protocol.
+ </description>
+
+ <request name="keymap">
+ <description summary="keyboard mapping">
+ Provide a file descriptor to the compositor which can be
+ memory-mapped to provide a keyboard mapping description.
+
+ Format carries a value from the keymap_format enumeration.
+ </description>
+ <arg name="format" type="uint" summary="keymap format"/>
+ <arg name="fd" type="fd" summary="keymap file descriptor"/>
+ <arg name="size" type="uint" summary="keymap size, in bytes"/>
+ </request>
+
+ <enum name="error">
+ <entry name="no_keymap" value="0" summary="No keymap was set"/>
+ </enum>
+
+ <request name="key">
+ <description summary="key event">
+ A key was pressed or released.
+ The time argument is a timestamp with millisecond granularity, with an
+ undefined base. All requests regarding a single object must share the
+ same clock.
+
+ Keymap must be set before issuing this request.
+
+ State carries a value from the key_state enumeration.
+ </description>
+ <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
+ <arg name="key" type="uint" summary="key that produced the event"/>
+ <arg name="state" type="uint" summary="physical state of the key"/>
+ </request>
+
+ <request name="modifiers">
+ <description summary="modifier and group state">
+ Notifies the compositor that the modifier and/or group state has
+ changed, and it should update state.
+
+ The client should use wl_keyboard.modifiers event to synchronize its
+ internal state with seat state.
+
+ Keymap must be set before issuing this request.
+ </description>
+ <arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
+ <arg name="mods_latched" type="uint" summary="latched modifiers"/>
+ <arg name="mods_locked" type="uint" summary="locked modifiers"/>
+ <arg name="group" type="uint" summary="keyboard layout"/>
+ </request>
+
+ <request name="destroy" type="destructor" since="1">
+ <description summary="destroy the virtual keyboard keyboard object"/>
+ </request>
+ </interface>
+
+ <interface name="zwp_virtual_keyboard_manager_v1" version="1">
+ <description summary="virtual keyboard manager">
+ A virtual keyboard manager allows an application to provide keyboard
+ input events as if they came from a physical keyboard.
+ </description>
+
+ <enum name="error">
+ <entry name="unauthorized" value="0" summary="client not authorized to use the interface"/>
+ </enum>
+
+ <request name="create_virtual_keyboard">
+ <description summary="Create a new virtual keyboard">
+ Creates a new virtual keyboard associated to a seat.
+
+ If the compositor enables a keyboard to perform arbitrary actions, it
+ should present an error when an untrusted client requests a new
+ keyboard.
+ </description>
+ <arg name="seat" type="object" interface="wl_seat"/>
+ <arg name="id" type="new_id" interface="zwp_virtual_keyboard_v1"/>
+ </request>
+ </interface>
+</protocol>
diff --git a/river/Cursor.zig b/river/Cursor.zig
index 3aad15b..46aad3d 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -232,10 +232,7 @@ pub fn setTheme(cursor: *Cursor, theme: ?[*:0]const u8, _size: ?u32) !void {
const wlr_xcursor = xcursor_manager.getXcursor("default", 1).?;
const image = wlr_xcursor.images[0];
xwayland.setCursor(
- image.buffer,
- image.width * 4,
- image.width,
- image.height,
+ image.getBuffer(),
@intCast(image.hotspot_x),
@intCast(image.hotspot_y),
);
diff --git a/river/InputManager.zig b/river/InputManager.zig
index c7852a1..b5bb9e3 100644
--- a/river/InputManager.zig
+++ b/river/InputManager.zig
@@ -83,8 +83,8 @@ pub fn init(input_manager: *InputManager) !void {
input_manager.virtual_pointer_manager.events.new_virtual_pointer.add(&input_manager.new_virtual_pointer);
input_manager.virtual_keyboard_manager.events.new_virtual_keyboard.add(&input_manager.new_virtual_keyboard);
input_manager.pointer_constraints.events.new_constraint.add(&input_manager.new_constraint);
- input_manager.input_method_manager.events.input_method.add(&input_manager.new_input_method);
- input_manager.text_input_manager.events.text_input.add(&input_manager.new_text_input);
+ input_manager.input_method_manager.events.new_input_method.add(&input_manager.new_input_method);
+ input_manager.text_input_manager.events.new_text_input.add(&input_manager.new_text_input);
}
pub fn deinit(input_manager: *InputManager) void {
diff --git a/river/InputRelay.zig b/river/InputRelay.zig
index 08c7961..007a7bf 100644
--- a/river/InputRelay.zig
+++ b/river/InputRelay.zig
@@ -32,9 +32,9 @@ input_popups: wl.list.Head(InputPopup, .link),
/// Always null if there is no input method.
text_input: ?*TextInput = null,
-input_method_commit: wl.Listener(*wlr.InputMethodV2) = .init(handleInputMethodCommit),
+input_method_commit: wl.Listener(void) = .init(handleInputMethodCommit),
grab_keyboard: wl.Listener(*wlr.InputMethodV2.KeyboardGrab) = .init(handleInputMethodGrabKeyboard),
-input_method_destroy: wl.Listener(*wlr.InputMethodV2) = .init(handleInputMethodDestroy),
+input_method_destroy: wl.Listener(void) = .init(handleInputMethodDestroy),
input_method_new_popup: wl.Listener(*wlr.InputPopupSurfaceV2) = .init(handleInputMethodNewPopup),
grab_keyboard_destroy: wl.Listener(*wlr.InputMethodV2.KeyboardGrab) = .init(handleInputMethodGrabKeyboardDestroy),
@@ -70,12 +70,9 @@ pub fn newInputMethod(relay: *InputRelay, input_method: *wlr.InputMethodV2) void
}
}
-fn handleInputMethodCommit(
- listener: *wl.Listener(*wlr.InputMethodV2),
- input_method: *wlr.InputMethodV2,
-) void {
+fn handleInputMethodCommit(listener: *wl.Listener(void)) void {
const relay: *InputRelay = @fieldParentPtr("input_method_commit", listener);
- assert(input_method == relay.input_method);
+ const input_method = relay.input_method.?;
if (!input_method.client_active) return;
const text_input = relay.text_input orelse return;
@@ -104,12 +101,8 @@ fn handleInputMethodCommit(
text_input.wlr_text_input.sendDone();
}
-fn handleInputMethodDestroy(
- listener: *wl.Listener(*wlr.InputMethodV2),
- input_method: *wlr.InputMethodV2,
-) void {
+fn handleInputMethodDestroy(listener: *wl.Listener(void)) void {
const relay: *InputRelay = @fieldParentPtr("input_method_destroy", listener);
- assert(input_method == relay.input_method);
relay.input_method_commit.link.remove();
relay.grab_keyboard.link.remove();
diff --git a/river/TextInput.zig b/river/TextInput.zig
index 0eb71df..3a73936 100644
--- a/river/TextInput.zig
+++ b/river/TextInput.zig
@@ -19,10 +19,10 @@ link: wl.list.Link,
wlr_text_input: *wlr.TextInputV3,
-enable: wl.Listener(*wlr.TextInputV3) = .init(handleEnable),
-commit: wl.Listener(*wlr.TextInputV3) = .init(handleCommit),
-disable: wl.Listener(*wlr.TextInputV3) = .init(handleDisable),
-destroy: wl.Listener(*wlr.TextInputV3) = .init(handleDestroy),
+enable: wl.Listener(void) = .init(handleEnable),
+commit: wl.Listener(void) = .init(handleCommit),
+disable: wl.Listener(void) = .init(handleDisable),
+destroy: wl.Listener(void) = .init(handleDestroy),
pub fn create(wlr_text_input: *wlr.TextInputV3) !void {
const seat: *Seat = @ptrCast(@alignCast(wlr_text_input.seat.data));
@@ -44,7 +44,7 @@ pub fn create(wlr_text_input: *wlr.TextInputV3) !void {
wlr_text_input.events.destroy.add(&text_input.destroy);
}
-fn handleEnable(listener: *wl.Listener(*wlr.TextInputV3), _: *wlr.TextInputV3) void {
+fn handleEnable(listener: *wl.Listener(void)) void {
const text_input: *TextInput = @fieldParentPtr("enable", listener);
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
@@ -71,7 +71,7 @@ fn handleEnable(listener: *wl.Listener(*wlr.TextInputV3), _: *wlr.TextInputV3) v
}
}
-fn handleCommit(listener: *wl.Listener(*wlr.TextInputV3), _: *wlr.TextInputV3) void {
+fn handleCommit(listener: *wl.Listener(void)) void {
const text_input: *TextInput = @fieldParentPtr("commit", listener);
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
@@ -85,7 +85,7 @@ fn handleCommit(listener: *wl.Listener(*wlr.TextInputV3), _: *wlr.TextInputV3) v
}
}
-fn handleDisable(listener: *wl.Listener(*wlr.TextInputV3), _: *wlr.TextInputV3) void {
+fn handleDisable(listener: *wl.Listener(void)) void {
const text_input: *TextInput = @fieldParentPtr("disable", listener);
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
@@ -94,7 +94,7 @@ fn handleDisable(listener: *wl.Listener(*wlr.TextInputV3), _: *wlr.TextInputV3)
}
}
-fn handleDestroy(listener: *wl.Listener(*wlr.TextInputV3), _: *wlr.TextInputV3) void {
+fn handleDestroy(listener: *wl.Listener(void)) void {
const text_input: *TextInput = @fieldParentPtr("destroy", listener);
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));