core,gtk: add drag-handle config (#13706)

Fixes hundreds of complaints about the fact that drag handles cannot be
hidden, on GTK at least.

I'm not sure if we ever made an issue for this? If you come across any
discussions asking for this, please link them here :)
This commit is contained in:
Leah Amelia Chen
2026-08-09 20:10:38 +08:00
committed by GitHub
4 changed files with 65 additions and 7 deletions

View File

@@ -239,12 +239,7 @@ pub const SplitTree = extern struct {
}
// Bind is-split property for new surface
_ = self.as(gobject.Object).bindProperty(
"is-split",
surface.as(gobject.Object),
"is-split",
.{ .sync_create = true },
);
surface.bindIsSplit(self);
// Create our tree
var single_tree = try Surface.Tree.init(alloc, surface);
@@ -452,6 +447,9 @@ pub const SplitTree = extern struct {
// Finally, set the final tree structures for both tree widgets
source_tree_widget.setTree(&new_source_tree);
self.setTree(&after_split);
// Re-bind vital properties like `is-split`
source.bindIsSplit(self);
}
}

View File

@@ -691,6 +691,7 @@ pub const Surface = extern struct {
// True if the current surface is a split, this is used to apply
// unfocused-split-* options
is_split: bool = false,
is_split_binding: ?*gobject.Binding = null,
action_group: ?*gio.SimpleActionGroup = null,
@@ -847,6 +848,18 @@ pub const Surface = extern struct {
return @intFromBool(config.@"bell-features".border);
}
pub fn bindIsSplit(self: *Self, tree: *SplitTree) void {
const priv = self.private();
if (priv.is_split_binding) |bind| bind.unbind();
priv.is_split_binding = tree.as(gobject.Object).bindProperty(
"is-split",
self.as(gobject.Object),
"is-split",
.{ .sync_create = true },
);
}
/// Callback used to determine whether unfocused-split-fill / unfocused-split-opacity
/// should be applied to the surface
fn closureShouldUnfocusedSplitBeShown(
@@ -3650,6 +3663,21 @@ pub const Surface = extern struct {
};
}
fn closureShouldDragHandleBeShown(
_: *Self,
config_: ?*Config,
is_split: c_int,
) callconv(.c) c_int {
const config = config_ orelse return @intFromBool(false);
const shown = switch (config.get().@"drag-handle") {
.always => true,
.auto => is_split != 0,
.never => false,
};
return @intFromBool(shown);
}
fn surfaceDragPrepare(
src: *gtk.DragSource,
x: f64,
@@ -3722,7 +3750,6 @@ pub const Surface = extern struct {
const dropped = self.core().?.app.findSurfaceByID(dropped_id) orelse return;
const from = dropped.rt_surface.gobj();
// TODO: Find a better way to access the split tree from here
const st = ext.getAncestor(
SplitTree,
self.as(gtk.Widget),
@@ -3892,6 +3919,7 @@ pub const Surface = extern struct {
class.bindTemplateCallback("search_changed", &searchChanged);
class.bindTemplateCallback("search_next_match", &searchNextMatch);
class.bindTemplateCallback("search_previous_match", &searchPreviousMatch);
class.bindTemplateCallback("should_drag_handle_be_shown", &closureShouldDragHandleBeShown);
class.bindTemplateCallback("surface_drag_prepare", &surfaceDragPrepare);
class.bindTemplateCallback("surface_drag_begin", &surfaceDragBegin);
class.bindTemplateCallback("surface_drop", &surfaceDrop);

View File

@@ -232,6 +232,7 @@ Overlay terminal_page {
CenterBox drag_handle {
halign: fill;
valign: start;
visible: bind $should_drag_handle_be_shown(template.config, template.is-split) as <bool>;
styles [
"drag-handle",

View File

@@ -2345,6 +2345,30 @@ keybind: Keybinds = .{},
/// Specified as either hex (`#RRGGBB` or `RRGGBB`) or a named X11 color.
@"window-titlebar-foreground": ?Color = null,
/// Controls when drag handles are shown over splits,
/// allowing splits to be rearranged with mouse controls.
///
/// Valid values:
///
/// - `always`
///
/// Always display the drag handle, even when there's only one split.
///
/// - `auto` *(default)*
///
/// Automatically show and hide the drag handle. The handle is only
/// shown when there are two or more splits present.
///
/// - `never`
///
/// Never show the drag handle. Splits then cannot be rearranged with
/// mouse controls.
///
/// Available since: 1.4.0.
///
/// Currently only supported on Linux (GTK).
@"drag-handle": DragHandle = .auto,
/// This controls when resize overlays are shown. Resize overlays are a
/// transient popup that shows the size of the terminal while the surfaces are
/// being resized. The possible options are:
@@ -9297,6 +9321,13 @@ pub const WindowShowTabBar = enum {
never,
};
/// See drag-handle
pub const DragHandle = enum {
always,
auto,
never,
};
/// See resize-overlay
pub const ResizeOverlay = enum {
always,