apprt/gtk-ng: connect surface signals
parent
a7865d79ea
commit
3b4c33afe0
|
|
@ -81,7 +81,7 @@ pub const SplitTree = extern struct {
|
|||
/// The new value is given as the signal parameter. The old value
|
||||
/// can still be retrieved from the tree property.
|
||||
pub const @"tree-will-change" = struct {
|
||||
pub const name = "tree-change";
|
||||
pub const name = "tree-will-change";
|
||||
pub const connect = impl.connect;
|
||||
const impl = gobject.ext.defineSignal(
|
||||
name,
|
||||
|
|
|
|||
|
|
@ -74,6 +74,26 @@ pub const Tab = extern struct {
|
|||
);
|
||||
};
|
||||
|
||||
pub const @"surface-tree" = struct {
|
||||
pub const name = "surface-tree";
|
||||
const impl = gobject.ext.defineProperty(
|
||||
name,
|
||||
Self,
|
||||
?*Surface.Tree,
|
||||
.{
|
||||
.nick = "Surface Tree",
|
||||
.blurb = "The surface tree that is contained in this tab.",
|
||||
.accessor = gobject.ext.typedAccessor(
|
||||
Self,
|
||||
?*Surface.Tree,
|
||||
.{
|
||||
.getter = getSurfaceTree,
|
||||
},
|
||||
),
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
pub const title = struct {
|
||||
pub const name = "title";
|
||||
pub const get = impl.get;
|
||||
|
|
@ -184,6 +204,18 @@ pub const Tab = extern struct {
|
|||
return priv.surface;
|
||||
}
|
||||
|
||||
/// Get the surface tree of this tab.
|
||||
pub fn getSurfaceTree(self: *Self) ?*Surface.Tree {
|
||||
const priv = self.private();
|
||||
return priv.split_tree.getTree();
|
||||
}
|
||||
|
||||
/// Get the split tree widget that is in this tab.
|
||||
pub fn getSplitTree(self: *Self) *SplitTree {
|
||||
const priv = self.private();
|
||||
return priv.split_tree;
|
||||
}
|
||||
|
||||
/// Returns true if this tab needs confirmation before quitting based
|
||||
/// on the various Ghostty configurations.
|
||||
pub fn getNeedsConfirmQuit(self: *Self) bool {
|
||||
|
|
@ -251,6 +283,14 @@ pub const Tab = extern struct {
|
|||
}
|
||||
}
|
||||
|
||||
fn propSplitTree(
|
||||
_: *SplitTree,
|
||||
_: *gobject.ParamSpec,
|
||||
self: *Self,
|
||||
) callconv(.c) void {
|
||||
self.as(gobject.Object).notifyByPspec(properties.@"surface-tree".impl.param_spec);
|
||||
}
|
||||
|
||||
const C = Common(Self, Private);
|
||||
pub const as = C.as;
|
||||
pub const ref = C.ref;
|
||||
|
|
@ -278,6 +318,7 @@ pub const Tab = extern struct {
|
|||
gobject.ext.registerProperties(class, &.{
|
||||
properties.@"active-surface".impl,
|
||||
properties.config.impl,
|
||||
properties.@"surface-tree".impl,
|
||||
properties.title.impl,
|
||||
});
|
||||
|
||||
|
|
@ -287,6 +328,7 @@ pub const Tab = extern struct {
|
|||
|
||||
// Template Callbacks
|
||||
class.bindTemplateCallback("surface_close_request", &surfaceCloseRequest);
|
||||
class.bindTemplateCallback("notify_tree", &propSplitTree);
|
||||
|
||||
// Signals
|
||||
signals.@"close-request".impl.register(.{});
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const Common = @import("../class.zig").Common;
|
|||
const Config = @import("config.zig").Config;
|
||||
const Application = @import("application.zig").Application;
|
||||
const CloseConfirmationDialog = @import("close_confirmation_dialog.zig").CloseConfirmationDialog;
|
||||
const SplitTree = @import("split_tree.zig").SplitTree;
|
||||
const Surface = @import("surface.zig").Surface;
|
||||
const Tab = @import("tab.zig").Tab;
|
||||
const DebugWarning = @import("debug_warning.zig").DebugWarning;
|
||||
|
|
@ -408,6 +409,24 @@ pub const Window = extern struct {
|
|||
.{ .sync_create = true },
|
||||
);
|
||||
|
||||
// Bind signals
|
||||
const split_tree = tab.getSplitTree();
|
||||
_ = SplitTree.signals.@"tree-will-change".connect(
|
||||
split_tree,
|
||||
*Self,
|
||||
tabSplitTreeWillChange,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
|
||||
// Run an initial notification for the surface tree so we can setup
|
||||
// initial state.
|
||||
tabSplitTreeWillChange(
|
||||
split_tree,
|
||||
split_tree.getTree(),
|
||||
self,
|
||||
);
|
||||
|
||||
return page;
|
||||
}
|
||||
|
||||
|
|
@ -637,6 +656,102 @@ pub const Window = extern struct {
|
|||
self.private().toast_overlay.addToast(toast);
|
||||
}
|
||||
|
||||
fn connectSurfaceHandlers(
|
||||
self: *Self,
|
||||
tree: *const Surface.Tree,
|
||||
) void {
|
||||
const priv = self.private();
|
||||
var it = tree.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const surface = entry.view;
|
||||
_ = Surface.signals.@"close-request".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceCloseRequest,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.@"present-request".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfacePresentRequest,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.@"clipboard-write".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceClipboardWrite,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.menu.connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceMenu,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.@"toggle-fullscreen".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceToggleFullscreen,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.@"toggle-maximize".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceToggleMaximize,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.@"toggle-command-palette".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceToggleCommandPalette,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
|
||||
// If we've never had a surface initialize yet, then we register
|
||||
// this signal. Its theoretically possible to launch multiple surfaces
|
||||
// before init so we could register this on multiple and that is not
|
||||
// a problem because we'll check the flag again in each handler.
|
||||
if (!priv.surface_init) {
|
||||
_ = Surface.signals.init.connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceInit,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Disconnect all the surface handlers for the given tree. This should
|
||||
/// be called whenever a tree is no longer present in the window, e.g.
|
||||
/// when a tab is detached or the tree changes.
|
||||
fn disconnectSurfaceHandlers(
|
||||
self: *Self,
|
||||
tree: *const Surface.Tree,
|
||||
) void {
|
||||
var it = tree.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const surface = entry.view;
|
||||
_ = gobject.signalHandlersDisconnectMatched(
|
||||
surface.as(gobject.Object),
|
||||
.{ .data = true },
|
||||
0,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
self,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Properties
|
||||
|
||||
|
|
@ -1134,8 +1249,6 @@ pub const Window = extern struct {
|
|||
_: c_int,
|
||||
self: *Self,
|
||||
) callconv(.c) void {
|
||||
const priv = self.private();
|
||||
|
||||
// Get the attached page which must be a Tab object.
|
||||
const child = page.getChild();
|
||||
const tab = gobject.ext.cast(Tab, child) orelse return;
|
||||
|
|
@ -1168,71 +1281,8 @@ pub const Window = extern struct {
|
|||
// behavior is consistent with macOS and the previous GTK apprt,
|
||||
// but that behavior was all implicit and not documented, so here
|
||||
// I am.
|
||||
//
|
||||
// TODO: When we have a split tree we'll want to attach to that.
|
||||
const surface = tab.getActiveSurface();
|
||||
_ = Surface.signals.@"close-request".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceCloseRequest,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.@"present-request".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfacePresentRequest,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.@"clipboard-write".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceClipboardWrite,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.menu.connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceMenu,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.@"toggle-fullscreen".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceToggleFullscreen,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.@"toggle-maximize".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceToggleMaximize,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
_ = Surface.signals.@"toggle-command-palette".connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceToggleCommandPalette,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
|
||||
// If we've never had a surface initialize yet, then we register
|
||||
// this signal. Its theoretically possible to launch multiple surfaces
|
||||
// before init so we could register this on multiple and that is not
|
||||
// a problem because we'll check the flag again in each handler.
|
||||
if (!priv.surface_init) {
|
||||
_ = Surface.signals.init.connect(
|
||||
surface,
|
||||
*Self,
|
||||
surfaceInit,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
if (tab.getSurfaceTree()) |tree| {
|
||||
self.connectSurfaceHandlers(tree);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1255,17 +1305,10 @@ pub const Window = extern struct {
|
|||
self,
|
||||
);
|
||||
|
||||
// Remove all the signals that have this window as the userdata.
|
||||
const surface = tab.getActiveSurface();
|
||||
_ = gobject.signalHandlersDisconnectMatched(
|
||||
surface.as(gobject.Object),
|
||||
.{ .data = true },
|
||||
0,
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
self,
|
||||
);
|
||||
// Remove the tree handlers
|
||||
if (tab.getSurfaceTree()) |tree| {
|
||||
self.disconnectSurfaceHandlers(tree);
|
||||
}
|
||||
}
|
||||
|
||||
fn tabViewCreateWindow(
|
||||
|
|
@ -1464,6 +1507,20 @@ pub const Window = extern struct {
|
|||
}
|
||||
}
|
||||
|
||||
fn tabSplitTreeWillChange(
|
||||
split_tree: *SplitTree,
|
||||
new_tree: ?*const Surface.Tree,
|
||||
self: *Self,
|
||||
) callconv(.c) void {
|
||||
if (split_tree.getTree()) |old_tree| {
|
||||
self.disconnectSurfaceHandlers(old_tree);
|
||||
}
|
||||
|
||||
if (new_tree) |tree| {
|
||||
self.connectSurfaceHandlers(tree);
|
||||
}
|
||||
}
|
||||
|
||||
fn actionAbout(
|
||||
_: *gio.SimpleAction,
|
||||
_: ?*glib.Variant,
|
||||
|
|
|
|||
|
|
@ -14,5 +14,7 @@ template $GhosttyTab: Box {
|
|||
close-request => $surface_close_request();
|
||||
}
|
||||
|
||||
$GhosttySplitTree split_tree {}
|
||||
$GhosttySplitTree split_tree {
|
||||
notify::tree => $notify_tree();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue