Merge branch 'main' of https://codeberg.org/river/river-classic
This commit is contained in:
@@ -28,7 +28,7 @@ sources:
|
|||||||
tasks:
|
tasks:
|
||||||
- install_deps: |
|
- install_deps: |
|
||||||
cd wlroots
|
cd wlroots
|
||||||
git checkout 0.19.0
|
git checkout 0.20.0
|
||||||
meson setup build --auto-features=enabled -Drenderers=gles2 \
|
meson setup build --auto-features=enabled -Drenderers=gles2 \
|
||||||
-Dcolor-management=disabled -Dlibliftoff=disabled \
|
-Dcolor-management=disabled -Dlibliftoff=disabled \
|
||||||
-Dexamples=false -Dwerror=false -Db_ndebug=false \
|
-Dexamples=false -Dwerror=false -Db_ndebug=false \
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ sources:
|
|||||||
tasks:
|
tasks:
|
||||||
- install_deps: |
|
- install_deps: |
|
||||||
cd wlroots
|
cd wlroots
|
||||||
git checkout 0.19.0
|
git checkout 0.20.0
|
||||||
meson setup build --auto-features=enabled -Drenderers=gles2 \
|
meson setup build --auto-features=enabled -Drenderers=gles2 \
|
||||||
-Dcolor-management=disabled -Dlibliftoff=disabled \
|
-Dcolor-management=disabled -Dlibliftoff=disabled \
|
||||||
-Dexamples=false -Dwerror=false -Db_ndebug=false \
|
-Dexamples=false -Dwerror=false -Db_ndebug=false \
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ sources:
|
|||||||
tasks:
|
tasks:
|
||||||
- install_deps: |
|
- install_deps: |
|
||||||
cd wlroots
|
cd wlroots
|
||||||
git checkout 0.19.0
|
git checkout 0.20.0
|
||||||
meson setup build --auto-features=enabled -Drenderers=gles2 \
|
meson setup build --auto-features=enabled -Drenderers=gles2 \
|
||||||
-Dallocators=gbm \
|
-Dallocators=gbm \
|
||||||
-Dcolor-management=disabled -Dlibliftoff=disabled \
|
-Dcolor-management=disabled -Dlibliftoff=disabled \
|
||||||
|
|||||||
@@ -26,12 +26,12 @@ layout and shifted around as windows are opened/closed.
|
|||||||
|
|
||||||
Rather than having the tiled layout logic built into the compositor process,
|
Rather than having the tiled layout logic built into the compositor process,
|
||||||
river-classic uses a [custom Wayland
|
river-classic uses a [custom Wayland
|
||||||
protocol](https://codeberg.org/river/river-classic/src/branch/master/protocol/river-layout-v3.xml)
|
protocol](https://codeberg.org/river/river-classic/src/branch/main/protocol/river-layout-v3.xml)
|
||||||
and separate "layout generator" process. A basic layout generator, `rivertile`,
|
and separate "layout generator" process. A basic layout generator, `rivertile`,
|
||||||
is provided but users are encouraged to use community-developed [layout
|
is provided but users are encouraged to use community-developed [layout
|
||||||
generators](https://codeberg.org/river/wiki/src/branch/master/pages/Community-Layouts.md)
|
generators](https://codeberg.org/river/wiki-classic/src/branch/main/pages/Community-Layouts.md)
|
||||||
or write their own. Examples in C and Python may be found
|
or write their own. Examples in C and Python may be found
|
||||||
[here](https://codeberg.org/river/river-classic/src/branch/master/contrib).
|
[here](https://codeberg.org/river/river-classic/src/branch/main/contrib).
|
||||||
|
|
||||||
Tags are used to organize windows rather than workspaces. A window may be
|
Tags are used to organize windows rather than workspaces. A window may be
|
||||||
assigned to one or more tags. Likewise, one or more tags may be displayed on a
|
assigned to one or more tags. Likewise, one or more tags may be displayed on a
|
||||||
@@ -53,7 +53,7 @@ distribution.
|
|||||||
- [zig](https://ziglang.org/download/) 0.15
|
- [zig](https://ziglang.org/download/) 0.15
|
||||||
- wayland
|
- wayland
|
||||||
- wayland-protocols
|
- wayland-protocols
|
||||||
- [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) 0.19
|
- [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) 0.20
|
||||||
- xkbcommon
|
- xkbcommon
|
||||||
- libevdev
|
- libevdev
|
||||||
- pixman
|
- pixman
|
||||||
|
|||||||
12
build.zig
12
build.zig
@@ -86,8 +86,11 @@ pub fn build(b: *Build) !void {
|
|||||||
|
|
||||||
scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml");
|
scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml");
|
||||||
scanner.addSystemProtocol("stable/tablet/tablet-v2.xml");
|
scanner.addSystemProtocol("stable/tablet/tablet-v2.xml");
|
||||||
|
scanner.addSystemProtocol("staging/color-management/color-management-v1.xml");
|
||||||
|
scanner.addSystemProtocol("staging/color-representation/color-representation-v1.xml");
|
||||||
scanner.addSystemProtocol("staging/cursor-shape/cursor-shape-v1.xml");
|
scanner.addSystemProtocol("staging/cursor-shape/cursor-shape-v1.xml");
|
||||||
scanner.addSystemProtocol("staging/ext-session-lock/ext-session-lock-v1.xml");
|
scanner.addSystemProtocol("staging/ext-session-lock/ext-session-lock-v1.xml");
|
||||||
|
scanner.addSystemProtocol("staging/ext-image-copy-capture/ext-image-copy-capture-v1.xml");
|
||||||
scanner.addSystemProtocol("staging/tearing-control/tearing-control-v1.xml");
|
scanner.addSystemProtocol("staging/tearing-control/tearing-control-v1.xml");
|
||||||
scanner.addSystemProtocol("unstable/pointer-constraints/pointer-constraints-unstable-v1.xml");
|
scanner.addSystemProtocol("unstable/pointer-constraints/pointer-constraints-unstable-v1.xml");
|
||||||
scanner.addSystemProtocol("unstable/pointer-gestures/pointer-gestures-unstable-v1.xml");
|
scanner.addSystemProtocol("unstable/pointer-gestures/pointer-gestures-unstable-v1.xml");
|
||||||
@@ -98,6 +101,7 @@ pub fn build(b: *Build) !void {
|
|||||||
scanner.addCustomProtocol(b.path("protocol/river-layout-v3.xml"));
|
scanner.addCustomProtocol(b.path("protocol/river-layout-v3.xml"));
|
||||||
scanner.addCustomProtocol(b.path("protocol/wlr-layer-shell-unstable-v1.xml"));
|
scanner.addCustomProtocol(b.path("protocol/wlr-layer-shell-unstable-v1.xml"));
|
||||||
scanner.addCustomProtocol(b.path("protocol/wlr-output-power-management-unstable-v1.xml"));
|
scanner.addCustomProtocol(b.path("protocol/wlr-output-power-management-unstable-v1.xml"));
|
||||||
|
scanner.addCustomProtocol(b.path("protocol/virtual-keyboard-unstable-v1.xml"));
|
||||||
|
|
||||||
// Some of these versions may be out of date with what wlroots implements.
|
// 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.
|
// This is not a problem in practice though as long as river successfully compiles.
|
||||||
@@ -117,8 +121,11 @@ pub fn build(b: *Build) !void {
|
|||||||
scanner.generate("zwp_tablet_manager_v2", 1);
|
scanner.generate("zwp_tablet_manager_v2", 1);
|
||||||
scanner.generate("zxdg_decoration_manager_v1", 1);
|
scanner.generate("zxdg_decoration_manager_v1", 1);
|
||||||
scanner.generate("ext_session_lock_manager_v1", 1);
|
scanner.generate("ext_session_lock_manager_v1", 1);
|
||||||
|
scanner.generate("ext_image_copy_capture_manager_v1", 1);
|
||||||
scanner.generate("wp_cursor_shape_manager_v1", 1);
|
scanner.generate("wp_cursor_shape_manager_v1", 1);
|
||||||
scanner.generate("wp_tearing_control_manager_v1", 1);
|
scanner.generate("wp_tearing_control_manager_v1", 1);
|
||||||
|
scanner.generate("wp_color_manager_v1", 2);
|
||||||
|
scanner.generate("wp_color_representation_manager_v1", 1);
|
||||||
|
|
||||||
scanner.generate("zriver_control_v1", 1);
|
scanner.generate("zriver_control_v1", 1);
|
||||||
scanner.generate("zriver_status_manager_v1", 4);
|
scanner.generate("zriver_status_manager_v1", 4);
|
||||||
@@ -126,6 +133,7 @@ pub fn build(b: *Build) !void {
|
|||||||
|
|
||||||
scanner.generate("zwlr_layer_shell_v1", 4);
|
scanner.generate("zwlr_layer_shell_v1", 4);
|
||||||
scanner.generate("zwlr_output_power_manager_v1", 1);
|
scanner.generate("zwlr_output_power_manager_v1", 1);
|
||||||
|
scanner.generate("zwp_virtual_keyboard_manager_v1", 1);
|
||||||
|
|
||||||
const wayland = b.createModule(.{ .root_source_file = scanner.result });
|
const wayland = b.createModule(.{ .root_source_file = scanner.result });
|
||||||
|
|
||||||
@@ -141,7 +149,7 @@ pub fn build(b: *Build) !void {
|
|||||||
// exposed to the wlroots module for @cImport() to work. This seems to be
|
// 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.
|
// the best way to do so with the current std.Build API.
|
||||||
wlroots.resolved_target = target;
|
wlroots.resolved_target = target;
|
||||||
wlroots.linkSystemLibrary("wlroots-0.19", .{});
|
wlroots.linkSystemLibrary("wlroots-0.20", .{});
|
||||||
|
|
||||||
const flags = b.createModule(.{ .root_source_file = b.path("common/flags.zig") });
|
const flags = b.createModule(.{ .root_source_file = b.path("common/flags.zig") });
|
||||||
const globber = b.createModule(.{ .root_source_file = b.path("common/globber.zig") });
|
const globber = b.createModule(.{ .root_source_file = b.path("common/globber.zig") });
|
||||||
@@ -162,7 +170,7 @@ pub fn build(b: *Build) !void {
|
|||||||
river.linkSystemLibrary("libevdev");
|
river.linkSystemLibrary("libevdev");
|
||||||
river.linkSystemLibrary("libinput");
|
river.linkSystemLibrary("libinput");
|
||||||
river.linkSystemLibrary("wayland-server");
|
river.linkSystemLibrary("wayland-server");
|
||||||
river.linkSystemLibrary("wlroots-0.19");
|
river.linkSystemLibrary("wlroots-0.20");
|
||||||
river.linkSystemLibrary("xkbcommon");
|
river.linkSystemLibrary("xkbcommon");
|
||||||
river.linkSystemLibrary("pixman-1");
|
river.linkSystemLibrary("pixman-1");
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
// When a release is tagged, the "-dev" suffix should be removed for the
|
// When a release is tagged, the "-dev" suffix should be removed for the
|
||||||
// commit that gets tagged. Directly after the tagged commit, the version
|
// commit that gets tagged. Directly after the tagged commit, the version
|
||||||
// should be bumped and the "-dev" suffix added.
|
// should be bumped and the "-dev" suffix added.
|
||||||
.version = "0.3.15-dev",
|
.version = "0.3.16-dev",
|
||||||
.paths = .{""},
|
.paths = .{""},
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.pixman = .{
|
.pixman = .{
|
||||||
@@ -17,8 +17,8 @@
|
|||||||
.hash = "wayland-0.4.0-lQa1khbMAQAsLS2eBR7M5lofyEGPIbu2iFDmoz8lPC27",
|
.hash = "wayland-0.4.0-lQa1khbMAQAsLS2eBR7M5lofyEGPIbu2iFDmoz8lPC27",
|
||||||
},
|
},
|
||||||
.wlroots = .{
|
.wlroots = .{
|
||||||
.url = "https://codeberg.org/ifreund/zig-wlroots/archive/v0.19.3.tar.gz",
|
.url = "https://codeberg.org/ifreund/zig-wlroots/archive/v0.20.0.tar.gz",
|
||||||
.hash = "wlroots-0.19.3-jmOlcuL_AwBHhLCwpFsXbTizE3q9BugFmGX-XIxqcPMc",
|
.hash = "wlroots-0.20.0-jmOlcmtCBADS6eoJ6mkeiSNZkibrhD-c5Qwn-LiM86r1",
|
||||||
},
|
},
|
||||||
.xkbcommon = .{
|
.xkbcommon = .{
|
||||||
.url = "https://codeberg.org/ifreund/zig-xkbcommon/archive/v0.3.0.tar.gz",
|
.url = "https://codeberg.org/ifreund/zig-xkbcommon/archive/v0.3.0.tar.gz",
|
||||||
|
|||||||
113
protocol/virtual-keyboard-unstable-v1.xml
Normal file
113
protocol/virtual-keyboard-unstable-v1.xml
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
<?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>
|
||||||
@@ -307,10 +307,7 @@ pub fn setTheme(cursor: *Cursor, theme: ?[*:0]const u8, _size: ?u32) !void {
|
|||||||
const wlr_xcursor = xcursor_manager.getXcursor("default", 1).?;
|
const wlr_xcursor = xcursor_manager.getXcursor("default", 1).?;
|
||||||
const image = wlr_xcursor.images[0];
|
const image = wlr_xcursor.images[0];
|
||||||
xwayland.setCursor(
|
xwayland.setCursor(
|
||||||
image.buffer,
|
image.getBuffer(),
|
||||||
image.width * 4,
|
|
||||||
image.width,
|
|
||||||
image.height,
|
|
||||||
@intCast(image.hotspot_x),
|
@intCast(image.hotspot_x),
|
||||||
@intCast(image.hotspot_y),
|
@intCast(image.hotspot_y),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -104,8 +104,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_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.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.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.input_method_manager.events.new_input_method.add(&input_manager.new_input_method);
|
||||||
input_manager.text_input_manager.events.text_input.add(&input_manager.new_text_input);
|
input_manager.text_input_manager.events.new_text_input.add(&input_manager.new_text_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit(input_manager: *InputManager) void {
|
pub fn deinit(input_manager: *InputManager) void {
|
||||||
|
|||||||
@@ -46,17 +46,12 @@ input_popups: wl.list.Head(InputPopup, .link),
|
|||||||
/// Always null if there is no input method.
|
/// Always null if there is no input method.
|
||||||
text_input: ?*TextInput = null,
|
text_input: ?*TextInput = null,
|
||||||
|
|
||||||
input_method_commit: wl.Listener(*wlr.InputMethodV2) =
|
input_method_commit: wl.Listener(void) = .init(handleInputMethodCommit),
|
||||||
wl.Listener(*wlr.InputMethodV2).init(handleInputMethodCommit),
|
grab_keyboard: wl.Listener(*wlr.InputMethodV2.KeyboardGrab) = .init(handleInputMethodGrabKeyboard),
|
||||||
grab_keyboard: wl.Listener(*wlr.InputMethodV2.KeyboardGrab) =
|
input_method_destroy: wl.Listener(void) = .init(handleInputMethodDestroy),
|
||||||
wl.Listener(*wlr.InputMethodV2.KeyboardGrab).init(handleInputMethodGrabKeyboard),
|
input_method_new_popup: wl.Listener(*wlr.InputPopupSurfaceV2) = .init(handleInputMethodNewPopup),
|
||||||
input_method_destroy: wl.Listener(*wlr.InputMethodV2) =
|
|
||||||
wl.Listener(*wlr.InputMethodV2).init(handleInputMethodDestroy),
|
|
||||||
input_method_new_popup: wl.Listener(*wlr.InputPopupSurfaceV2) =
|
|
||||||
wl.Listener(*wlr.InputPopupSurfaceV2).init(handleInputMethodNewPopup),
|
|
||||||
|
|
||||||
grab_keyboard_destroy: wl.Listener(*wlr.InputMethodV2.KeyboardGrab) =
|
grab_keyboard_destroy: wl.Listener(void) = .init(handleInputMethodGrabKeyboardDestroy),
|
||||||
wl.Listener(*wlr.InputMethodV2.KeyboardGrab).init(handleInputMethodGrabKeyboardDestroy),
|
|
||||||
|
|
||||||
pub fn init(relay: *InputRelay) void {
|
pub fn init(relay: *InputRelay) void {
|
||||||
relay.* = .{ .text_inputs = undefined, .input_popups = undefined };
|
relay.* = .{ .text_inputs = undefined, .input_popups = undefined };
|
||||||
@@ -89,12 +84,9 @@ pub fn newInputMethod(relay: *InputRelay, input_method: *wlr.InputMethodV2) void
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleInputMethodCommit(
|
fn handleInputMethodCommit(listener: *wl.Listener(void)) void {
|
||||||
listener: *wl.Listener(*wlr.InputMethodV2),
|
|
||||||
input_method: *wlr.InputMethodV2,
|
|
||||||
) void {
|
|
||||||
const relay: *InputRelay = @fieldParentPtr("input_method_commit", listener);
|
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;
|
if (!input_method.client_active) return;
|
||||||
const text_input = relay.text_input orelse return;
|
const text_input = relay.text_input orelse return;
|
||||||
@@ -123,12 +115,8 @@ fn handleInputMethodCommit(
|
|||||||
text_input.wlr_text_input.sendDone();
|
text_input.wlr_text_input.sendDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleInputMethodDestroy(
|
fn handleInputMethodDestroy(listener: *wl.Listener(void)) void {
|
||||||
listener: *wl.Listener(*wlr.InputMethodV2),
|
|
||||||
input_method: *wlr.InputMethodV2,
|
|
||||||
) void {
|
|
||||||
const relay: *InputRelay = @fieldParentPtr("input_method_destroy", listener);
|
const relay: *InputRelay = @fieldParentPtr("input_method_destroy", listener);
|
||||||
assert(input_method == relay.input_method);
|
|
||||||
|
|
||||||
relay.input_method_commit.link.remove();
|
relay.input_method_commit.link.remove();
|
||||||
relay.grab_keyboard.link.remove();
|
relay.grab_keyboard.link.remove();
|
||||||
@@ -166,15 +154,15 @@ fn handleInputMethodNewPopup(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleInputMethodGrabKeyboardDestroy(
|
fn handleInputMethodGrabKeyboardDestroy(listener: *wl.Listener(void)) void {
|
||||||
listener: *wl.Listener(*wlr.InputMethodV2.KeyboardGrab),
|
|
||||||
keyboard_grab: *wlr.InputMethodV2.KeyboardGrab,
|
|
||||||
) void {
|
|
||||||
const relay: *InputRelay = @fieldParentPtr("grab_keyboard_destroy", listener);
|
const relay: *InputRelay = @fieldParentPtr("grab_keyboard_destroy", listener);
|
||||||
|
const input_method = relay.input_method.?;
|
||||||
|
const keyboard_grab = input_method.keyboard_grab.?;
|
||||||
|
|
||||||
relay.grab_keyboard_destroy.link.remove();
|
relay.grab_keyboard_destroy.link.remove();
|
||||||
|
|
||||||
if (keyboard_grab.keyboard) |keyboard| {
|
if (keyboard_grab.keyboard) |keyboard| {
|
||||||
keyboard_grab.input_method.seat.keyboardNotifyModifiers(&keyboard.modifiers);
|
input_method.seat.keyboardNotifyModifiers(&keyboard.modifiers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_xdg_popup: *wlr.Xdg
|
|||||||
wlr_xdg_popup,
|
wlr_xdg_popup,
|
||||||
layer_surface.popup_tree,
|
layer_surface.popup_tree,
|
||||||
layer_surface.popup_tree,
|
layer_surface.popup_tree,
|
||||||
|
null,
|
||||||
) catch {
|
) catch {
|
||||||
wlr_xdg_popup.resource.postNoMemory();
|
wlr_xdg_popup.resource.postNoMemory();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -124,6 +124,8 @@ pub fn init(root: *Root) !void {
|
|||||||
const gamma_control_manager = try wlr.GammaControlManagerV1.create(server.wl_server);
|
const gamma_control_manager = try wlr.GammaControlManagerV1.create(server.wl_server);
|
||||||
scene.setGammaControlManagerV1(gamma_control_manager);
|
scene.setGammaControlManagerV1(gamma_control_manager);
|
||||||
|
|
||||||
|
if (server.color_manager) |color_manager| scene.setColorManagerV1(color_manager);
|
||||||
|
|
||||||
const interactive_content = try scene.tree.createSceneTree();
|
const interactive_content = try scene.tree.createSceneTree();
|
||||||
const drag_icons = try scene.tree.createSceneTree();
|
const drag_icons = try scene.tree.createSceneTree();
|
||||||
const hidden_tree = try scene.tree.createSceneTree();
|
const hidden_tree = try scene.tree.createSceneTree();
|
||||||
@@ -311,7 +313,7 @@ pub fn deactivateOutput(root: *Root, output: *Output) void {
|
|||||||
};
|
};
|
||||||
if (fallback_output) |fallback| {
|
if (fallback_output) |fallback| {
|
||||||
var it = output.pending.focus_stack.safeIterator(.reverse);
|
var it = output.pending.focus_stack.safeIterator(.reverse);
|
||||||
while (it.next()) |view| view.setPendingOutput(fallback);
|
while (it.next()) |view| view.setPendingOutput(fallback, fallback.attachMode());
|
||||||
} else {
|
} else {
|
||||||
var it = output.pending.focus_stack.iterator(.forward);
|
var it = output.pending.focus_stack.iterator(.forward);
|
||||||
while (it.next()) |view| view.pending.output = null;
|
while (it.next()) |view| view.pending.output = null;
|
||||||
@@ -390,7 +392,7 @@ pub fn activateOutput(root: *Root, output: *Output) void {
|
|||||||
output.pending.tags = root.fallback_pending.tags;
|
output.pending.tags = root.fallback_pending.tags;
|
||||||
{
|
{
|
||||||
var it = root.fallback_pending.wm_stack.safeIterator(.reverse);
|
var it = root.fallback_pending.wm_stack.safeIterator(.reverse);
|
||||||
while (it.next()) |view| view.setPendingOutput(output);
|
while (it.next()) |view| view.setPendingOutput(output, .top);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// Focus the new output with all seats
|
// Focus the new output with all seats
|
||||||
@@ -407,7 +409,7 @@ pub fn activateOutput(root: *Root, output: *Output) void {
|
|||||||
const name = view.output_before_evac orelse continue;
|
const name = view.output_before_evac orelse continue;
|
||||||
if (mem.eql(u8, name, mem.span(output.wlr_output.name))) {
|
if (mem.eql(u8, name, mem.span(output.wlr_output.name))) {
|
||||||
if (view.pending.output != output) {
|
if (view.pending.output != output) {
|
||||||
view.setPendingOutput(output);
|
view.setPendingOutput(output, output.attachMode());
|
||||||
}
|
}
|
||||||
util.gpa.free(name);
|
util.gpa.free(name);
|
||||||
view.output_before_evac = null;
|
view.output_before_evac = null;
|
||||||
|
|||||||
@@ -22,7 +22,9 @@ const assert = std.debug.assert;
|
|||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const posix = std.posix;
|
const posix = std.posix;
|
||||||
const wlr = @import("wlroots");
|
const wlr = @import("wlroots");
|
||||||
const wl = @import("wayland").server.wl;
|
const wayland = @import("wayland");
|
||||||
|
const wl = wayland.server.wl;
|
||||||
|
const wp = wayland.server.wp;
|
||||||
|
|
||||||
const c = @import("c.zig").c;
|
const c = @import("c.zig").c;
|
||||||
const util = @import("util.zig");
|
const util = @import("util.zig");
|
||||||
@@ -44,6 +46,7 @@ const XdgDecoration = @import("XdgDecoration.zig");
|
|||||||
const XdgToplevel = @import("XdgToplevel.zig");
|
const XdgToplevel = @import("XdgToplevel.zig");
|
||||||
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
|
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
|
||||||
const XwaylandView = @import("XwaylandView.zig");
|
const XwaylandView = @import("XwaylandView.zig");
|
||||||
|
const View = @import("View.zig");
|
||||||
|
|
||||||
const log = std.log.scoped(.server);
|
const log = std.log.scoped(.server);
|
||||||
|
|
||||||
@@ -52,6 +55,8 @@ wl_server: *wl.Server,
|
|||||||
sigint_source: *wl.EventSource,
|
sigint_source: *wl.EventSource,
|
||||||
sigterm_source: *wl.EventSource,
|
sigterm_source: *wl.EventSource,
|
||||||
|
|
||||||
|
fixes: *wlr.Fixes,
|
||||||
|
|
||||||
backend: *wlr.Backend,
|
backend: *wlr.Backend,
|
||||||
session: ?*wlr.Session,
|
session: ?*wlr.Session,
|
||||||
|
|
||||||
@@ -66,6 +71,9 @@ linux_dmabuf: ?*wlr.LinuxDmabufV1 = null,
|
|||||||
linux_drm_syncobj_manager: ?*wlr.LinuxDrmSyncobjManagerV1 = null,
|
linux_drm_syncobj_manager: ?*wlr.LinuxDrmSyncobjManagerV1 = null,
|
||||||
single_pixel_buffer_manager: *wlr.SinglePixelBufferManagerV1,
|
single_pixel_buffer_manager: *wlr.SinglePixelBufferManagerV1,
|
||||||
|
|
||||||
|
color_manager: ?*wlr.ColorManagerV1 = null,
|
||||||
|
color_representation_manager: *wlr.ColorRepresentationManagerV1,
|
||||||
|
|
||||||
viewporter: *wlr.Viewporter,
|
viewporter: *wlr.Viewporter,
|
||||||
fractional_scale_manager: *wlr.FractionalScaleManagerV1,
|
fractional_scale_manager: *wlr.FractionalScaleManagerV1,
|
||||||
compositor: *wlr.Compositor,
|
compositor: *wlr.Compositor,
|
||||||
@@ -84,6 +92,10 @@ data_control_manager: *wlr.DataControlManagerV1,
|
|||||||
export_dmabuf_manager: *wlr.ExportDmabufManagerV1,
|
export_dmabuf_manager: *wlr.ExportDmabufManagerV1,
|
||||||
screencopy_manager: *wlr.ScreencopyManagerV1,
|
screencopy_manager: *wlr.ScreencopyManagerV1,
|
||||||
|
|
||||||
|
image_copy_capture_manager: *wlr.ExtImageCopyCaptureManagerV1,
|
||||||
|
output_image_capture_source_manager: *wlr.ExtOutputImageCaptureSourceManagerV1,
|
||||||
|
foreign_toplevel_image_capture_source_manager: *wlr.ExtForeignToplevelImageCaptureSourceManagerV1,
|
||||||
|
|
||||||
foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1,
|
foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1,
|
||||||
|
|
||||||
foreign_toplevel_list: *wlr.ExtForeignToplevelListV1,
|
foreign_toplevel_list: *wlr.ExtForeignToplevelListV1,
|
||||||
@@ -117,6 +129,8 @@ request_activate: wl.Listener(*wlr.XdgActivationV1.event.RequestActivate) =
|
|||||||
wl.Listener(*wlr.XdgActivationV1.event.RequestActivate).init(handleRequestActivate),
|
wl.Listener(*wlr.XdgActivationV1.event.RequestActivate).init(handleRequestActivate),
|
||||||
request_set_cursor_shape: wl.Listener(*wlr.CursorShapeManagerV1.event.RequestSetShape) =
|
request_set_cursor_shape: wl.Listener(*wlr.CursorShapeManagerV1.event.RequestSetShape) =
|
||||||
wl.Listener(*wlr.CursorShapeManagerV1.event.RequestSetShape).init(handleRequestSetCursorShape),
|
wl.Listener(*wlr.CursorShapeManagerV1.event.RequestSetShape).init(handleRequestSetCursorShape),
|
||||||
|
new_foreign_toplevel_capture_request: wl.Listener(*wlr.ExtForeignToplevelImageCaptureSourceManagerV1.Request) =
|
||||||
|
wl.Listener(*wlr.ExtForeignToplevelImageCaptureSourceManagerV1.Request).init(handleNewForeignToplevelCaptureRequest),
|
||||||
|
|
||||||
pub fn init(server: *Server, runtime_xwayland: bool) !void {
|
pub fn init(server: *Server, runtime_xwayland: bool) !void {
|
||||||
// We intentionally don't try to prevent memory leaks on error in this function
|
// We intentionally don't try to prevent memory leaks on error in this function
|
||||||
@@ -137,6 +151,8 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void {
|
|||||||
.sigint_source = try loop.addSignal(*wl.Server, posix.SIG.INT, terminate, wl_server),
|
.sigint_source = try loop.addSignal(*wl.Server, posix.SIG.INT, terminate, wl_server),
|
||||||
.sigterm_source = try loop.addSignal(*wl.Server, posix.SIG.TERM, terminate, wl_server),
|
.sigterm_source = try loop.addSignal(*wl.Server, posix.SIG.TERM, terminate, wl_server),
|
||||||
|
|
||||||
|
.fixes = try wlr.Fixes.create(wl_server, 1),
|
||||||
|
|
||||||
.backend = backend,
|
.backend = backend,
|
||||||
.session = session,
|
.session = session,
|
||||||
.renderer = renderer,
|
.renderer = renderer,
|
||||||
@@ -147,11 +163,13 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void {
|
|||||||
.shm = try wlr.Shm.createWithRenderer(wl_server, 2, renderer),
|
.shm = try wlr.Shm.createWithRenderer(wl_server, 2, renderer),
|
||||||
.single_pixel_buffer_manager = try wlr.SinglePixelBufferManagerV1.create(wl_server),
|
.single_pixel_buffer_manager = try wlr.SinglePixelBufferManagerV1.create(wl_server),
|
||||||
|
|
||||||
|
.color_representation_manager = try wlr.ColorRepresentationManagerV1.createWithRenderer(wl_server, 1, renderer),
|
||||||
|
|
||||||
.viewporter = try wlr.Viewporter.create(wl_server),
|
.viewporter = try wlr.Viewporter.create(wl_server),
|
||||||
.fractional_scale_manager = try wlr.FractionalScaleManagerV1.create(wl_server, 1),
|
.fractional_scale_manager = try wlr.FractionalScaleManagerV1.create(wl_server, 1),
|
||||||
.compositor = compositor,
|
.compositor = compositor,
|
||||||
.subcompositor = try wlr.Subcompositor.create(wl_server),
|
.subcompositor = try wlr.Subcompositor.create(wl_server),
|
||||||
.cursor_shape_manager = try wlr.CursorShapeManagerV1.create(server.wl_server, 1),
|
.cursor_shape_manager = try wlr.CursorShapeManagerV1.create(server.wl_server, 2),
|
||||||
|
|
||||||
.xdg_shell = try wlr.XdgShell.create(wl_server, 5),
|
.xdg_shell = try wlr.XdgShell.create(wl_server, 5),
|
||||||
.xdg_decoration_manager = try wlr.XdgDecorationManagerV1.create(wl_server),
|
.xdg_decoration_manager = try wlr.XdgDecorationManagerV1.create(wl_server),
|
||||||
@@ -165,6 +183,10 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void {
|
|||||||
.export_dmabuf_manager = try wlr.ExportDmabufManagerV1.create(wl_server),
|
.export_dmabuf_manager = try wlr.ExportDmabufManagerV1.create(wl_server),
|
||||||
.screencopy_manager = try wlr.ScreencopyManagerV1.create(wl_server),
|
.screencopy_manager = try wlr.ScreencopyManagerV1.create(wl_server),
|
||||||
|
|
||||||
|
.image_copy_capture_manager = try wlr.ExtImageCopyCaptureManagerV1.create(wl_server, 1),
|
||||||
|
.output_image_capture_source_manager = try wlr.ExtOutputImageCaptureSourceManagerV1.create(wl_server, 1),
|
||||||
|
.foreign_toplevel_image_capture_source_manager = try wlr.ExtForeignToplevelImageCaptureSourceManagerV1.create(wl_server, 1),
|
||||||
|
|
||||||
.foreign_toplevel_manager = try wlr.ForeignToplevelManagerV1.create(wl_server),
|
.foreign_toplevel_manager = try wlr.ForeignToplevelManagerV1.create(wl_server),
|
||||||
|
|
||||||
.foreign_toplevel_list = try wlr.ExtForeignToplevelListV1.create(wl_server, 1),
|
.foreign_toplevel_list = try wlr.ExtForeignToplevelListV1.create(wl_server, 1),
|
||||||
@@ -194,6 +216,23 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (renderer.features.input_color_transform) {
|
||||||
|
const render_intents: []const wp.ColorManagerV1.RenderIntent = &.{.perceptual};
|
||||||
|
const transfer_functions = renderer.transferFunctionList();
|
||||||
|
defer std.c.free(transfer_functions.ptr);
|
||||||
|
const primaries = renderer.primariesList();
|
||||||
|
defer std.c.free(primaries.ptr);
|
||||||
|
server.color_manager = try wlr.ColorManagerV1.create(wl_server, 2, .{
|
||||||
|
.features = .{
|
||||||
|
.parametric = true,
|
||||||
|
.set_mastering_display_primaries = true,
|
||||||
|
},
|
||||||
|
.render_intents = render_intents,
|
||||||
|
.transfer_functions = transfer_functions,
|
||||||
|
.primaries = primaries,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (build_options.xwayland and runtime_xwayland) {
|
if (build_options.xwayland and runtime_xwayland) {
|
||||||
server.xwayland = try wlr.Xwayland.create(wl_server, compositor, false);
|
server.xwayland = try wlr.Xwayland.create(wl_server, compositor, false);
|
||||||
server.xwayland.?.events.new_surface.add(&server.new_xwayland_surface);
|
server.xwayland.?.events.new_surface.add(&server.new_xwayland_surface);
|
||||||
@@ -213,6 +252,7 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void {
|
|||||||
server.layer_shell.events.new_surface.add(&server.new_layer_surface);
|
server.layer_shell.events.new_surface.add(&server.new_layer_surface);
|
||||||
server.xdg_activation.events.request_activate.add(&server.request_activate);
|
server.xdg_activation.events.request_activate.add(&server.request_activate);
|
||||||
server.cursor_shape_manager.events.request_set_shape.add(&server.request_set_cursor_shape);
|
server.cursor_shape_manager.events.request_set_shape.add(&server.request_set_cursor_shape);
|
||||||
|
server.foreign_toplevel_image_capture_source_manager.events.new_request.add(&server.new_foreign_toplevel_capture_request);
|
||||||
|
|
||||||
wl_server.setGlobalFilter(*Server, globalFilter, server);
|
wl_server.setGlobalFilter(*Server, globalFilter, server);
|
||||||
}
|
}
|
||||||
@@ -228,6 +268,7 @@ pub fn deinit(server: *Server) void {
|
|||||||
server.new_layer_surface.link.remove();
|
server.new_layer_surface.link.remove();
|
||||||
server.request_activate.link.remove();
|
server.request_activate.link.remove();
|
||||||
server.request_set_cursor_shape.link.remove();
|
server.request_set_cursor_shape.link.remove();
|
||||||
|
server.new_foreign_toplevel_capture_request.link.remove();
|
||||||
|
|
||||||
if (build_options.xwayland) {
|
if (build_options.xwayland) {
|
||||||
if (server.xwayland) |xwayland| {
|
if (server.xwayland) |xwayland| {
|
||||||
@@ -306,6 +347,9 @@ fn allowlist(server: *Server, global: *const wl.Global) bool {
|
|||||||
if (server.linux_drm_syncobj_manager) |linux_drm_syncobj_manager| {
|
if (server.linux_drm_syncobj_manager) |linux_drm_syncobj_manager| {
|
||||||
if (global == linux_drm_syncobj_manager.global) return true;
|
if (global == linux_drm_syncobj_manager.global) return true;
|
||||||
}
|
}
|
||||||
|
if (server.color_manager) |color_manager| {
|
||||||
|
if (global == color_manager.global) return true;
|
||||||
|
}
|
||||||
|
|
||||||
// We must use the getInterface() approach for dynamically created globals
|
// We must use the getInterface() approach for dynamically created globals
|
||||||
// such as wl_output and wl_seat since the wl_global_create() function will
|
// such as wl_output and wl_seat since the wl_global_create() function will
|
||||||
@@ -320,8 +364,10 @@ fn allowlist(server: *Server, global: *const wl.Global) bool {
|
|||||||
// For other globals I like the current pointer comparison approach as it
|
// For other globals I like the current pointer comparison approach as it
|
||||||
// should catch river accidentally exposing multiple copies of e.g. wl_shm
|
// should catch river accidentally exposing multiple copies of e.g. wl_shm
|
||||||
// with an assertion failure.
|
// with an assertion failure.
|
||||||
return global == server.shm.global or
|
return global == server.fixes.global or
|
||||||
|
global == server.shm.global or
|
||||||
global == server.single_pixel_buffer_manager.global or
|
global == server.single_pixel_buffer_manager.global or
|
||||||
|
global == server.color_representation_manager.global or
|
||||||
global == server.viewporter.global or
|
global == server.viewporter.global or
|
||||||
global == server.fractional_scale_manager.global or
|
global == server.fractional_scale_manager.global or
|
||||||
global == server.compositor.global or
|
global == server.compositor.global or
|
||||||
@@ -351,6 +397,9 @@ fn blocklist(server: *Server, global: *const wl.Global) bool {
|
|||||||
global == server.foreign_toplevel_manager.global or
|
global == server.foreign_toplevel_manager.global or
|
||||||
global == server.foreign_toplevel_list.global or
|
global == server.foreign_toplevel_list.global or
|
||||||
global == server.screencopy_manager.global or
|
global == server.screencopy_manager.global or
|
||||||
|
global == server.image_copy_capture_manager.global or
|
||||||
|
global == server.output_image_capture_source_manager.global or
|
||||||
|
global == server.foreign_toplevel_image_capture_source_manager.global or
|
||||||
global == server.export_dmabuf_manager.global or
|
global == server.export_dmabuf_manager.global or
|
||||||
global == server.data_control_manager.global or
|
global == server.data_control_manager.global or
|
||||||
global == server.layout_manager.global or
|
global == server.layout_manager.global or
|
||||||
@@ -556,3 +605,24 @@ fn handleRequestSetCursorShape(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handleNewForeignToplevelCaptureRequest(
|
||||||
|
listener: *wl.Listener(*wlr.ExtForeignToplevelImageCaptureSourceManagerV1.Request),
|
||||||
|
request: *wlr.ExtForeignToplevelImageCaptureSourceManagerV1.Request,
|
||||||
|
) void {
|
||||||
|
const server: *Server = @fieldParentPtr("new_foreign_toplevel_capture_request", listener);
|
||||||
|
if (request.toplevel_handle.data) |opaque_view| {
|
||||||
|
const view: *View = @ptrCast(@alignCast(opaque_view));
|
||||||
|
const capture_source = view.image_capture_source orelse wlr.ExtImageCaptureSourceV1.createWithSceneNode(
|
||||||
|
&view.image_capture_scene.tree.node,
|
||||||
|
server.wl_server.getEventLoop(),
|
||||||
|
server.allocator,
|
||||||
|
server.renderer,
|
||||||
|
) catch {
|
||||||
|
log.err("failed to create ext image capture source", .{});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
_ = request.accept(capture_source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -33,14 +33,10 @@ link: wl.list.Link,
|
|||||||
|
|
||||||
wlr_text_input: *wlr.TextInputV3,
|
wlr_text_input: *wlr.TextInputV3,
|
||||||
|
|
||||||
enable: wl.Listener(*wlr.TextInputV3) =
|
enable: wl.Listener(void) = .init(handleEnable),
|
||||||
wl.Listener(*wlr.TextInputV3).init(handleEnable),
|
commit: wl.Listener(void) = .init(handleCommit),
|
||||||
commit: wl.Listener(*wlr.TextInputV3) =
|
disable: wl.Listener(void) = .init(handleDisable),
|
||||||
wl.Listener(*wlr.TextInputV3).init(handleCommit),
|
destroy: wl.Listener(void) = .init(handleDestroy),
|
||||||
disable: wl.Listener(*wlr.TextInputV3) =
|
|
||||||
wl.Listener(*wlr.TextInputV3).init(handleDisable),
|
|
||||||
destroy: wl.Listener(*wlr.TextInputV3) =
|
|
||||||
wl.Listener(*wlr.TextInputV3).init(handleDestroy),
|
|
||||||
|
|
||||||
pub fn create(wlr_text_input: *wlr.TextInputV3) !void {
|
pub fn create(wlr_text_input: *wlr.TextInputV3) !void {
|
||||||
const seat: *Seat = @ptrCast(@alignCast(wlr_text_input.seat.data));
|
const seat: *Seat = @ptrCast(@alignCast(wlr_text_input.seat.data));
|
||||||
@@ -62,7 +58,7 @@ pub fn create(wlr_text_input: *wlr.TextInputV3) !void {
|
|||||||
wlr_text_input.events.destroy.add(&text_input.destroy);
|
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 text_input: *TextInput = @fieldParentPtr("enable", listener);
|
||||||
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
|
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
|
||||||
|
|
||||||
@@ -89,7 +85,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 text_input: *TextInput = @fieldParentPtr("commit", listener);
|
||||||
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
|
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
|
||||||
|
|
||||||
@@ -103,7 +99,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 text_input: *TextInput = @fieldParentPtr("disable", listener);
|
||||||
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
|
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
|
||||||
|
|
||||||
@@ -112,7 +108,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 text_input: *TextInput = @fieldParentPtr("destroy", listener);
|
||||||
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
|
const seat: *Seat = @ptrCast(@alignCast(text_input.wlr_text_input.seat.data));
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ const wp = @import("wayland").server.wp;
|
|||||||
const server = &@import("main.zig").server;
|
const server = &@import("main.zig").server;
|
||||||
const util = @import("util.zig");
|
const util = @import("util.zig");
|
||||||
|
|
||||||
|
const Config = @import("Config.zig");
|
||||||
const ForeignToplevelHandle = @import("ForeignToplevelHandle.zig");
|
const ForeignToplevelHandle = @import("ForeignToplevelHandle.zig");
|
||||||
const Output = @import("Output.zig");
|
const Output = @import("Output.zig");
|
||||||
const SceneNodeData = @import("SceneNodeData.zig");
|
const SceneNodeData = @import("SceneNodeData.zig");
|
||||||
@@ -139,6 +140,9 @@ saved_surface_tree: *wlr.SceneTree,
|
|||||||
borders: [4]*wlr.SceneRect,
|
borders: [4]*wlr.SceneRect,
|
||||||
popup_tree: *wlr.SceneTree,
|
popup_tree: *wlr.SceneTree,
|
||||||
|
|
||||||
|
image_capture_scene: *wlr.Scene,
|
||||||
|
image_capture_source: ?*wlr.ExtImageCaptureSourceV1,
|
||||||
|
|
||||||
/// Bounds on the width/height of the view, set by the toplevel/xwayland_view implementation.
|
/// Bounds on the width/height of the view, set by the toplevel/xwayland_view implementation.
|
||||||
constraints: Constraints = .{},
|
constraints: Constraints = .{},
|
||||||
|
|
||||||
@@ -214,6 +218,9 @@ pub fn create(impl: Impl) error{OutOfMemory}!*View {
|
|||||||
},
|
},
|
||||||
.popup_tree = popup_tree,
|
.popup_tree = popup_tree,
|
||||||
|
|
||||||
|
.image_capture_scene = try wlr.Scene.create(),
|
||||||
|
.image_capture_source = null,
|
||||||
|
|
||||||
.pending_wm_stack_link = undefined,
|
.pending_wm_stack_link = undefined,
|
||||||
.pending_focus_stack_link = undefined,
|
.pending_focus_stack_link = undefined,
|
||||||
.inflight_wm_stack_link = undefined,
|
.inflight_wm_stack_link = undefined,
|
||||||
@@ -229,6 +236,7 @@ pub fn create(impl: Impl) error{OutOfMemory}!*View {
|
|||||||
view.tree.node.setEnabled(false);
|
view.tree.node.setEnabled(false);
|
||||||
view.popup_tree.node.setEnabled(false);
|
view.popup_tree.node.setEnabled(false);
|
||||||
view.saved_surface_tree.node.setEnabled(false);
|
view.saved_surface_tree.node.setEnabled(false);
|
||||||
|
view.image_capture_scene.restack_xwayland_surfaces = false;
|
||||||
|
|
||||||
try SceneNodeData.attach(&view.tree.node, .{ .view = view });
|
try SceneNodeData.attach(&view.tree.node, .{ .view = view });
|
||||||
try SceneNodeData.attach(&view.popup_tree.node, .{ .view = view });
|
try SceneNodeData.attach(&view.popup_tree.node, .{ .view = view });
|
||||||
@@ -249,6 +257,7 @@ pub fn destroy(view: *View, when: enum { lazy, assert }) void {
|
|||||||
// around until the current transaction completes. This function will be
|
// around until the current transaction completes. This function will be
|
||||||
// called again in Root.commitTransaction()
|
// called again in Root.commitTransaction()
|
||||||
if (!view.saved_surface_tree.node.enabled) {
|
if (!view.saved_surface_tree.node.enabled) {
|
||||||
|
view.image_capture_scene.tree.node.destroy();
|
||||||
view.tree.node.destroy();
|
view.tree.node.destroy();
|
||||||
view.popup_tree.node.destroy();
|
view.popup_tree.node.destroy();
|
||||||
|
|
||||||
@@ -529,12 +538,12 @@ fn saveSurfaceTreeIter(
|
|||||||
saved.setTransform(buffer.transform);
|
saved.setTransform(buffer.transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setPendingOutput(view: *View, output: *Output) void {
|
pub fn setPendingOutput(view: *View, output: *Output, attach_mode: Config.AttachMode) void {
|
||||||
view.pending.output = output;
|
view.pending.output = output;
|
||||||
view.pending_wm_stack_link.remove();
|
view.pending_wm_stack_link.remove();
|
||||||
view.pending_focus_stack_link.remove();
|
view.pending_focus_stack_link.remove();
|
||||||
|
|
||||||
switch (output.attachMode()) {
|
switch (attach_mode) {
|
||||||
.top => output.pending.wm_stack.prepend(view),
|
.top => output.pending.wm_stack.prepend(view),
|
||||||
.bottom => output.pending.wm_stack.append(view),
|
.bottom => output.pending.wm_stack.append(view),
|
||||||
.after => |n| view.attachAfter(&output.pending, n),
|
.after => |n| view.attachAfter(&output.pending, n),
|
||||||
@@ -664,6 +673,7 @@ pub fn map(view: *View) !void {
|
|||||||
.app_id = view.getAppId(),
|
.app_id = view.getAppId(),
|
||||||
})) |handle| {
|
})) |handle| {
|
||||||
view.ext_foreign_toplevel_handle = handle;
|
view.ext_foreign_toplevel_handle = handle;
|
||||||
|
handle.data = view;
|
||||||
} else |_| {
|
} else |_| {
|
||||||
log.err("failed to create ext foreign toplevel handle", .{});
|
log.err("failed to create ext foreign toplevel handle", .{});
|
||||||
}
|
}
|
||||||
@@ -719,7 +729,7 @@ pub fn map(view: *View) !void {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (output) |o| {
|
if (output) |o| {
|
||||||
view.setPendingOutput(o);
|
view.setPendingOutput(o, o.attachMode());
|
||||||
|
|
||||||
var it = server.input_manager.seats.iterator(.forward);
|
var it = server.input_manager.seats.iterator(.forward);
|
||||||
while (it.next()) |seat| seat.focus(view);
|
while (it.next()) |seat| seat.focus(view);
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ root: *wlr.SceneTree,
|
|||||||
|
|
||||||
tree: *wlr.SceneTree,
|
tree: *wlr.SceneTree,
|
||||||
|
|
||||||
|
image_capture_tree: ?*wlr.SceneTree,
|
||||||
|
|
||||||
destroy: wl.Listener(void) = wl.Listener(void).init(handleDestroy),
|
destroy: wl.Listener(void) = wl.Listener(void).init(handleDestroy),
|
||||||
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
|
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
|
||||||
new_popup: wl.Listener(*wlr.XdgPopup) = wl.Listener(*wlr.XdgPopup).init(handleNewPopup),
|
new_popup: wl.Listener(*wlr.XdgPopup) = wl.Listener(*wlr.XdgPopup).init(handleNewPopup),
|
||||||
@@ -44,14 +46,21 @@ pub fn create(
|
|||||||
wlr_xdg_popup: *wlr.XdgPopup,
|
wlr_xdg_popup: *wlr.XdgPopup,
|
||||||
root: *wlr.SceneTree,
|
root: *wlr.SceneTree,
|
||||||
parent: *wlr.SceneTree,
|
parent: *wlr.SceneTree,
|
||||||
|
image_capture_parent: ?*wlr.SceneTree,
|
||||||
) error{OutOfMemory}!void {
|
) error{OutOfMemory}!void {
|
||||||
const xdg_popup = try util.gpa.create(XdgPopup);
|
const xdg_popup = try util.gpa.create(XdgPopup);
|
||||||
errdefer util.gpa.destroy(xdg_popup);
|
errdefer util.gpa.destroy(xdg_popup);
|
||||||
|
|
||||||
|
const image_capture_tree = if (image_capture_parent) |p|
|
||||||
|
try p.createSceneXdgSurface(wlr_xdg_popup.base)
|
||||||
|
else
|
||||||
|
null;
|
||||||
|
|
||||||
xdg_popup.* = .{
|
xdg_popup.* = .{
|
||||||
.wlr_xdg_popup = wlr_xdg_popup,
|
.wlr_xdg_popup = wlr_xdg_popup,
|
||||||
.root = root,
|
.root = root,
|
||||||
.tree = try parent.createSceneXdgSurface(wlr_xdg_popup.base),
|
.tree = try parent.createSceneXdgSurface(wlr_xdg_popup.base),
|
||||||
|
.image_capture_tree = image_capture_tree,
|
||||||
};
|
};
|
||||||
|
|
||||||
wlr_xdg_popup.events.destroy.add(&xdg_popup.destroy);
|
wlr_xdg_popup.events.destroy.add(&xdg_popup.destroy);
|
||||||
@@ -86,6 +95,7 @@ fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_xdg_popup: *wlr.Xdg
|
|||||||
wlr_xdg_popup,
|
wlr_xdg_popup,
|
||||||
xdg_popup.root,
|
xdg_popup.root,
|
||||||
xdg_popup.tree,
|
xdg_popup.tree,
|
||||||
|
xdg_popup.image_capture_tree,
|
||||||
) catch {
|
) catch {
|
||||||
wlr_xdg_popup.resource.postNoMemory();
|
wlr_xdg_popup.resource.postNoMemory();
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ pub fn create(wlr_toplevel: *wlr.XdgToplevel) error{OutOfMemory}!void {
|
|||||||
errdefer toplevel.unmap.link.remove();
|
errdefer toplevel.unmap.link.remove();
|
||||||
|
|
||||||
_ = try view.surface_tree.createSceneXdgSurface(wlr_toplevel.base);
|
_ = try view.surface_tree.createSceneXdgSurface(wlr_toplevel.base);
|
||||||
|
_ = try view.image_capture_scene.tree.createSceneXdgSurface(wlr_toplevel.base);
|
||||||
|
|
||||||
toplevel.view = view;
|
toplevel.view = view;
|
||||||
|
|
||||||
@@ -282,7 +283,12 @@ fn handleUnmap(listener: *wl.Listener(void)) void {
|
|||||||
fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_xdg_popup: *wlr.XdgPopup) void {
|
fn handleNewPopup(listener: *wl.Listener(*wlr.XdgPopup), wlr_xdg_popup: *wlr.XdgPopup) void {
|
||||||
const toplevel: *XdgToplevel = @fieldParentPtr("new_popup", listener);
|
const toplevel: *XdgToplevel = @fieldParentPtr("new_popup", listener);
|
||||||
|
|
||||||
XdgPopup.create(wlr_xdg_popup, toplevel.view.popup_tree, toplevel.view.popup_tree) catch {
|
XdgPopup.create(
|
||||||
|
wlr_xdg_popup,
|
||||||
|
toplevel.view.popup_tree,
|
||||||
|
toplevel.view.popup_tree,
|
||||||
|
&toplevel.view.image_capture_scene.tree,
|
||||||
|
) catch {
|
||||||
wlr_xdg_popup.resource.postNoMemory();
|
wlr_xdg_popup.resource.postNoMemory();
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -179,6 +179,12 @@ pub fn handleMap(listener: *wl.Listener(void)) void {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_ = view.image_capture_scene.tree.createSceneSurface(surface) catch {
|
||||||
|
log.err("out of memory", .{});
|
||||||
|
surface.resource.getClient().postNoMemory();
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
view.pending.box = .{
|
view.pending.box = .{
|
||||||
.x = 0,
|
.x = 0,
|
||||||
.y = 0,
|
.y = 0,
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ pub fn sendToOutput(
|
|||||||
seat.focused.view.pending.tags = destination_output.pending.tags;
|
seat.focused.view.pending.tags = destination_output.pending.tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
seat.focused.view.setPendingOutput(destination_output);
|
seat.focused.view.setPendingOutput(destination_output, destination_output.attachMode());
|
||||||
|
|
||||||
// When explicitly sending a view to an output, the user likely
|
// When explicitly sending a view to an output, the user likely
|
||||||
// does not expect a previously evacuated view moved back to a
|
// does not expect a previously evacuated view moved back to a
|
||||||
|
|||||||
Reference in New Issue
Block a user