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

View File

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