commit - fa1a1b01bda020cb10fee649d8c5f34b749289cd
commit + 0d2b1235479134adf59940ca6d8dd58de7ccfbd1
blob - 5d0f06871a5a131915fdae0264cf28dd28031cbf
blob + d6c8e420e337d750ddf45767c43548b31995b359
--- river/Server.zig
+++ river/Server.zig
const XdgToplevel = @import("XdgToplevel.zig");
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
const XwaylandView = @import("XwaylandView.zig");
+const View = @import("View.zig");
const log = std.log.scoped(.server);
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,
wl.Listener(*wlr.XdgActivationV1.event.RequestActivate).init(handleRequestActivate),
request_set_cursor_shape: wl.Listener(*wlr.CursorShapeManagerV1.event.RequestSetShape) =
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 {
// We intentionally don't try to prevent memory leaks on error in this function
.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),
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.data_control_manager.global or
global == server.layout_manager.global or
}
}
}
+
+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);
+ }
+}
blob - f3380a0bae03f8a0123832fd443b8c16891a0229
blob + 8cba7d0e9ab5371a213a477a38d87eb33754ae7b
--- river/View.zig
+++ river/View.zig
borders: [4]*wlr.SceneRect,
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.
constraints: Constraints = .{},
},
.popup_tree = popup_tree,
+ .image_capture_scene = try wlr.Scene.create(),
+ .image_capture_source = null,
+
.pending_wm_stack_link = undefined,
.pending_focus_stack_link = undefined,
.inflight_wm_stack_link = undefined,
view.tree.node.setEnabled(false);
view.popup_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.popup_tree.node, .{ .view = view });
// around until the current transaction completes. This function will be
// called again in Root.commitTransaction()
if (!view.saved_surface_tree.node.enabled) {
+ view.image_capture_scene.tree.node.destroy();
view.tree.node.destroy();
view.popup_tree.node.destroy();
.app_id = view.getAppId(),
})) |handle| {
view.ext_foreign_toplevel_handle = handle;
+ handle.data = view;
} else |_| {
log.err("failed to create ext foreign toplevel handle", .{});
}
blob - 4fa775c12567c57d744b96a1fad5ddf3faf90738
blob + 02c0537e15b1c24b9cf313a3919061945d9fffcf
--- river/XdgToplevel.zig
+++ river/XdgToplevel.zig
errdefer toplevel.unmap.link.remove();
_ = try view.surface_tree.createSceneXdgSurface(wlr_toplevel.base);
+ _ = try view.image_capture_scene.tree.createSceneXdgSurface(wlr_toplevel.base);
toplevel.view = view;
blob - 836de81edddcbb8bb5c7a260519323a0658dc1c7
blob + 5224be4b194d184fd7e72a430345e29f5d72fbc2
--- river/XwaylandView.zig
+++ river/XwaylandView.zig
return;
};
+ _ = view.image_capture_scene.tree.createSceneSurface(surface) catch {
+ log.err("out of memory", .{});
+ surface.resource.getClient().postNoMemory();
+ return;
+ };
+
view.pending.box = .{
.x = 0,
.y = 0,