gtk: keep buffer of surface title, update if focused

This commit is contained in:
Thorsten Ball
2023-11-01 07:52:24 +01:00
committed by Mitchell Hashimoto
parent b1e3685664
commit b60133fd34
4 changed files with 38 additions and 24 deletions

View File

@ -87,11 +87,7 @@ pub fn setParent(self: *Paned, parent: Parent) void {
pub fn focusFirstSurfaceInPosition(self: *Paned, position: Position) void { pub fn focusFirstSurfaceInPosition(self: *Paned, position: Position) void {
const child = self.childInPosition(position); const child = self.childInPosition(position);
switch (child) { switch (child) {
.surface => |s| { .surface => |s| s.grabFocus(),
const widget = @as(*c.GtkWidget, @ptrCast(s.gl_area));
s.tab.focus_child = s;
_ = c.gtk_widget_grab_focus(widget);
},
.paned => |p| p.focusFirstSurfaceInPosition(position), .paned => |p| p.focusFirstSurfaceInPosition(position),
.none => { .none => {
log.warn("attempted to focus on first surface, found none", .{}); log.warn("attempted to focus on first surface, found none", .{});

View File

@ -90,6 +90,11 @@ cursor: ?*c.GdkCursor = null,
/// Our title label (if there is one). /// Our title label (if there is one).
title: Title, title: Title,
/// Our title. The raw value of the title. This will be kept up to date and
/// .title will be updated if we have focus.
/// TODO: what's a big enough value?
titleText: [4096]u8,
/// The core surface backing this surface /// The core surface backing this surface
core_surface: CoreSurface, core_surface: CoreSurface,
@ -175,6 +180,7 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
.title = if (opts.title_label) |label| .{ .title = if (opts.title_label) |label| .{
.label = label, .label = label,
} else .{ .none = {} }, } else .{ .none = {} },
.titleText = undefined,
.core_surface = undefined, .core_surface = undefined,
.font_size = opts.font_size, .font_size = opts.font_size,
.parentSurface = opts.parentSurface, .parentSurface = opts.parentSurface,
@ -445,24 +451,38 @@ pub fn setSizeLimits(self: *Surface, min: apprt.SurfaceSize, max_: ?apprt.Surfac
_ = max_; _ = max_;
} }
pub fn setTitle(self: *Surface, slice: [:0]const u8) !void { pub fn grabFocus(self: *Surface) void {
self.updateTitleLabels();
self.tab.focus_child = self;
const widget = @as(*c.GtkWidget, @ptrCast(self.gl_area));
_ = c.gtk_widget_grab_focus(widget);
}
fn updateTitleLabels(self: *Surface) void {
switch (self.title) { switch (self.title) {
.none => {}, .none => {},
.label => |label| { .label => |label| {
c.gtk_label_set_text(label, slice.ptr); const slice: []u8 = std.mem.sliceTo(&self.titleText, 0);
// Check whether there's even something in the buffer yet.
const widget = @as(*c.GtkWidget, @ptrCast(self.gl_area)); // TODO: This check is really bad.
if (c.gtk_widget_is_focus(widget) == 1) { if (slice.len != self.titleText.len) {
c.gtk_label_set_text(label, @as([*c]const u8, @ptrCast(slice)));
c.gtk_window_set_title(self.window.window, c.gtk_label_get_text(label)); c.gtk_window_set_title(self.window.window, c.gtk_label_get_text(label));
} }
}, },
} }
}
// const root = c.gtk_widget_get_root(@ptrCast( pub fn setTitle(self: *Surface, slice: [:0]const u8) !void {
// *c.GtkWidget, // TODO: I'm sure there has to be a better way than this in Zig.
// self.gl_area, const len = @min(self.titleText.len - 1, slice.len);
// )); @memcpy(self.titleText[0..len], slice[0..]);
self.titleText[len] = 0;
const widget = @as(*c.GtkWidget, @ptrCast(self.gl_area));
if (c.gtk_widget_is_focus(widget) == 1) {
self.updateTitleLabels();
}
} }
pub fn setParent(self: *Surface, parent: Parent) void { pub fn setParent(self: *Surface, parent: Parent) void {
@ -838,6 +858,10 @@ fn gtkMouseDown(
if (c.gtk_widget_has_focus(gl_widget) == 0) { if (c.gtk_widget_has_focus(gl_widget) == 0) {
self.tab.focus_child = self; self.tab.focus_child = self;
_ = c.gtk_widget_grab_focus(gl_widget); _ = c.gtk_widget_grab_focus(gl_widget);
// If we have siblings, we also update the title, since it means
// another sibling might have updated the title.
if (self.parent != Parent.tab) self.updateTitleLabels();
} }
self.core_surface.mouseButtonCallback(.press, button, mods) catch |err| { self.core_surface.mouseButtonCallback(.press, button, mods) catch |err| {
@ -1267,6 +1291,7 @@ fn gtkInputCommit(
fn gtkFocusEnter(_: *c.GtkEventControllerFocus, ud: ?*anyopaque) callconv(.C) void { fn gtkFocusEnter(_: *c.GtkEventControllerFocus, ud: ?*anyopaque) callconv(.C) void {
const self = userdataSelf(ud.?); const self = userdataSelf(ud.?);
// Notify our IM context // Notify our IM context
c.gtk_im_context_focus_in(self.im_context); c.gtk_im_context_focus_in(self.im_context);

View File

@ -120,9 +120,6 @@ pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void {
c.gtk_notebook_set_show_tabs(window.notebook, 1); c.gtk_notebook_set_show_tabs(window.notebook, 1);
} }
// TODO: This needs to happen before we show the page
self.focus_child = surface;
// Set the userdata of the box to point to this tab. // Set the userdata of the box to point to this tab.
c.g_object_set_data(@ptrCast(box_widget), GHOSTTY_TAB, self); c.g_object_set_data(@ptrCast(box_widget), GHOSTTY_TAB, self);
@ -131,7 +128,7 @@ pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void {
// We need to grab focus after Surface and Tab is added to the window. When // We need to grab focus after Surface and Tab is added to the window. When
// creating a Tab we want to always focus on the widget. // creating a Tab we want to always focus on the widget.
_ = c.gtk_widget_grab_focus(gl_area_widget); surface.grabFocus();
} }
/// Allocates and initializes a new Surface, but doesn't add it to the Tab yet. /// Allocates and initializes a new Surface, but doesn't add it to the Tab yet.

View File

@ -314,11 +314,7 @@ fn closeSurfaceInPaned(self: *Window, surface: *Surface, paned: *Paned, position
} }
switch (sibling_child) { switch (sibling_child) {
.surface => |s| { .surface => |s| s.grabFocus(),
s.tab.focus_child = s;
const widget = @as(*c.GtkWidget, @ptrCast(s.gl_area));
_ = c.gtk_widget_grab_focus(widget);
},
.paned => |p| { .paned => |p| {
// Focus on first surface in sibling Paned // Focus on first surface in sibling Paned
p.focusFirstSurfaceInPosition(position); p.focusFirstSurfaceInPosition(position);