mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
apprt/gtk: stylistic changes
This commit is contained in:
@ -360,10 +360,7 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
|
|||||||
errdefer self.* = undefined;
|
errdefer self.* = undefined;
|
||||||
|
|
||||||
// Set up Xkb if we are running under X11.
|
// Set up Xkb if we are running under X11.
|
||||||
const display = c.gdk_display_get_default();
|
self.x11_xkb = try x11.X11Xkb.init(c.gdk_display_get_default());
|
||||||
if (x11.x11_is_display(display)) {
|
|
||||||
self.x11_xkb = try x11.X11Xkb.init(display);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set our default mouse shape
|
// Set our default mouse shape
|
||||||
try self.setMouseShape(.text);
|
try self.setMouseShape(.text);
|
||||||
@ -1345,18 +1342,21 @@ fn keyEvent(
|
|||||||
_ = gtk_mods;
|
_ = gtk_mods;
|
||||||
|
|
||||||
const device = c.gdk_event_get_device(event);
|
const device = c.gdk_event_get_device(event);
|
||||||
var mods = if (self.x11_xkb) |x11_xkb| init_mods: {
|
var mods = init_mods: {
|
||||||
// Add any modifier state events from Xkb if we have them (X11 only).
|
if (self.x11_xkb) |x11_xkb| {
|
||||||
if (x11_xkb.modifier_state_from_notify(display)) |xkb_mods| {
|
// Add any modifier state events from Xkb if we have them (X11 only).
|
||||||
break :init_mods xkb_mods;
|
if (x11_xkb.modifier_state_from_notify(display)) |xkb_mods| {
|
||||||
} else {
|
break :init_mods xkb_mods;
|
||||||
|
}
|
||||||
|
|
||||||
// Null back from the Xkb call means there was no modifier
|
// Null back from the Xkb call means there was no modifier
|
||||||
// event to read. This likely means that the key event did not
|
// event to read. This likely means that the key event did not
|
||||||
// result in a modifier change and we can safely rely on the
|
// result in a modifier change and we can safely rely on the
|
||||||
// GDK state.
|
// GDK state.
|
||||||
break :init_mods translateMods(c.gdk_device_get_modifier_state(device));
|
|
||||||
}
|
}
|
||||||
} else translateMods(c.gdk_device_get_modifier_state(device));
|
|
||||||
|
break :init_mods translateMods(c.gdk_device_get_modifier_state(device));
|
||||||
|
};
|
||||||
|
|
||||||
mods.num_lock = c.gdk_device_get_num_lock_state(device) == 1;
|
mods.num_lock = c.gdk_device_get_num_lock_state(device) == 1;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ const std = @import("std");
|
|||||||
const c = @import("c.zig");
|
const c = @import("c.zig");
|
||||||
const input = @import("../../input.zig");
|
const input = @import("../../input.zig");
|
||||||
|
|
||||||
const log = std.log.scoped(.gtk);
|
const log = std.log.scoped(.gtk_x11);
|
||||||
|
|
||||||
// X11 Function types. We load these dynamically at runtime to avoid having to
|
// X11 Function types. We load these dynamically at runtime to avoid having to
|
||||||
// link against X11.
|
// link against X11.
|
||||||
@ -13,9 +13,11 @@ const XEventsQueuedType = *const fn (?*c.struct__XDisplay, c_int) callconv(.C) c
|
|||||||
const XPeekEventType = *const fn (?*c.struct__XDisplay, [*c]c.union__XEvent) callconv(.C) c_int;
|
const XPeekEventType = *const fn (?*c.struct__XDisplay, [*c]c.union__XEvent) callconv(.C) c_int;
|
||||||
|
|
||||||
/// Returns true if the passed in display is an X11 display.
|
/// Returns true if the passed in display is an X11 display.
|
||||||
pub fn x11_is_display(display_: ?*c.GdkDisplay) bool {
|
pub fn x11_is_display(display: ?*c.GdkDisplay) bool {
|
||||||
const display = display_ orelse return false;
|
return c.g_type_check_instance_is_a(
|
||||||
return (c.g_type_check_instance_is_a(@ptrCast(@alignCast(display)), c.gdk_x11_display_get_type()) != 0);
|
@ptrCast(@alignCast(display orelse return false)),
|
||||||
|
c.gdk_x11_display_get_type(),
|
||||||
|
) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const X11Xkb = struct {
|
pub const X11Xkb = struct {
|
||||||
@ -29,47 +31,79 @@ pub const X11Xkb = struct {
|
|||||||
XEventsQueued: XEventsQueuedType = undefined,
|
XEventsQueued: XEventsQueuedType = undefined,
|
||||||
XPeekEvent: XPeekEventType = undefined,
|
XPeekEvent: XPeekEventType = undefined,
|
||||||
|
|
||||||
pub fn init(display_: ?*c.GdkDisplay) !X11Xkb {
|
/// Initialize an X11Xkb struct, for the given GDK display. If the display
|
||||||
log.debug("X11: X11Xkb.init: initializing Xkb", .{});
|
/// isn't backed by X then this will return null.
|
||||||
const display = display_ orelse {
|
pub fn init(display_: ?*c.GdkDisplay) !?X11Xkb {
|
||||||
log.err("Fatal: error initializing Xkb extension: display is null", .{});
|
// Display should never be null but we just treat that as a non-X11
|
||||||
return error.XkbInitializationError;
|
// display so that the caller can just ignore it and not unwrap it.
|
||||||
};
|
const display = display_ orelse return null;
|
||||||
|
|
||||||
|
// If the display isn't X11, then we don't need to do anything.
|
||||||
|
if (!x11_is_display(display)) return null;
|
||||||
|
|
||||||
|
log.debug("X11Xkb.init: initializing Xkb", .{});
|
||||||
const xdisplay = c.gdk_x11_display_get_xdisplay(display);
|
const xdisplay = c.gdk_x11_display_get_xdisplay(display);
|
||||||
var result: X11Xkb = .{ .opcode = 0, .base_event_code = 0, .base_error_code = 0 };
|
var result: X11Xkb = .{ .opcode = 0, .base_event_code = 0, .base_error_code = 0 };
|
||||||
|
|
||||||
// Load in the X11 calls we need.
|
// Load in the X11 calls we need.
|
||||||
log.debug("X11: X11Xkb.init: loading libX11.so dynamically", .{});
|
log.debug(" X11Xkb.init: loading libX11.so dynamically", .{});
|
||||||
var libX11 = try std.DynLib.open("libX11.so");
|
var libX11 = try std.DynLib.open("libX11.so");
|
||||||
defer libX11.close();
|
defer libX11.close();
|
||||||
result.XkbQueryExtension = libX11.lookup(XkbQueryExtensionType, "XkbQueryExtension") orelse {
|
result.XkbQueryExtension = libX11.lookup(
|
||||||
|
XkbQueryExtensionType,
|
||||||
|
"XkbQueryExtension",
|
||||||
|
) orelse {
|
||||||
log.err("Fatal: error dynamic loading libX11: missing symbol XkbQueryExtension", .{});
|
log.err("Fatal: error dynamic loading libX11: missing symbol XkbQueryExtension", .{});
|
||||||
return error.XkbInitializationError;
|
return error.XkbInitializationError;
|
||||||
};
|
};
|
||||||
result.XkbSelectEventDetails = libX11.lookup(XkbSelectEventDetailsType, "XkbSelectEventDetails") orelse {
|
|
||||||
|
result.XkbSelectEventDetails = libX11.lookup(
|
||||||
|
XkbSelectEventDetailsType,
|
||||||
|
"XkbSelectEventDetails",
|
||||||
|
) orelse {
|
||||||
log.err("Fatal: error dynamic loading libX11: missing symbol XkbSelectEventDetails", .{});
|
log.err("Fatal: error dynamic loading libX11: missing symbol XkbSelectEventDetails", .{});
|
||||||
return error.XkbInitializationError;
|
return error.XkbInitializationError;
|
||||||
};
|
};
|
||||||
result.XEventsQueued = libX11.lookup(XEventsQueuedType, "XEventsQueued") orelse {
|
|
||||||
|
result.XEventsQueued = libX11.lookup(
|
||||||
|
XEventsQueuedType,
|
||||||
|
"XEventsQueued",
|
||||||
|
) orelse {
|
||||||
log.err("Fatal: error dynamic loading libX11: missing symbol XEventsQueued", .{});
|
log.err("Fatal: error dynamic loading libX11: missing symbol XEventsQueued", .{});
|
||||||
return error.XkbInitializationError;
|
return error.XkbInitializationError;
|
||||||
};
|
};
|
||||||
result.XPeekEvent = libX11.lookup(XPeekEventType, "XPeekEvent") orelse {
|
|
||||||
|
result.XPeekEvent = libX11.lookup(
|
||||||
|
XPeekEventType,
|
||||||
|
"XPeekEvent",
|
||||||
|
) orelse {
|
||||||
log.err("Fatal: error dynamic loading libX11: missing symbol XPeekEvent", .{});
|
log.err("Fatal: error dynamic loading libX11: missing symbol XPeekEvent", .{});
|
||||||
return error.XkbInitializationError;
|
return error.XkbInitializationError;
|
||||||
};
|
};
|
||||||
|
|
||||||
log.debug("X11: X11Xkb.init: running XkbQueryExtension", .{});
|
log.debug("X11Xkb.init: running XkbQueryExtension", .{});
|
||||||
var major = c.XkbMajorVersion;
|
var major = c.XkbMajorVersion;
|
||||||
var minor = c.XkbMinorVersion;
|
var minor = c.XkbMinorVersion;
|
||||||
if (result.XkbQueryExtension(xdisplay, &result.opcode, &result.base_event_code, &result.base_error_code, &major, &minor) == 0) {
|
if (result.XkbQueryExtension(
|
||||||
|
xdisplay,
|
||||||
|
&result.opcode,
|
||||||
|
&result.base_event_code,
|
||||||
|
&result.base_error_code,
|
||||||
|
&major,
|
||||||
|
&minor,
|
||||||
|
) == 0) {
|
||||||
log.err("Fatal: error initializing Xkb extension: error executing XkbQueryExtension", .{});
|
log.err("Fatal: error initializing Xkb extension: error executing XkbQueryExtension", .{});
|
||||||
return error.XkbInitializationError;
|
return error.XkbInitializationError;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("X11: X11Xkb.init: running XkbSelectEventDetails", .{});
|
log.debug("X11Xkb.init: running XkbSelectEventDetails", .{});
|
||||||
if (result.XkbSelectEventDetails(xdisplay, c.XkbUseCoreKbd, c.XkbStateNotify, c.XkbModifierStateMask, c.XkbModifierStateMask) == 0) {
|
if (result.XkbSelectEventDetails(
|
||||||
|
xdisplay,
|
||||||
|
c.XkbUseCoreKbd,
|
||||||
|
c.XkbStateNotify,
|
||||||
|
c.XkbModifierStateMask,
|
||||||
|
c.XkbModifierStateMask,
|
||||||
|
) == 0) {
|
||||||
log.err("Fatal: error initializing Xkb extension: error executing XkbSelectEventDetails", .{});
|
log.err("Fatal: error initializing Xkb extension: error executing XkbSelectEventDetails", .{});
|
||||||
return error.XkbInitializationError;
|
return error.XkbInitializationError;
|
||||||
}
|
}
|
||||||
@ -89,32 +123,31 @@ pub const X11Xkb = struct {
|
|||||||
/// event did not result in a modifier change).
|
/// event did not result in a modifier change).
|
||||||
pub fn modifier_state_from_notify(self: X11Xkb, display_: ?*c.GdkDisplay) ?input.Mods {
|
pub fn modifier_state_from_notify(self: X11Xkb, display_: ?*c.GdkDisplay) ?input.Mods {
|
||||||
const display = display_ orelse return null;
|
const display = display_ orelse return null;
|
||||||
|
|
||||||
// Shoutout to Mozilla for figuring out a clean way to do this, this is
|
// Shoutout to Mozilla for figuring out a clean way to do this, this is
|
||||||
// paraphrased from Firefox/Gecko in widget/gtk/nsGtkKeyUtils.cpp.
|
// paraphrased from Firefox/Gecko in widget/gtk/nsGtkKeyUtils.cpp.
|
||||||
const xdisplay = c.gdk_x11_display_get_xdisplay(display);
|
const xdisplay = c.gdk_x11_display_get_xdisplay(display);
|
||||||
if (self.XEventsQueued(xdisplay, c.QueuedAfterReading) != 0) {
|
if (self.XEventsQueued(xdisplay, c.QueuedAfterReading) == 0) return null;
|
||||||
var nextEvent: c.XEvent = undefined;
|
|
||||||
_ = self.XPeekEvent(xdisplay, &nextEvent);
|
|
||||||
if (nextEvent.type == self.base_event_code) {
|
|
||||||
const xkb_event: *c.XkbEvent = @ptrCast(&nextEvent);
|
|
||||||
if (xkb_event.any.xkb_type == c.XkbStateNotify) {
|
|
||||||
const xkb_state_notify_event: *c.XkbStateNotifyEvent = @ptrCast(xkb_event);
|
|
||||||
// Check the state according to XKB masks.
|
|
||||||
const lookup_mods = xkb_state_notify_event.lookup_mods;
|
|
||||||
var mods: input.Mods = .{};
|
|
||||||
|
|
||||||
log.debug("X11: found extra XkbStateNotify event w/lookup_mods: {b}", .{lookup_mods});
|
var nextEvent: c.XEvent = undefined;
|
||||||
if (lookup_mods & c.ShiftMask != 0) mods.shift = true;
|
_ = self.XPeekEvent(xdisplay, &nextEvent);
|
||||||
if (lookup_mods & c.ControlMask != 0) mods.ctrl = true;
|
if (nextEvent.type != self.base_event_code) return null;
|
||||||
if (lookup_mods & c.Mod1Mask != 0) mods.alt = true;
|
|
||||||
if (lookup_mods & c.Mod2Mask != 0) mods.super = true;
|
|
||||||
if (lookup_mods & c.LockMask != 0) mods.caps_lock = true;
|
|
||||||
|
|
||||||
return mods;
|
const xkb_event: *c.XkbEvent = @ptrCast(&nextEvent);
|
||||||
}
|
if (xkb_event.any.xkb_type != c.XkbStateNotify) return null;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
const xkb_state_notify_event: *c.XkbStateNotifyEvent = @ptrCast(xkb_event);
|
||||||
|
// Check the state according to XKB masks.
|
||||||
|
const lookup_mods = xkb_state_notify_event.lookup_mods;
|
||||||
|
var mods: input.Mods = .{};
|
||||||
|
|
||||||
|
log.debug("X11: found extra XkbStateNotify event w/lookup_mods: {b}", .{lookup_mods});
|
||||||
|
if (lookup_mods & c.ShiftMask != 0) mods.shift = true;
|
||||||
|
if (lookup_mods & c.ControlMask != 0) mods.ctrl = true;
|
||||||
|
if (lookup_mods & c.Mod1Mask != 0) mods.alt = true;
|
||||||
|
if (lookup_mods & c.Mod2Mask != 0) mods.super = true;
|
||||||
|
if (lookup_mods & c.LockMask != 0) mods.caps_lock = true;
|
||||||
|
|
||||||
|
return mods;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user