Xwayland: handle override redirect state changes
This commit is contained in:
parent
8a8dd9ff65
commit
6ef97eea24
@ -193,7 +193,7 @@ fn handleNewXdgSurface(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wl
|
|||||||
xdg_surface.resource.postNoMemory();
|
xdg_surface.resource.postNoMemory();
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
node.view.init(output, getNewViewTags(output), xdg_surface);
|
node.view.init(output, xdg_surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This event is raised when the layer_shell recieves a new surface from a client.
|
/// This event is raised when the layer_shell recieves a new surface from a client.
|
||||||
@ -259,10 +259,5 @@ fn handleNewXwaylandSurface(listener: *wl.Listener(*wlr.XwaylandSurface), wlr_xw
|
|||||||
// The View will add itself to the output's view stack on map
|
// The View will add itself to the output's view stack on map
|
||||||
const output = self.input_manager.defaultSeat().focused_output;
|
const output = self.input_manager.defaultSeat().focused_output;
|
||||||
const node = util.gpa.create(ViewStack(View).Node) catch return;
|
const node = util.gpa.create(ViewStack(View).Node) catch return;
|
||||||
node.view.init(output, getNewViewTags(output), wlr_xwayland_surface);
|
node.view.init(output, wlr_xwayland_surface);
|
||||||
}
|
|
||||||
|
|
||||||
fn getNewViewTags(output: *Output) u32 {
|
|
||||||
const tags = output.current.tags & output.spawn_tagmask;
|
|
||||||
return if (tags != 0) tags else output.current.tags;
|
|
||||||
}
|
}
|
||||||
|
@ -126,11 +126,16 @@ foreign_close: wl.Listener(*wlr.ForeignToplevelHandleV1) =
|
|||||||
request_activate: wl.Listener(*wlr.XdgActivationV1.event.RequestActivate) =
|
request_activate: wl.Listener(*wlr.XdgActivationV1.event.RequestActivate) =
|
||||||
wl.Listener(*wlr.XdgActivationV1.event.RequestActivate).init(handleRequestActivate),
|
wl.Listener(*wlr.XdgActivationV1.event.RequestActivate).init(handleRequestActivate),
|
||||||
|
|
||||||
pub fn init(self: *Self, output: *Output, tags: u32, surface: anytype) void {
|
pub fn init(self: *Self, output: *Output, surface: anytype) void {
|
||||||
|
const initial_tags = blk: {
|
||||||
|
const tags = output.current.tags & output.spawn_tagmask;
|
||||||
|
break :blk if (tags != 0) tags else output.current.tags;
|
||||||
|
};
|
||||||
|
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.output = output,
|
.output = output,
|
||||||
.current = .{ .tags = tags },
|
.current = .{ .tags = initial_tags },
|
||||||
.pending = .{ .tags = tags },
|
.pending = .{ .tags = initial_tags },
|
||||||
.saved_buffers = std.ArrayList(SavedBuffer).init(util.gpa),
|
.saved_buffers = std.ArrayList(SavedBuffer).init(util.gpa),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
const wlr = @import("wlroots");
|
const wlr = @import("wlroots");
|
||||||
const wl = @import("wayland").server.wl;
|
const wl = @import("wayland").server.wl;
|
||||||
|
|
||||||
@ -24,6 +26,11 @@ const server = &@import("main.zig").server;
|
|||||||
const util = @import("util.zig");
|
const util = @import("util.zig");
|
||||||
|
|
||||||
const Box = @import("Box.zig");
|
const Box = @import("Box.zig");
|
||||||
|
const View = @import("View.zig");
|
||||||
|
const XwaylandView = @import("XwaylandView.zig");
|
||||||
|
const ViewStack = @import("view_stack.zig").ViewStack;
|
||||||
|
|
||||||
|
const log = std.log.scoped(.xwayland);
|
||||||
|
|
||||||
/// The corresponding wlroots object
|
/// The corresponding wlroots object
|
||||||
xwayland_surface: *wlr.XwaylandSurface,
|
xwayland_surface: *wlr.XwaylandSurface,
|
||||||
@ -34,6 +41,10 @@ request_configure: wl.Listener(*wlr.XwaylandSurface.event.Configure) =
|
|||||||
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_override_redirect: wl.Listener(*wlr.XwaylandSurface) =
|
||||||
|
wl.Listener(*wlr.XwaylandSurface).init(handleSetOverrideRedirect),
|
||||||
|
|
||||||
|
// Listeners that are only active while mapped
|
||||||
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
|
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
|
||||||
|
|
||||||
pub fn init(self: *Self, xwayland_surface: *wlr.XwaylandSurface) void {
|
pub fn init(self: *Self, xwayland_surface: *wlr.XwaylandSurface) void {
|
||||||
@ -69,7 +80,7 @@ fn handleDestroy(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandS
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the xwayland surface is mapped, or ready to display on-screen.
|
/// Called when the xwayland surface is mapped, or ready to display on-screen.
|
||||||
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);
|
||||||
|
|
||||||
// Add self to the list of unmanaged views in the root
|
// Add self to the list of unmanaged views in the root
|
||||||
@ -110,3 +121,29 @@ fn handleCommit(_: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
|
|||||||
var it = server.root.outputs.first;
|
var it = server.root.outputs.first;
|
||||||
while (it) |node| : (it = node.next) node.data.damage.addWhole();
|
while (it) |node| : (it = node.next) node.data.damage.addWhole();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handleSetOverrideRedirect(
|
||||||
|
listener: *wl.Listener(*wlr.XwaylandSurface),
|
||||||
|
xwayland_surface: *wlr.XwaylandSurface,
|
||||||
|
) void {
|
||||||
|
const self = @fieldParentPtr(Self, "set_override_redirect", listener);
|
||||||
|
|
||||||
|
log.debug("xwayland surface unset override redirect, switching to managed", .{});
|
||||||
|
|
||||||
|
assert(!xwayland_surface.override_redirect);
|
||||||
|
|
||||||
|
if (xwayland_surface.mapped) handleUnmap(&self.unmap, xwayland_surface);
|
||||||
|
handleDestroy(&self.destroy, xwayland_surface);
|
||||||
|
|
||||||
|
// The View will add itself to the output's view stack on map
|
||||||
|
const output = server.input_manager.defaultSeat().focused_output;
|
||||||
|
const node = util.gpa.create(ViewStack(View).Node) catch {
|
||||||
|
log.err("out of memory", .{});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
node.view.init(output, xwayland_surface);
|
||||||
|
|
||||||
|
if (xwayland_surface.mapped) {
|
||||||
|
XwaylandView.handleMap(&node.view.impl.xwayland_view.map, xwayland_surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,16 +17,22 @@
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
const math = std.math;
|
const math = std.math;
|
||||||
|
|
||||||
const wlr = @import("wlroots");
|
const wlr = @import("wlroots");
|
||||||
const wl = @import("wayland").server.wl;
|
const wl = @import("wayland").server.wl;
|
||||||
|
|
||||||
const server = &@import("main.zig").server;
|
const server = &@import("main.zig").server;
|
||||||
|
const util = @import("util.zig");
|
||||||
|
|
||||||
const Box = @import("Box.zig");
|
const Box = @import("Box.zig");
|
||||||
const View = @import("View.zig");
|
const View = @import("View.zig");
|
||||||
const ViewStack = @import("view_stack.zig").ViewStack;
|
const ViewStack = @import("view_stack.zig").ViewStack;
|
||||||
const XdgPopup = @import("XdgPopup.zig");
|
const XdgPopup = @import("XdgPopup.zig");
|
||||||
|
const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig");
|
||||||
|
|
||||||
|
const log = std.log.scoped(.xwayland);
|
||||||
|
|
||||||
/// The view this xwayland view implements
|
/// The view this xwayland view implements
|
||||||
view: *View,
|
view: *View,
|
||||||
@ -45,6 +51,8 @@ map: wl.Listener(*wlr.XwaylandSurface) = wl.Listener(*wlr.XwaylandSurface).init(
|
|||||||
unmap: wl.Listener(*wlr.XwaylandSurface) = wl.Listener(*wlr.XwaylandSurface).init(handleUnmap),
|
unmap: wl.Listener(*wlr.XwaylandSurface) = wl.Listener(*wlr.XwaylandSurface).init(handleUnmap),
|
||||||
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),
|
||||||
|
set_override_redirect: wl.Listener(*wlr.XwaylandSurface) =
|
||||||
|
wl.Listener(*wlr.XwaylandSurface).init(handleSetOverrideRedirect),
|
||||||
|
|
||||||
// Listeners that are only active while the view is mapped
|
// Listeners that are only active while the view is mapped
|
||||||
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
|
commit: wl.Listener(*wlr.Surface) = wl.Listener(*wlr.Surface).init(handleCommit),
|
||||||
@ -176,7 +184,7 @@ fn handleDestroy(listener: *wl.Listener(*wlr.XwaylandSurface), _: *wlr.XwaylandS
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Called when the xwayland surface is mapped, or ready to display on-screen.
|
/// Called when the xwayland surface is mapped, or ready to display on-screen.
|
||||||
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;
|
||||||
|
|
||||||
@ -223,7 +231,7 @@ fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wl
|
|||||||
}
|
}
|
||||||
|
|
||||||
view.map() catch {
|
view.map() catch {
|
||||||
std.log.err("out of memory", .{});
|
log.err("out of memory", .{});
|
||||||
surface.resource.getClient().postNoMemory();
|
surface.resource.getClient().postNoMemory();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -262,6 +270,32 @@ fn handleRequestConfigure(
|
|||||||
self.configure();
|
self.configure();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handleSetOverrideRedirect(
|
||||||
|
listener: *wl.Listener(*wlr.XwaylandSurface),
|
||||||
|
xwayland_surface: *wlr.XwaylandSurface,
|
||||||
|
) void {
|
||||||
|
const self = @fieldParentPtr(Self, "set_override_redirect", listener);
|
||||||
|
|
||||||
|
log.debug("xwayland surface set override redirect, switching to unmanaged", .{});
|
||||||
|
|
||||||
|
assert(xwayland_surface.override_redirect);
|
||||||
|
|
||||||
|
if (xwayland_surface.mapped) handleUnmap(&self.unmap, xwayland_surface);
|
||||||
|
handleDestroy(&self.destroy, xwayland_surface);
|
||||||
|
|
||||||
|
// The unmanged surface will add itself to the list of unmanaged views
|
||||||
|
// in Root when it is mapped.
|
||||||
|
const node = util.gpa.create(std.TailQueue(XwaylandUnmanaged).Node) catch {
|
||||||
|
log.err("out of memory", .{});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
node.data.init(xwayland_surface);
|
||||||
|
|
||||||
|
if (xwayland_surface.mapped) {
|
||||||
|
XwaylandUnmanaged.handleMap(&node.data.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 {
|
||||||
const self = @fieldParentPtr(Self, "commit", listener);
|
const self = @fieldParentPtr(Self, "commit", listener);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user