Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
wlr-foreign-toplevel-management: implement subset
Implement a small subset of the protocol which is used by fcitx5 to
provide critical input method functionality, namely window-specific
input method state.
It would be nice if the input method protocol itself provided this
information in the future...
river/Server.zig | 3 +++
river/Window.zig | 26 ++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/river/Server.zig b/river/Server.zig
index 89ee50f..f990fb0 100644
--- a/river/Server.zig
+++ b/river/Server.zig
@@ -84,6 +84,7 @@ screencopy_manager: *wlr.ScreencopyManagerV1,
image_copy_capture_manager: *wlr.ExtImageCopyCaptureManagerV1,
output_image_capture_source_manager: *wlr.ExtOutputImageCaptureSourceManagerV1,
+wlr_foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1,
foreign_toplevel_list: *wlr.ExtForeignToplevelListV1,
toplevel_capture_source_manager: *wlr.ExtForeignToplevelImageCaptureSourceManagerV1,
@@ -166,6 +167,7 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void {
.image_copy_capture_manager = try wlr.ExtImageCopyCaptureManagerV1.create(wl_server, 1),
.output_image_capture_source_manager = try wlr.ExtOutputImageCaptureSourceManagerV1.create(wl_server, 1),
+ .wlr_foreign_toplevel_manager = try wlr.ForeignToplevelManagerV1.create(wl_server),
.foreign_toplevel_list = try wlr.ExtForeignToplevelListV1.create(wl_server, 1),
.toplevel_capture_source_manager = try wlr.ExtForeignToplevelImageCaptureSourceManagerV1.create(wl_server, 1),
@@ -379,6 +381,7 @@ fn blocklist(server: *Server, global: *const wl.Global) bool {
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.wlr_foreign_toplevel_manager.global or
global == server.foreign_toplevel_list.global or
global == server.toplevel_capture_source_manager.global or
global == server.export_dmabuf_manager.global or
diff --git a/river/Window.zig b/river/Window.zig
index 9b05f45..5963a59 100644
--- a/river/Window.zig
+++ b/river/Window.zig
@@ -266,6 +266,7 @@ rendering_requested: RenderingRequested = .init,
box: wlr.Box = .{ .x = 0, .y = 0, .width = 0, .height = 0 },
foreign_toplevel_handle: ?*wlr.ExtForeignToplevelHandleV1 = null,
+wlr_toplevel_handle: ?*wlr.ForeignToplevelHandleV1 = null,
pub fn create(impl: Impl) error{OutOfMemory}!*Window {
assert(impl != .destroying);
@@ -430,6 +431,16 @@ pub fn manageStart(window: *Window) void {
}
}
+ if (window.wlr_toplevel_handle == null) {
+ if (wlr.ForeignToplevelHandleV1.create(server.wlr_foreign_toplevel_manager)) |handle| {
+ window.wlr_toplevel_handle = handle;
+ if (window.getTitle()) |title| handle.setTitle(title);
+ if (window.getAppId()) |app_id| handle.setAppId(app_id);
+ } else |_| {
+ log.err("failed to create wlr foreign toplevel handle", .{});
+ }
+ }
+
break :blk window_v1;
};
@@ -772,6 +783,10 @@ pub fn manageFinish(window: *Window) bool {
break :blk false;
};
+ if (window.wlr_toplevel_handle) |handle| {
+ handle.setActivated(activated);
+ }
+
const width, const height = blk: {
if (wm_requested.fullscreen) |output| {
const width, const height = output.sent.dimensions();
@@ -1150,6 +1165,11 @@ pub fn unmap(window: *Window) void {
window.foreign_toplevel_handle = null;
}
+ if (window.wlr_toplevel_handle) |handle| {
+ handle.destroy();
+ window.wlr_toplevel_handle = null;
+ }
+
{
var it = server.input_manager.seats.iterator(.forward);
while (it.next()) |seat| {
@@ -1170,6 +1190,9 @@ pub fn notifyTitle(window: *Window) void {
.app_id = window.getAppId(),
});
}
+ if (window.wlr_toplevel_handle) |handle| {
+ if (window.getTitle()) |title| handle.setTitle(title);
+ }
}
pub fn notifyAppId(window: *Window) void {
@@ -1182,4 +1205,7 @@ pub fn notifyAppId(window: *Window) void {
.app_id = window.getAppId(),
});
}
+ if (window.wlr_toplevel_handle) |handle| {
+ if (window.getAppId()) |app_id| handle.setAppId(app_id);
+ }
}