View: fix assertion failure if focused while destroying

Also clean up this code a bit, it's no longer necessary to split these
one line functions out into separate files as Zig's conditional
compilation support has improved since these functions were originally
written.
This commit is contained in:
Isaac Freund 2024-04-08 12:54:05 +02:00
parent 93f9eb8e5e
commit 3594fe501e
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
3 changed files with 17 additions and 55 deletions

View File

@ -453,12 +453,14 @@ pub fn configure(view: *View) bool {
} }
} }
pub fn rootSurface(view: View) *wlr.Surface { /// Returns null if the view is currently being destroyed and no longer has
assert(view.mapped and !view.destroying); /// an associated surface.
/// May also return null for Xwayland views that are not currently mapped.
pub fn rootSurface(view: View) ?*wlr.Surface {
return switch (view.impl) { return switch (view.impl) {
.toplevel => |toplevel| toplevel.rootSurface(), .toplevel => |toplevel| toplevel.wlr_toplevel.base.surface,
.xwayland_view => |xwayland_view| xwayland_view.rootSurface(), .xwayland_view => |xwayland_view| xwayland_view.xwayland_surface.surface,
.none => unreachable, .none => null,
}; };
} }
@ -466,7 +468,7 @@ pub fn sendFrameDone(view: View) void {
assert(view.mapped and !view.destroying); assert(view.mapped and !view.destroying);
var now: os.timespec = undefined; var now: os.timespec = undefined;
os.clock_gettime(os.CLOCK.MONOTONIC, &now) catch @panic("CLOCK_MONOTONIC not supported"); os.clock_gettime(os.CLOCK.MONOTONIC, &now) catch @panic("CLOCK_MONOTONIC not supported");
view.rootSurface().sendFrameDone(&now); view.rootSurface().?.sendFrameDone(&now);
} }
pub fn dropSavedSurfaceTree(view: *View) void { pub fn dropSavedSurfaceTree(view: *View) void {
@ -528,20 +530,17 @@ pub fn setPendingOutput(view: *View, output: *Output) void {
} }
pub fn close(view: View) void { pub fn close(view: View) void {
assert(!view.destroying);
switch (view.impl) { switch (view.impl) {
.toplevel => |toplevel| toplevel.close(), .toplevel => |toplevel| toplevel.wlr_toplevel.sendClose(),
.xwayland_view => |xwayland_view| xwayland_view.close(), .xwayland_view => |xwayland_view| xwayland_view.xwayland_surface.close(),
.none => unreachable, .none => {},
} }
} }
pub fn destroyPopups(view: View) void { pub fn destroyPopups(view: View) void {
assert(!view.destroying);
switch (view.impl) { switch (view.impl) {
.toplevel => |toplevel| toplevel.destroyPopups(), .toplevel => |toplevel| toplevel.destroyPopups(),
.xwayland_view => {}, .xwayland_view, .none => {},
.none => unreachable,
} }
} }
@ -549,8 +548,8 @@ pub fn destroyPopups(view: View) void {
pub fn getTitle(view: View) ?[*:0]const u8 { pub fn getTitle(view: View) ?[*:0]const u8 {
assert(!view.destroying); assert(!view.destroying);
return switch (view.impl) { return switch (view.impl) {
.toplevel => |toplevel| toplevel.getTitle(), .toplevel => |toplevel| toplevel.wlr_toplevel.title,
.xwayland_view => |xwayland_view| xwayland_view.getTitle(), .xwayland_view => |xwayland_view| xwayland_view.xwayland_surface.title,
.none => unreachable, .none => unreachable,
}; };
} }
@ -559,8 +558,9 @@ pub fn getTitle(view: View) ?[*:0]const u8 {
pub fn getAppId(view: View) ?[*:0]const u8 { pub fn getAppId(view: View) ?[*:0]const u8 {
assert(!view.destroying); assert(!view.destroying);
return switch (view.impl) { return switch (view.impl) {
.toplevel => |toplevel| toplevel.getAppId(), .toplevel => |toplevel| toplevel.wlr_toplevel.app_id,
.xwayland_view => |xwayland_view| xwayland_view.getAppId(), // X11 clients don't have an app_id but the class serves a similar role.
.xwayland_view => |xwayland_view| xwayland_view.xwayland_surface.class,
.none => unreachable, .none => unreachable,
}; };
} }

View File

@ -194,25 +194,6 @@ pub fn configure(toplevel: *XdgToplevel) bool {
return true; return true;
} }
pub fn rootSurface(toplevel: XdgToplevel) *wlr.Surface {
return toplevel.wlr_toplevel.base.surface;
}
/// Close the view. This will lead to the unmap and destroy events being sent
pub fn close(toplevel: XdgToplevel) void {
toplevel.wlr_toplevel.sendClose();
}
/// Return the current title of the toplevel if any.
pub fn getTitle(toplevel: XdgToplevel) ?[*:0]const u8 {
return toplevel.wlr_toplevel.title;
}
/// Return the current app_id of the toplevel if any .
pub fn getAppId(toplevel: XdgToplevel) ?[*:0]const u8 {
return toplevel.wlr_toplevel.app_id;
}
pub fn destroyPopups(toplevel: XdgToplevel) void { pub fn destroyPopups(toplevel: XdgToplevel) void {
var it = toplevel.wlr_toplevel.base.popups.safeIterator(.forward); var it = toplevel.wlr_toplevel.base.popups.safeIterator(.forward);
while (it.next()) |wlr_xdg_popup| wlr_xdg_popup.destroy(); while (it.next()) |wlr_xdg_popup| wlr_xdg_popup.destroy();

View File

@ -119,15 +119,6 @@ pub fn configure(xwayland_view: XwaylandView) bool {
return false; return false;
} }
pub fn rootSurface(xwayland_view: XwaylandView) *wlr.Surface {
return xwayland_view.xwayland_surface.surface.?;
}
/// Close the view. This will lead to the unmap and destroy events being sent
pub fn close(xwayland_view: XwaylandView) void {
xwayland_view.xwayland_surface.close();
}
fn setActivated(xwayland_view: XwaylandView, activated: bool) void { fn setActivated(xwayland_view: XwaylandView, activated: bool) void {
// See comment on handleRequestMinimize() for details // See comment on handleRequestMinimize() for details
if (activated and xwayland_view.xwayland_surface.minimized) { if (activated and xwayland_view.xwayland_surface.minimized) {
@ -139,16 +130,6 @@ fn setActivated(xwayland_view: XwaylandView, activated: bool) void {
} }
} }
/// Get the current title of the xwayland surface if any.
pub fn getTitle(xwayland_view: XwaylandView) ?[*:0]const u8 {
return xwayland_view.xwayland_surface.title;
}
/// X11 clients don't have an app_id but the class serves a similar role.
/// Get the current class of the xwayland surface if any.
pub fn getAppId(xwayland_view: XwaylandView) ?[*:0]const u8 {
return xwayland_view.xwayland_surface.class;
}
fn handleDestroy(listener: *wl.Listener(void)) void { fn handleDestroy(listener: *wl.Listener(void)) void {
const xwayland_view = @fieldParentPtr(XwaylandView, "destroy", listener); const xwayland_view = @fieldParentPtr(XwaylandView, "destroy", listener);