Xwayland: render using the scene graph
This commit is contained in:
parent
0b2272ec57
commit
ce7fda4ed9
@ -941,7 +941,7 @@ fn warp(self: *Self) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn updateDragIcons(self: *Self) void {
|
fn updateDragIcons(self: *Self) void {
|
||||||
var it = server.root.layers.drag_icons.children.iterator(.forward);
|
var it = server.root.drag_icons.children.iterator(.forward);
|
||||||
while (it.next()) |node| {
|
while (it.next()) |node| {
|
||||||
const icon = @intToPtr(*DragIcon, node.data);
|
const icon = @intToPtr(*DragIcon, node.data);
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ unmap: wl.Listener(*wlr.Drag.Icon) = wl.Listener(*wlr.Drag.Icon).init(handleUnma
|
|||||||
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
|
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
|
||||||
|
|
||||||
pub fn create(wlr_drag_icon: *wlr.Drag.Icon) error{OutOfMemory}!void {
|
pub fn create(wlr_drag_icon: *wlr.Drag.Icon) error{OutOfMemory}!void {
|
||||||
const tree = try server.root.layers.drag_icons.createSceneTree();
|
const tree = try server.root.drag_icons.createSceneTree();
|
||||||
errdefer tree.node.destroy();
|
errdefer tree.node.destroy();
|
||||||
|
|
||||||
const drag_icon = try util.gpa.create(DragIcon);
|
const drag_icon = try util.gpa.create(DragIcon);
|
||||||
|
@ -37,15 +37,20 @@ const ViewStack = @import("view_stack.zig").ViewStack;
|
|||||||
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
|
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
|
||||||
|
|
||||||
scene: *wlr.Scene,
|
scene: *wlr.Scene,
|
||||||
/// All direct children of the root scene node
|
/// All windows, status bars, drowdown menus, etc. that can recieve pointer events and similar.
|
||||||
|
interactive_content: *wlr.SceneTree,
|
||||||
|
/// Drag icons, which cannot recieve e.g. pointer events and are therefore kept in a separate tree.
|
||||||
|
drag_icons: *wlr.SceneTree,
|
||||||
|
|
||||||
|
/// All direct children of the interactive_content scene node
|
||||||
layers: struct {
|
layers: struct {
|
||||||
/// Parent tree for output trees which have their position updated when
|
/// Parent tree for output trees which have their position updated when
|
||||||
/// outputs are moved in the layout.
|
/// outputs are moved in the layout.
|
||||||
outputs: *wlr.SceneTree,
|
outputs: *wlr.SceneTree,
|
||||||
/// Drag icons which have a position in layout coordinates that is updated
|
/// Xwayland override redirect windows are a legacy wart that decide where
|
||||||
/// on cursor/touch point movement.
|
/// to place themselves in layout coordinates. Unfortunately this is how
|
||||||
/// This tree is ignored by Root.at()
|
/// X11 decided to make dropdown menus and the like possible.
|
||||||
drag_icons: *wlr.SceneTree,
|
xwayland_override_redirect: if (build_options.xwayland) *wlr.SceneTree else void,
|
||||||
},
|
},
|
||||||
|
|
||||||
new_output: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleNewOutput),
|
new_output: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleNewOutput),
|
||||||
@ -73,14 +78,6 @@ outputs: std.TailQueue(Output) = .{},
|
|||||||
/// It is not advertised to clients.
|
/// It is not advertised to clients.
|
||||||
noop_output: Output = undefined,
|
noop_output: Output = undefined,
|
||||||
|
|
||||||
/// This list stores all "override redirect" Xwayland windows. This needs to be in root
|
|
||||||
/// since X is like the wild west and who knows where these things will place themselves.
|
|
||||||
xwayland_override_redirect_views: if (build_options.xwayland)
|
|
||||||
std.TailQueue(XwaylandOverrideRedirect)
|
|
||||||
else
|
|
||||||
void = if (build_options.xwayland)
|
|
||||||
.{},
|
|
||||||
|
|
||||||
/// Number of layout demands pending before the transaction may be started.
|
/// Number of layout demands pending before the transaction may be started.
|
||||||
pending_layout_demands: u32 = 0,
|
pending_layout_demands: u32 = 0,
|
||||||
/// Number of pending configures sent in the current transaction.
|
/// Number of pending configures sent in the current transaction.
|
||||||
@ -96,6 +93,12 @@ pub fn init(self: *Self) !void {
|
|||||||
const scene = try wlr.Scene.create();
|
const scene = try wlr.Scene.create();
|
||||||
errdefer scene.tree.node.destroy();
|
errdefer scene.tree.node.destroy();
|
||||||
|
|
||||||
|
const interactive_content = try scene.tree.createSceneTree();
|
||||||
|
const drag_icons = try scene.tree.createSceneTree();
|
||||||
|
|
||||||
|
const outputs = try interactive_content.createSceneTree();
|
||||||
|
const xwayland_override_redirect = if (build_options.xwayland) try interactive_content.createSceneTree();
|
||||||
|
|
||||||
try scene.attachOutputLayout(output_layout);
|
try scene.attachOutputLayout(output_layout);
|
||||||
|
|
||||||
_ = try wlr.XdgOutputManagerV1.create(server.wl_server, output_layout);
|
_ = try wlr.XdgOutputManagerV1.create(server.wl_server, output_layout);
|
||||||
@ -104,8 +107,6 @@ pub fn init(self: *Self) !void {
|
|||||||
const transaction_timer = try event_loop.addTimer(*Self, handleTransactionTimeout, self);
|
const transaction_timer = try event_loop.addTimer(*Self, handleTransactionTimeout, self);
|
||||||
errdefer transaction_timer.remove();
|
errdefer transaction_timer.remove();
|
||||||
|
|
||||||
const outputs = try scene.tree.createSceneTree();
|
|
||||||
|
|
||||||
// TODO get rid of this hack somehow
|
// TODO get rid of this hack somehow
|
||||||
const noop_wlr_output = try server.headless_backend.headlessAddOutput(1920, 1080);
|
const noop_wlr_output = try server.headless_backend.headlessAddOutput(1920, 1080);
|
||||||
const noop_tree = try outputs.createSceneTree();
|
const noop_tree = try outputs.createSceneTree();
|
||||||
@ -113,9 +114,11 @@ pub fn init(self: *Self) !void {
|
|||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.scene = scene,
|
.scene = scene,
|
||||||
|
.interactive_content = interactive_content,
|
||||||
|
.drag_icons = drag_icons,
|
||||||
.layers = .{
|
.layers = .{
|
||||||
.outputs = outputs,
|
.outputs = outputs,
|
||||||
.drag_icons = try scene.tree.createSceneTree(),
|
.xwayland_override_redirect = xwayland_override_redirect,
|
||||||
},
|
},
|
||||||
.output_layout = output_layout,
|
.output_layout = output_layout,
|
||||||
.output_manager = try wlr.OutputManagerV1.create(server.wl_server),
|
.output_manager = try wlr.OutputManagerV1.create(server.wl_server),
|
||||||
@ -170,12 +173,12 @@ pub const AtResult = struct {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Return information about what is currently rendered in the Root.layers.outputs
|
/// Return information about what is currently rendered in the interactive_content
|
||||||
/// tree at the given layout coordinates.
|
/// tree at the given layout coordinates, taking surface input regions into account.
|
||||||
pub fn at(self: Self, lx: f64, ly: f64) ?AtResult {
|
pub fn at(self: Self, lx: f64, ly: f64) ?AtResult {
|
||||||
var sx: f64 = undefined;
|
var sx: f64 = undefined;
|
||||||
var sy: f64 = undefined;
|
var sy: f64 = undefined;
|
||||||
const node_at = self.layers.outputs.node.at(lx, ly, &sx, &sy) orelse return null;
|
const node_at = self.interactive_content.node.at(lx, ly, &sx, &sy) orelse return null;
|
||||||
|
|
||||||
const surface: ?*wlr.Surface = blk: {
|
const surface: ?*wlr.Surface = blk: {
|
||||||
if (node_at.type == .buffer) {
|
if (node_at.type == .buffer) {
|
||||||
@ -199,6 +202,9 @@ pub fn at(self: Self, lx: f64, ly: f64) ?AtResult {
|
|||||||
.view => |view| .{ .view = view },
|
.view => |view| .{ .view = view },
|
||||||
.layer_surface => |layer_surface| .{ .layer_surface = layer_surface },
|
.layer_surface => |layer_surface| .{ .layer_surface = layer_surface },
|
||||||
.lock_surface => |lock_surface| .{ .lock_surface = lock_surface },
|
.lock_surface => |lock_surface| .{ .lock_surface = lock_surface },
|
||||||
|
.xwayland_override_redirect => |xwayland_override_redirect| .{
|
||||||
|
.xwayland_override_redirect = xwayland_override_redirect,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,13 @@ const util = @import("util.zig");
|
|||||||
const LayerSurface = @import("LayerSurface.zig");
|
const LayerSurface = @import("LayerSurface.zig");
|
||||||
const LockSurface = @import("LockSurface.zig");
|
const LockSurface = @import("LockSurface.zig");
|
||||||
const View = @import("View.zig");
|
const View = @import("View.zig");
|
||||||
|
const XwaylandOverrideRedirect = @import("XwaylandOverrideRedirect.zig");
|
||||||
|
|
||||||
const Data = union(enum) {
|
const Data = union(enum) {
|
||||||
view: *View,
|
view: *View,
|
||||||
lock_surface: *LockSurface,
|
lock_surface: *LockSurface,
|
||||||
layer_surface: *LayerSurface,
|
layer_surface: *LayerSurface,
|
||||||
|
xwayland_override_redirect: if (build_options.xwayland) *XwaylandOverrideRedirect else noreturn,
|
||||||
};
|
};
|
||||||
|
|
||||||
node: *wlr.SceneNode,
|
node: *wlr.SceneNode,
|
||||||
|
@ -25,41 +25,42 @@ const wl = @import("wayland").server.wl;
|
|||||||
const server = &@import("main.zig").server;
|
const server = &@import("main.zig").server;
|
||||||
const util = @import("util.zig");
|
const util = @import("util.zig");
|
||||||
|
|
||||||
|
const SceneNodeData = @import("SceneNodeData.zig");
|
||||||
const View = @import("View.zig");
|
const View = @import("View.zig");
|
||||||
const XwaylandView = @import("XwaylandView.zig");
|
|
||||||
const ViewStack = @import("view_stack.zig").ViewStack;
|
const ViewStack = @import("view_stack.zig").ViewStack;
|
||||||
|
const XwaylandView = @import("XwaylandView.zig");
|
||||||
|
|
||||||
const log = std.log.scoped(.xwayland);
|
const log = std.log.scoped(.xwayland);
|
||||||
|
|
||||||
/// The corresponding wlroots object
|
|
||||||
xwayland_surface: *wlr.XwaylandSurface,
|
xwayland_surface: *wlr.XwaylandSurface,
|
||||||
|
surface_tree: ?*wlr.SceneTree = null,
|
||||||
|
|
||||||
// Listeners that are always active over the view's lifetime
|
|
||||||
request_configure: wl.Listener(*wlr.XwaylandSurface.event.Configure) =
|
request_configure: wl.Listener(*wlr.XwaylandSurface.event.Configure) =
|
||||||
wl.Listener(*wlr.XwaylandSurface.event.Configure).init(handleRequestConfigure),
|
wl.Listener(*wlr.XwaylandSurface.event.Configure).init(handleRequestConfigure),
|
||||||
destroy: wl.Listener(*wlr.XwaylandSurface) = wl.Listener(*wlr.XwaylandSurface).init(handleDestroy),
|
destroy: wl.Listener(*wlr.XwaylandSurface) = wl.Listener(*wlr.XwaylandSurface).init(handleDestroy),
|
||||||
map: wl.Listener(*wlr.XwaylandSurface) = wl.Listener(*wlr.XwaylandSurface).init(handleMap),
|
map: wl.Listener(*wlr.XwaylandSurface) = wl.Listener(*wlr.XwaylandSurface).init(handleMap),
|
||||||
unmap: wl.Listener(*wlr.XwaylandSurface) = wl.Listener(*wlr.XwaylandSurface).init(handleUnmap),
|
unmap: wl.Listener(*wlr.XwaylandSurface) = wl.Listener(*wlr.XwaylandSurface).init(handleUnmap),
|
||||||
|
set_geometry: wl.Listener(*wlr.XwaylandSurface) = wl.Listener(*wlr.XwaylandSurface).init(handleSetGeometry),
|
||||||
set_override_redirect: wl.Listener(*wlr.XwaylandSurface) =
|
set_override_redirect: wl.Listener(*wlr.XwaylandSurface) =
|
||||||
wl.Listener(*wlr.XwaylandSurface).init(handleSetOverrideRedirect),
|
wl.Listener(*wlr.XwaylandSurface).init(handleSetOverrideRedirect),
|
||||||
|
|
||||||
/// The override redirect surface will add itself to the list in Root when it is mapped.
|
pub fn create(xwayland_surface: *wlr.XwaylandSurface) error{OutOfMemory}!void {
|
||||||
pub fn create(xwayland_surface: *wlr.XwaylandSurface) error{OutOfMemory}!*Self {
|
const self = try util.gpa.create(Self);
|
||||||
const node = try util.gpa.create(std.TailQueue(Self).Node);
|
errdefer util.gpa.destroy(self);
|
||||||
const self = &node.data;
|
|
||||||
|
|
||||||
self.* = .{ .xwayland_surface = xwayland_surface };
|
self.* = .{ .xwayland_surface = xwayland_surface };
|
||||||
// This must be set to 0 for usage in View.fromWlrSurface()
|
// This must be set to 0 for usage in View.fromWlrSurface()
|
||||||
xwayland_surface.data = 0;
|
xwayland_surface.data = 0;
|
||||||
|
|
||||||
// Add listeners that are active over the the entire lifetime
|
|
||||||
xwayland_surface.events.request_configure.add(&self.request_configure);
|
xwayland_surface.events.request_configure.add(&self.request_configure);
|
||||||
xwayland_surface.events.destroy.add(&self.destroy);
|
xwayland_surface.events.destroy.add(&self.destroy);
|
||||||
xwayland_surface.events.map.add(&self.map);
|
xwayland_surface.events.map.add(&self.map);
|
||||||
xwayland_surface.events.unmap.add(&self.unmap);
|
xwayland_surface.events.unmap.add(&self.unmap);
|
||||||
xwayland_surface.events.set_override_redirect.add(&self.set_override_redirect);
|
xwayland_surface.events.set_override_redirect.add(&self.set_override_redirect);
|
||||||
|
|
||||||
return self;
|
if (xwayland_surface.mapped) {
|
||||||
|
handleMap(&self.map, xwayland_surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleRequestConfigure(
|
fn handleRequestConfigure(
|
||||||
@ -69,28 +70,36 @@ fn handleRequestConfigure(
|
|||||||
event.surface.configure(event.x, event.y, event.width, event.height);
|
event.surface.configure(event.x, event.y, event.width, event.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the xwayland surface is destroyed
|
|
||||||
fn handleDestroy(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
|
fn handleDestroy(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
|
||||||
const self = @fieldParentPtr(Self, "destroy", listener);
|
const self = @fieldParentPtr(Self, "destroy", listener);
|
||||||
|
|
||||||
// Remove listeners that are active for the entire lifetime
|
|
||||||
self.request_configure.link.remove();
|
self.request_configure.link.remove();
|
||||||
self.destroy.link.remove();
|
self.destroy.link.remove();
|
||||||
self.map.link.remove();
|
self.map.link.remove();
|
||||||
self.unmap.link.remove();
|
self.unmap.link.remove();
|
||||||
self.set_override_redirect.link.remove();
|
self.set_override_redirect.link.remove();
|
||||||
|
|
||||||
// Deallocate the node
|
util.gpa.destroy(self);
|
||||||
const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self);
|
|
||||||
util.gpa.destroy(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the xwayland surface is mapped, or ready to display on-screen.
|
|
||||||
pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
|
pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
|
||||||
const self = @fieldParentPtr(Self, "map", listener);
|
const self = @fieldParentPtr(Self, "map", listener);
|
||||||
|
|
||||||
const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self);
|
self.mapImpl() catch {
|
||||||
server.root.xwayland_override_redirect_views.prepend(node);
|
log.err("out of memory", .{});
|
||||||
|
self.xwayland_surface.surface.?.resource.getClient().postNoMemory();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mapImpl(self: *Self) error{OutOfMemory}!void {
|
||||||
|
self.surface_tree = try server.root.layers.xwayland_override_redirect.createSceneSubsurfaceTree(
|
||||||
|
self.xwayland_surface.surface.?,
|
||||||
|
);
|
||||||
|
try SceneNodeData.attach(&self.surface_tree.?.node, .{ .xwayland_override_redirect = self });
|
||||||
|
|
||||||
|
self.surface_tree.?.node.setPosition(self.xwayland_surface.x, self.xwayland_surface.y);
|
||||||
|
|
||||||
|
self.xwayland_surface.events.set_geometry.add(&self.set_geometry);
|
||||||
|
|
||||||
self.focusIfDesired();
|
self.focusIfDesired();
|
||||||
}
|
}
|
||||||
@ -117,12 +126,13 @@ pub fn focusIfDesired(self: *Self) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the surface is unmapped and will no longer be displayed.
|
|
||||||
fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
|
fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
|
||||||
const self = @fieldParentPtr(Self, "unmap", listener);
|
const self = @fieldParentPtr(Self, "unmap", listener);
|
||||||
|
|
||||||
const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self);
|
self.set_geometry.link.remove();
|
||||||
server.root.xwayland_override_redirect_views.remove(node);
|
|
||||||
|
self.surface_tree.?.node.destroy();
|
||||||
|
self.surface_tree = null;
|
||||||
|
|
||||||
// If the unmapped surface is currently focused, pass keyboard focus
|
// If the unmapped surface is currently focused, pass keyboard focus
|
||||||
// to the most appropriate surface.
|
// to the most appropriate surface.
|
||||||
@ -144,6 +154,12 @@ fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSur
|
|||||||
server.root.startTransaction();
|
server.root.startTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handleSetGeometry(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
|
||||||
|
const self = @fieldParentPtr(Self, "set_geometry", listener);
|
||||||
|
|
||||||
|
self.surface_tree.?.node.setPosition(self.xwayland_surface.x, self.xwayland_surface.y);
|
||||||
|
}
|
||||||
|
|
||||||
fn handleSetOverrideRedirect(
|
fn handleSetOverrideRedirect(
|
||||||
listener: *wl.Listener(*wlr.XwaylandSurface),
|
listener: *wl.Listener(*wlr.XwaylandSurface),
|
||||||
xwayland_surface: *wlr.XwaylandSurface,
|
xwayland_surface: *wlr.XwaylandSurface,
|
||||||
@ -158,12 +174,8 @@ fn handleSetOverrideRedirect(
|
|||||||
handleDestroy(&self.destroy, xwayland_surface);
|
handleDestroy(&self.destroy, xwayland_surface);
|
||||||
|
|
||||||
const output = server.input_manager.defaultSeat().focused_output;
|
const output = server.input_manager.defaultSeat().focused_output;
|
||||||
const xwayland_view = XwaylandView.create(output, xwayland_surface) catch {
|
XwaylandView.create(output, xwayland_surface) catch {
|
||||||
log.err("out of memory", .{});
|
log.err("out of memory", .{});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (xwayland_surface.mapped) {
|
|
||||||
XwaylandView.handleMap(&xwayland_view.map, xwayland_surface);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,9 @@ const log = std.log.scoped(.xwayland);
|
|||||||
/// The view this xwayland view implements
|
/// The view this xwayland view implements
|
||||||
view: *View,
|
view: *View,
|
||||||
|
|
||||||
/// The corresponding wlroots object
|
|
||||||
xwayland_surface: *wlr.XwaylandSurface,
|
xwayland_surface: *wlr.XwaylandSurface,
|
||||||
|
/// Created on map and destroyed on unmap
|
||||||
|
surface_tree: ?*wlr.SceneTree = null,
|
||||||
|
|
||||||
/// The wlroots Xwayland implementation overwrites xwayland_surface.fullscreen
|
/// The wlroots Xwayland implementation overwrites xwayland_surface.fullscreen
|
||||||
/// immediately when the client requests it, so we track this state here to be
|
/// immediately when the client requests it, so we track this state here to be
|
||||||
@ -62,8 +63,7 @@ request_fullscreen: wl.Listener(*wlr.XwaylandSurface) =
|
|||||||
request_minimize: wl.Listener(*wlr.XwaylandSurface.event.Minimize) =
|
request_minimize: wl.Listener(*wlr.XwaylandSurface.event.Minimize) =
|
||||||
wl.Listener(*wlr.XwaylandSurface.event.Minimize).init(handleRequestMinimize),
|
wl.Listener(*wlr.XwaylandSurface.event.Minimize).init(handleRequestMinimize),
|
||||||
|
|
||||||
/// The View will add itself to the output's view stack on map
|
pub fn create(output: *Output, xwayland_surface: *wlr.XwaylandSurface) error{OutOfMemory}!void {
|
||||||
pub fn create(output: *Output, xwayland_surface: *wlr.XwaylandSurface) error{OutOfMemory}!*Self {
|
|
||||||
const node = try util.gpa.create(ViewStack(View).Node);
|
const node = try util.gpa.create(ViewStack(View).Node);
|
||||||
const view = &node.view;
|
const view = &node.view;
|
||||||
|
|
||||||
@ -84,7 +84,9 @@ pub fn create(output: *Output, xwayland_surface: *wlr.XwaylandSurface) error{Out
|
|||||||
xwayland_surface.events.request_configure.add(&self.request_configure);
|
xwayland_surface.events.request_configure.add(&self.request_configure);
|
||||||
xwayland_surface.events.set_override_redirect.add(&self.set_override_redirect);
|
xwayland_surface.events.set_override_redirect.add(&self.set_override_redirect);
|
||||||
|
|
||||||
return self;
|
if (xwayland_surface.mapped) {
|
||||||
|
handleMap(&self.map, xwayland_surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn needsConfigure(self: Self) bool {
|
pub fn needsConfigure(self: Self) bool {
|
||||||
@ -181,7 +183,6 @@ fn handleDestroy(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandS
|
|||||||
self.view.destroy();
|
self.view.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the xwayland surface is mapped, or ready to display on-screen.
|
|
||||||
pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wlr.XwaylandSurface) void {
|
pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wlr.XwaylandSurface) void {
|
||||||
const self = @fieldParentPtr(Self, "map", listener);
|
const self = @fieldParentPtr(Self, "map", listener);
|
||||||
const view = self.view;
|
const view = self.view;
|
||||||
@ -194,12 +195,13 @@ pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface:
|
|||||||
xwayland_surface.events.request_fullscreen.add(&self.request_fullscreen);
|
xwayland_surface.events.request_fullscreen.add(&self.request_fullscreen);
|
||||||
xwayland_surface.events.request_minimize.add(&self.request_minimize);
|
xwayland_surface.events.request_minimize.add(&self.request_minimize);
|
||||||
|
|
||||||
const surface_tree = view.tree.createSceneSubsurfaceTree(surface) catch {
|
self.surface_tree = view.tree.createSceneSubsurfaceTree(surface) catch {
|
||||||
log.err("out of memory", .{});
|
log.err("out of memory", .{});
|
||||||
surface.resource.getClient().postNoMemory();
|
surface.resource.getClient().postNoMemory();
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
surface_tree.node.lowerToBottom();
|
// Place the node below the view's border nodes
|
||||||
|
self.surface_tree.?.node.lowerToBottom();
|
||||||
|
|
||||||
// Use the view's "natural" size centered on the output as the default
|
// Use the view's "natural" size centered on the output as the default
|
||||||
// floating dimensions
|
// floating dimensions
|
||||||
@ -231,10 +233,12 @@ pub fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface:
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the surface is unmapped and will no longer be displayed.
|
|
||||||
fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
|
fn handleUnmap(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandSurface) void {
|
||||||
const self = @fieldParentPtr(Self, "unmap", listener);
|
const self = @fieldParentPtr(Self, "unmap", listener);
|
||||||
|
|
||||||
|
self.surface_tree.?.node.destroy();
|
||||||
|
self.surface_tree = null;
|
||||||
|
|
||||||
// Remove listeners that are only active while mapped
|
// Remove listeners that are only active while mapped
|
||||||
self.commit.link.remove();
|
self.commit.link.remove();
|
||||||
self.set_title.link.remove();
|
self.set_title.link.remove();
|
||||||
@ -278,14 +282,10 @@ fn handleSetOverrideRedirect(
|
|||||||
if (xwayland_surface.mapped) handleUnmap(&self.unmap, xwayland_surface);
|
if (xwayland_surface.mapped) handleUnmap(&self.unmap, xwayland_surface);
|
||||||
handleDestroy(&self.destroy, xwayland_surface);
|
handleDestroy(&self.destroy, xwayland_surface);
|
||||||
|
|
||||||
const override_redirect = XwaylandOverrideRedirect.create(xwayland_surface) catch {
|
XwaylandOverrideRedirect.create(xwayland_surface) catch {
|
||||||
log.err("out of memory", .{});
|
log.err("out of memory", .{});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (xwayland_surface.mapped) {
|
|
||||||
XwaylandOverrideRedirect.handleMap(&override_redirect.map, xwayland_surface);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handleCommit(listener: *wl.Listener(*wlr.Surface), surface: *wlr.Surface) void {
|
fn handleCommit(listener: *wl.Listener(*wlr.Surface), surface: *wlr.Surface) void {
|
||||||
|
Loading…
Reference in New Issue
Block a user