apprt/gtk-ng: hook up Tab signals to surface
parent
3b4c33afe0
commit
bc731c0ff6
|
|
@ -1318,6 +1318,11 @@ pub const Surface = extern struct {
|
||||||
return self.private().pwd;
|
return self.private().pwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the focus state of this surface.
|
||||||
|
pub fn getFocused(self: *Self) bool {
|
||||||
|
return self.private().focused;
|
||||||
|
}
|
||||||
|
|
||||||
/// Change the configuration for this surface.
|
/// Change the configuration for this surface.
|
||||||
pub fn setConfig(self: *Self, config: *Config) void {
|
pub fn setConfig(self: *Self, config: *Config) void {
|
||||||
const priv = self.private();
|
const priv = self.private();
|
||||||
|
|
@ -1654,6 +1659,7 @@ pub const Surface = extern struct {
|
||||||
priv.focused = true;
|
priv.focused = true;
|
||||||
priv.im_context.as(gtk.IMContext).focusIn();
|
priv.im_context.as(gtk.IMContext).focusIn();
|
||||||
_ = glib.idleAddOnce(idleFocus, self.ref());
|
_ = glib.idleAddOnce(idleFocus, self.ref());
|
||||||
|
self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ecFocusLeave(_: *gtk.EventControllerFocus, self: *Self) callconv(.c) void {
|
fn ecFocusLeave(_: *gtk.EventControllerFocus, self: *Self) callconv(.c) void {
|
||||||
|
|
@ -1661,6 +1667,7 @@ pub const Surface = extern struct {
|
||||||
priv.focused = false;
|
priv.focused = false;
|
||||||
priv.im_context.as(gtk.IMContext).focusOut();
|
priv.im_context.as(gtk.IMContext).focusOut();
|
||||||
_ = glib.idleAddOnce(idleFocus, self.ref());
|
_ = glib.idleAddOnce(idleFocus, self.ref());
|
||||||
|
self.as(gobject.Object).notifyByPspec(properties.focused.impl.param_spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The focus callback must be triggered on an idle loop source because
|
/// The focus callback must be triggered on an idle loop source because
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,6 @@ pub const Tab = extern struct {
|
||||||
|
|
||||||
// Template bindings
|
// Template bindings
|
||||||
split_tree: *SplitTree,
|
split_tree: *SplitTree,
|
||||||
surface: *Surface,
|
|
||||||
|
|
||||||
pub var offset: c_int = 0;
|
pub var offset: c_int = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -147,12 +146,10 @@ pub const Tab = extern struct {
|
||||||
/// Set the parent of this tab page. This only affects the first surface
|
/// Set the parent of this tab page. This only affects the first surface
|
||||||
/// ever created for a tab. If a surface was already created this does
|
/// ever created for a tab. If a surface was already created this does
|
||||||
/// nothing.
|
/// nothing.
|
||||||
pub fn setParent(
|
pub fn setParent(self: *Self, parent: *CoreSurface) void {
|
||||||
self: *Self,
|
if (self.getActiveSurface()) |surface| {
|
||||||
parent: *CoreSurface,
|
surface.setParent(parent);
|
||||||
) void {
|
}
|
||||||
const priv = self.private();
|
|
||||||
priv.surface.setParent(parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(self: *Self, _: *Class) callconv(.c) void {
|
fn init(self: *Self, _: *Class) callconv(.c) void {
|
||||||
|
|
@ -175,10 +172,6 @@ pub const Tab = extern struct {
|
||||||
.{},
|
.{},
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Eventually this should be set dynamically based on the
|
|
||||||
// current active surface.
|
|
||||||
priv.surface_bindings.setSource(priv.surface.as(gobject.Object));
|
|
||||||
|
|
||||||
// We need to do this so that the title initializes properly,
|
// We need to do this so that the title initializes properly,
|
||||||
// I think because its a dynamic getter.
|
// I think because its a dynamic getter.
|
||||||
self.as(gobject.Object).notifyByPspec(properties.@"active-surface".impl.param_spec);
|
self.as(gobject.Object).notifyByPspec(properties.@"active-surface".impl.param_spec);
|
||||||
|
|
@ -194,14 +187,62 @@ pub const Tab = extern struct {
|
||||||
priv.split_tree.setTree(&tree);
|
priv.split_tree.setTree(&tree);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn connectSurfaceHandlers(
|
||||||
|
self: *Self,
|
||||||
|
tree: *const Surface.Tree,
|
||||||
|
) void {
|
||||||
|
var it = tree.iterator();
|
||||||
|
while (it.next()) |entry| {
|
||||||
|
const surface = entry.view;
|
||||||
|
_ = Surface.signals.@"close-request".connect(
|
||||||
|
surface,
|
||||||
|
*Self,
|
||||||
|
surfaceCloseRequest,
|
||||||
|
self,
|
||||||
|
.{},
|
||||||
|
);
|
||||||
|
_ = gobject.Object.signals.notify.connect(
|
||||||
|
surface,
|
||||||
|
*Self,
|
||||||
|
propSurfaceFocused,
|
||||||
|
self,
|
||||||
|
.{ .detail = "focused" },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// Properties
|
||||||
|
|
||||||
/// Get the currently active surface. See the "active-surface" property.
|
/// Get the currently active surface. See the "active-surface" property.
|
||||||
/// This does not ref the value.
|
/// This does not ref the value.
|
||||||
pub fn getActiveSurface(self: *Self) *Surface {
|
pub fn getActiveSurface(self: *Self) ?*Surface {
|
||||||
const priv = self.private();
|
const tree = self.getSurfaceTree() orelse return null;
|
||||||
return priv.surface;
|
var it = tree.iterator();
|
||||||
|
while (it.next()) |entry| {
|
||||||
|
if (entry.view.getFocused()) return entry.view;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the surface tree of this tab.
|
/// Get the surface tree of this tab.
|
||||||
|
|
@ -219,7 +260,7 @@ pub const Tab = extern struct {
|
||||||
/// Returns true if this tab needs confirmation before quitting based
|
/// Returns true if this tab needs confirmation before quitting based
|
||||||
/// on the various Ghostty configurations.
|
/// on the various Ghostty configurations.
|
||||||
pub fn getNeedsConfirmQuit(self: *Self) bool {
|
pub fn getNeedsConfirmQuit(self: *Self) bool {
|
||||||
const surface = self.getActiveSurface();
|
const surface = self.getActiveSurface() orelse return false;
|
||||||
const core_surface = surface.core() orelse return false;
|
const core_surface = surface.core() orelse return false;
|
||||||
return core_surface.needsConfirmQuit();
|
return core_surface.needsConfirmQuit();
|
||||||
}
|
}
|
||||||
|
|
@ -283,6 +324,20 @@ pub const Tab = extern struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn splitTreeWillChange(
|
||||||
|
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 propSplitTree(
|
fn propSplitTree(
|
||||||
_: *SplitTree,
|
_: *SplitTree,
|
||||||
_: *gobject.ParamSpec,
|
_: *gobject.ParamSpec,
|
||||||
|
|
@ -291,6 +346,27 @@ pub const Tab = extern struct {
|
||||||
self.as(gobject.Object).notifyByPspec(properties.@"surface-tree".impl.param_spec);
|
self.as(gobject.Object).notifyByPspec(properties.@"surface-tree".impl.param_spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn propActiveSurface(
|
||||||
|
_: *Self,
|
||||||
|
_: *gobject.ParamSpec,
|
||||||
|
self: *Self,
|
||||||
|
) callconv(.c) void {
|
||||||
|
const priv = self.private();
|
||||||
|
priv.surface_bindings.setSource(null);
|
||||||
|
if (self.getActiveSurface()) |surface| {
|
||||||
|
priv.surface_bindings.setSource(surface.as(gobject.Object));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn propSurfaceFocused(
|
||||||
|
surface: *Surface,
|
||||||
|
_: *gobject.ParamSpec,
|
||||||
|
self: *Self,
|
||||||
|
) callconv(.c) void {
|
||||||
|
if (!surface.getFocused()) return;
|
||||||
|
self.as(gobject.Object).notifyByPspec(properties.@"active-surface".impl.param_spec);
|
||||||
|
}
|
||||||
|
|
||||||
const C = Common(Self, Private);
|
const C = Common(Self, Private);
|
||||||
pub const as = C.as;
|
pub const as = C.as;
|
||||||
pub const ref = C.ref;
|
pub const ref = C.ref;
|
||||||
|
|
@ -324,10 +400,10 @@ pub const Tab = extern struct {
|
||||||
|
|
||||||
// Bindings
|
// Bindings
|
||||||
class.bindTemplateChildPrivate("split_tree", .{});
|
class.bindTemplateChildPrivate("split_tree", .{});
|
||||||
class.bindTemplateChildPrivate("surface", .{});
|
|
||||||
|
|
||||||
// Template Callbacks
|
// Template Callbacks
|
||||||
class.bindTemplateCallback("surface_close_request", &surfaceCloseRequest);
|
class.bindTemplateCallback("tree_will_change", &splitTreeWillChange);
|
||||||
|
class.bindTemplateCallback("notify_active_surface", &propActiveSurface);
|
||||||
class.bindTemplateCallback("notify_tree", &propSplitTree);
|
class.bindTemplateCallback("notify_tree", &propSplitTree);
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,13 @@ template $GhosttyTab: Box {
|
||||||
"tab",
|
"tab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
notify::active-surface => $notify_active_surface();
|
||||||
orientation: vertical;
|
orientation: vertical;
|
||||||
hexpand: true;
|
hexpand: true;
|
||||||
vexpand: true;
|
vexpand: true;
|
||||||
// A tab currently just contains a surface directly. When we introduce
|
|
||||||
// splits we probably want to replace this with the split widget type.
|
|
||||||
$GhosttySurface surface {
|
|
||||||
close-request => $surface_close_request();
|
|
||||||
}
|
|
||||||
|
|
||||||
$GhosttySplitTree split_tree {
|
$GhosttySplitTree split_tree {
|
||||||
notify::tree => $notify_tree();
|
notify::tree => $notify_tree();
|
||||||
|
tree-will-change => $tree_will_change();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue