mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 16:26:08 +03:00
gtk: keep buffer of surface title, update if focused
This commit is contained in:

committed by
Mitchell Hashimoto

parent
b1e3685664
commit
b60133fd34
@ -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", .{});
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user