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,78 +116,52 @@ 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,
if (registryBind( else => continue,
org.KdeKwinBlurManager,
registry,
global,
)) |blur_manager| {
context.kde_blur_manager = blur_manager;
return;
}
if (registryBind(
org.KdeKwinServerDecorationManager,
registry,
global,
)) |deco_manager| {
context.kde_decoration_manager = deco_manager;
deco_manager.setListener(*Context, decoManagerListener, context);
return;
}
if (registryBind(
org.KdeKwinSlideManager,
registry,
global,
)) |slide_manager| {
context.kde_slide_manager = slide_manager;
return;
}
if (registryBind(
xdg.ActivationV1,
registry,
global,
)) |activation| {
context.xdg_activation = activation;
return;
}
}, },
else => continue,
};
// We don't handle removal events // Only process Wayland interfaces
.global_remove => {}, if (!@hasDecl(T, "interface")) continue;
}
}
/// Bind a Wayland interface to a global object. Returns non-null switch (event) {
/// if the binding was successful, otherwise null. .global => |v| global: {
///
/// 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( if (std.mem.orderZ(
u8, u8,
global.interface, v.interface,
T.interface.name, T.interface.name,
) != .eq) return null; ) != .eq) break :global;
return registry.bind(global.name, T, T.generated_version) catch |err| { @field(context, field.name) = registry.bind(
log.warn("error binding interface {s} error={}", .{ v.name,
global.interface, T,
err, T.generated_version,
}); ) catch |err| {
return null; log.warn(
"error binding interface {s} error={}",
.{ v.interface, err },
);
return;
}; };
},
// 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;
}
},
}
}
} }
fn decoManagerListener( fn decoManagerListener(

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|