gtk(wayland,x11): refactors (#7485)

This commit is contained in:
Leah Amelia Chen
2025-05-31 08:17:11 +02:00
committed by GitHub
2 changed files with 47 additions and 83 deletions

View File

@ -48,16 +48,11 @@ pub const App = struct {
_ = config;
_ = app_id;
// Check if we're actually on Wayland
if (gobject.typeCheckInstanceIsA(
gdk_display.as(gobject.TypeInstance),
gdk_wayland.WaylandDisplay.getGObjectType(),
) == 0) return null;
const gdk_wayland_display = gobject.ext.cast(
gdk_wayland.WaylandDisplay,
gdk_display,
) orelse return error.NoWaylandDisplay;
) orelse return null;
const display: *wl.Display = @ptrCast(@alignCast(
gdk_wayland_display.getWlDisplay() orelse return error.NoWaylandDisplay,
));
@ -76,9 +71,9 @@ pub const App = struct {
registry.setListener(*Context, registryListener, context);
if (display.roundtrip() != .SUCCESS) return error.RoundtripFailed;
if (context.kde_decoration_manager != null) {
// FIXME: Roundtrip again because we have to wait for the decoration
// manager to respond with the preferred default mode. Ew.
// Do another round-trip to get the default decoration mode
if (context.kde_decoration_manager) |deco_manager| {
deco_manager.setListener(*Context, decoManagerListener, context);
if (display.roundtrip() != .SUCCESS) return error.RoundtripFailed;
}
@ -121,80 +116,54 @@ pub const App = struct {
event: wl.Registry.Event,
context: *Context,
) void {
switch (event) {
// https://wayland.app/protocols/wayland#wl_registry:event:global
.global => |global| {
log.debug("wl_registry.global: interface={s}", .{global.interface});
inline for (@typeInfo(Context).@"struct".fields) |field| {
// Globals should be optional pointers
const T = switch (@typeInfo(field.type)) {
.optional => |o| switch (@typeInfo(o.child)) {
.pointer => |v| v.child,
else => continue,
},
else => continue,
};
if (registryBind(
org.KdeKwinBlurManager,
registry,
global,
)) |blur_manager| {
context.kde_blur_manager = blur_manager;
return;
}
// Only process Wayland interfaces
if (!@hasDecl(T, "interface")) continue;
if (registryBind(
org.KdeKwinServerDecorationManager,
registry,
global,
)) |deco_manager| {
context.kde_decoration_manager = deco_manager;
deco_manager.setListener(*Context, decoManagerListener, context);
return;
}
switch (event) {
.global => |v| global: {
if (std.mem.orderZ(
u8,
v.interface,
T.interface.name,
) != .eq) break :global;
if (registryBind(
org.KdeKwinSlideManager,
registry,
global,
)) |slide_manager| {
context.kde_slide_manager = slide_manager;
return;
}
@field(context, field.name) = registry.bind(
v.name,
T,
T.generated_version,
) catch |err| {
log.warn(
"error binding interface {s} error={}",
.{ v.interface, err },
);
return;
};
},
if (registryBind(
xdg.ActivationV1,
registry,
global,
)) |activation| {
context.xdg_activation = activation;
return;
}
},
// We don't handle removal events
.global_remove => {},
// This should be a rare occurrence, but in case a global
// is suddenly no longer available, we destroy and unset it
// as the protocol mandates.
.global_remove => |v| remove: {
const global = @field(context, field.name) orelse break :remove;
if (global.getId() == v.name) {
global.destroy();
@field(context, field.name) = null;
}
},
}
}
}
/// Bind a Wayland interface to a global object. Returns non-null
/// if the binding was successful, otherwise null.
///
/// The type T is the Wayland interface type that we're requesting.
/// This function will verify that the global object is the correct
/// interface and version before binding.
fn registryBind(
comptime T: type,
registry: *wl.Registry,
global: anytype,
) ?*T {
if (std.mem.orderZ(
u8,
global.interface,
T.interface.name,
) != .eq) return null;
return registry.bind(global.name, T, T.generated_version) catch |err| {
log.warn("error binding interface {s} error={}", .{
global.interface,
err,
});
return null;
};
}
fn decoManagerListener(
_: *org.KdeKwinServerDecorationManager,
event: org.KdeKwinServerDecorationManager.Event,

View File

@ -36,16 +36,11 @@ pub const App = struct {
config: *const Config,
) !?App {
// If the display isn't X11, then we don't need to do anything.
if (gobject.typeCheckInstanceIsA(
gdk_display.as(gobject.TypeInstance),
gdk_x11.X11Display.getGObjectType(),
) == 0) return null;
// Get our X11 display
const gdk_x11_display = gobject.ext.cast(
gdk_x11.X11Display,
gdk_display,
) orelse return null;
const xlib_display = gdk_x11_display.getXdisplay();
const x11_program_name: [:0]const u8 = if (config.@"x11-instance-name") |pn|