gtk: find first surface to focus on if sibling is Paned

This commit is contained in:
Thorsten Ball
2023-11-01 06:56:16 +01:00
committed by Mitchell Hashimoto
parent f1e81563d9
commit b1e3685664
3 changed files with 35 additions and 17 deletions

View File

@ -82,12 +82,22 @@ pub fn setParent(self: *Paned, parent: Parent) void {
self.parent = parent; self.parent = parent;
} }
/// Focus on the Surface's gl_area in the given position. /// Focus on first Surface that can be found in given position. If there's a
pub fn focusSurfaceInPosition(self: *Paned, position: Position) void { /// Paned in the position, it will focus on the first surface in that position.
const surface: *Surface = self.surfaceInPosition(position) orelse return; pub fn focusFirstSurfaceInPosition(self: *Paned, position: Position) void {
const widget = @as(*c.GtkWidget, @ptrCast(surface.gl_area)); const child = self.childInPosition(position);
surface.tab.focus_child = surface; switch (child) {
_ = c.gtk_widget_grab_focus(widget); .surface => |s| {
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),
.none => {
log.warn("attempted to focus on first surface, found none", .{});
return;
},
}
} }
/// Split the Surface in the given position into a Paned with two surfaces. /// Split the Surface in the given position into a Paned with two surfaces.
@ -116,7 +126,7 @@ pub fn splitSurfaceInPosition(self: *Paned, position: Position, direction: input
c.gtk_paned_set_position(self.paned, parent_paned_position_before); c.gtk_paned_set_position(self.paned, parent_paned_position_before);
// Focus on new surface // Focus on new surface
paned.focusSurfaceInPosition(.end); paned.focusFirstSurfaceInPosition(.end);
} }
/// Replace the existing .start or .end Child with the given new Child. /// Replace the existing .start or .end Child with the given new Child.
@ -125,7 +135,7 @@ pub fn replaceChildInPosition(self: *Paned, child: Child, position: Position) vo
const parent_paned_position_before = c.gtk_paned_get_position(self.paned); const parent_paned_position_before = c.gtk_paned_get_position(self.paned);
// Focus on the sibling, otherwise we'll get a GTK warning // Focus on the sibling, otherwise we'll get a GTK warning
self.focusSurfaceInPosition(if (position == .start) .end else .start); self.focusFirstSurfaceInPosition(if (position == .start) .end else .start);
// Now we can remove the other one // Now we can remove the other one
self.removeChildInPosition(position); self.removeChildInPosition(position);
@ -193,13 +203,15 @@ fn addChild2(self: *Paned, child: Child) void {
child.setParent(.{ .paned = .{ self, .end } }); child.setParent(.{ .paned = .{ self, .end } });
} }
fn surfaceInPosition(self: *Paned, position: Position) ?*Surface { fn childInPosition(self: *Paned, position: Position) Child {
const child = switch (position) { return switch (position) {
.start => self.child1, .start => self.child1,
.end => self.child2, .end => self.child2,
}; };
}
return switch (child) { fn surfaceInPosition(self: *Paned, position: Position) ?*Surface {
return switch (self.childInPosition(position)) {
.surface => |surface| surface, .surface => |surface| surface,
else => null, else => null,
}; };

View File

@ -188,7 +188,7 @@ pub fn splitSurface(self: *Tab, direction: input.SplitDirection) !void {
self.setChild(.{ .paned = paned }); self.setChild(.{ .paned = paned });
// Focus on new surface // Focus on new surface
paned.focusSurfaceInPosition(.end); paned.focusFirstSurfaceInPosition(.end);
} }
/// Remove the current child from the Tab. Noop if no child set. /// Remove the current child from the Tab. Noop if no child set.

View File

@ -283,8 +283,8 @@ fn closeSurfaceInPaned(self: *Window, surface: *Surface, paned: *Paned, position
const sibling_child = sibling[0]; const sibling_child = sibling[0];
const sibling_widget = sibling[1]; const sibling_widget = sibling[1];
// Keep explicit reference to sibling's gl_area, so it's not // Keep explicit reference to sibling's widget (gl_area, or Paned), so it's
// destroyed when we remove it from GtkPaned. // not destroyed when we remove it from GtkPaned.
const sibling_object: *c.GObject = @ptrCast(sibling_widget); const sibling_object: *c.GObject = @ptrCast(sibling_widget);
_ = c.g_object_ref(sibling_object); _ = c.g_object_ref(sibling_object);
defer c.g_object_unref(sibling_object); defer c.g_object_unref(sibling_object);
@ -314,11 +314,17 @@ fn closeSurfaceInPaned(self: *Window, surface: *Surface, paned: *Paned, position
} }
switch (sibling_child) { switch (sibling_child) {
.surface => |s| s.tab.focus_child = s, .surface => |s| {
s.tab.focus_child = s;
const widget = @as(*c.GtkWidget, @ptrCast(s.gl_area));
_ = c.gtk_widget_grab_focus(widget);
},
.paned => |p| {
// Focus on first surface in sibling Paned
p.focusFirstSurfaceInPosition(position);
},
else => {}, else => {},
} }
const widget = @as(*c.GtkWidget, @ptrCast(sibling_widget));
_ = c.gtk_widget_grab_focus(widget);
} }
/// Returns true if this window has any tabs. /// Returns true if this window has any tabs.