apprt/gtk-ng: surface inheritance, new window (#8067)
This makes the `new_window` action properly inherit properties from the parent surface that initiated the action. Today, that is only the pwd and font size.pull/8068/head
commit
3cdd6f4f5e
|
|
@ -1085,9 +1085,7 @@ const Action = struct {
|
||||||
self: *Application,
|
self: *Application,
|
||||||
parent: ?*CoreSurface,
|
parent: ?*CoreSurface,
|
||||||
) !void {
|
) !void {
|
||||||
_ = parent;
|
const win = Window.new(self, parent);
|
||||||
|
|
||||||
const win = Window.new(self);
|
|
||||||
gtk.Window.present(win.as(gtk.Window));
|
gtk.Window.present(win.as(gtk.Window));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ const gobject = @import("gobject");
|
||||||
const gtk = @import("gtk");
|
const gtk = @import("gtk");
|
||||||
|
|
||||||
const apprt = @import("../../../apprt.zig");
|
const apprt = @import("../../../apprt.zig");
|
||||||
|
const font = @import("../../../font/main.zig");
|
||||||
const input = @import("../../../input.zig");
|
const input = @import("../../../input.zig");
|
||||||
const internal_os = @import("../../../os/main.zig");
|
const internal_os = @import("../../../os/main.zig");
|
||||||
const renderer = @import("../../../renderer.zig");
|
const renderer = @import("../../../renderer.zig");
|
||||||
|
|
@ -79,6 +80,25 @@ pub const Surface = extern struct {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const @"font-size-request" = struct {
|
||||||
|
pub const name = "font-size-request";
|
||||||
|
const impl = gobject.ext.defineProperty(
|
||||||
|
name,
|
||||||
|
Self,
|
||||||
|
?*font.face.DesiredSize,
|
||||||
|
.{
|
||||||
|
.nick = "Desired Font Size",
|
||||||
|
.blurb = "The desired font size, only affects initialization.",
|
||||||
|
.accessor = gobject.ext.privateFieldAccessor(
|
||||||
|
Self,
|
||||||
|
Private,
|
||||||
|
&Private.offset,
|
||||||
|
"font_size_request",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
pub const focused = struct {
|
pub const focused = struct {
|
||||||
pub const name = "focused";
|
pub const name = "focused";
|
||||||
const impl = gobject.ext.defineProperty(
|
const impl = gobject.ext.defineProperty(
|
||||||
|
|
@ -261,6 +281,10 @@ pub const Surface = extern struct {
|
||||||
/// if `Application.transient_cgroup_base` is set.
|
/// if `Application.transient_cgroup_base` is set.
|
||||||
cgroup_path: ?[]const u8 = null,
|
cgroup_path: ?[]const u8 = null,
|
||||||
|
|
||||||
|
/// The requested font size. This only applies to initialization
|
||||||
|
/// and has no effect later.
|
||||||
|
font_size_request: ?*font.face.DesiredSize = null,
|
||||||
|
|
||||||
/// The mouse shape to show for the surface.
|
/// The mouse shape to show for the surface.
|
||||||
mouse_shape: terminal.MouseShape = .default,
|
mouse_shape: terminal.MouseShape = .default,
|
||||||
|
|
||||||
|
|
@ -273,6 +297,10 @@ pub const Surface = extern struct {
|
||||||
/// The current working directory. This has to be reported externally,
|
/// The current working directory. This has to be reported externally,
|
||||||
/// usually by shell integration which then talks to libghostty
|
/// usually by shell integration which then talks to libghostty
|
||||||
/// which triggers this property.
|
/// which triggers this property.
|
||||||
|
///
|
||||||
|
/// If this is set prior to initialization then the surface will
|
||||||
|
/// start in this pwd. If it is set after, it has no impact on the
|
||||||
|
/// core surface.
|
||||||
pwd: ?[:0]const u8 = null,
|
pwd: ?[:0]const u8 = null,
|
||||||
|
|
||||||
/// The title of this surface, if any has been set.
|
/// The title of this surface, if any has been set.
|
||||||
|
|
@ -349,6 +377,38 @@ pub const Surface = extern struct {
|
||||||
return &priv.rt_surface;
|
return &priv.rt_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the parent of this surface. This will extract the information
|
||||||
|
/// required to initialize this surface with the proper values but doesn't
|
||||||
|
/// retain any memory.
|
||||||
|
///
|
||||||
|
/// If the surface is already realized this does nothing.
|
||||||
|
pub fn setParent(
|
||||||
|
self: *Self,
|
||||||
|
parent: *CoreSurface,
|
||||||
|
) void {
|
||||||
|
const priv = self.private();
|
||||||
|
|
||||||
|
// This is a mistake! We can only set a parent before surface
|
||||||
|
// realization. We log this because this is probably a logic error.
|
||||||
|
if (priv.core_surface != null) {
|
||||||
|
log.warn("setParent called after surface is already realized", .{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup our font size
|
||||||
|
const font_size_ptr = glib.ext.create(font.face.DesiredSize);
|
||||||
|
errdefer glib.ext.destroy(font_size_ptr);
|
||||||
|
font_size_ptr.* = parent.font_size;
|
||||||
|
priv.font_size_request = font_size_ptr;
|
||||||
|
self.as(gobject.Object).notifyByPspec(properties.@"font-size-request".impl.param_spec);
|
||||||
|
|
||||||
|
// Setup our pwd
|
||||||
|
if (parent.rt_surface.surface.getPwd()) |pwd| {
|
||||||
|
priv.pwd = glib.ext.dupeZ(u8, pwd);
|
||||||
|
self.as(gobject.Object).notifyByPspec(properties.pwd.impl.param_spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Force the surface to redraw itself. Ghostty often will only redraw
|
/// Force the surface to redraw itself. Ghostty often will only redraw
|
||||||
/// the terminal in reaction to internal changes. If there are external
|
/// the terminal in reaction to internal changes. If there are external
|
||||||
/// events that invalidate the surface, such as the widget moving parents,
|
/// events that invalidate the surface, such as the widget moving parents,
|
||||||
|
|
@ -1029,6 +1089,10 @@ pub const Surface = extern struct {
|
||||||
glib.free(@constCast(@ptrCast(v)));
|
glib.free(@constCast(@ptrCast(v)));
|
||||||
priv.mouse_hover_url = null;
|
priv.mouse_hover_url = null;
|
||||||
}
|
}
|
||||||
|
if (priv.font_size_request) |v| {
|
||||||
|
glib.ext.destroy(v);
|
||||||
|
priv.font_size_request = null;
|
||||||
|
}
|
||||||
if (priv.pwd) |v| {
|
if (priv.pwd) |v| {
|
||||||
glib.free(@constCast(@ptrCast(v)));
|
glib.free(@constCast(@ptrCast(v)));
|
||||||
priv.pwd = null;
|
priv.pwd = null;
|
||||||
|
|
@ -1053,6 +1117,11 @@ pub const Surface = extern struct {
|
||||||
return self.private().title;
|
return self.private().title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the pwd property without a copy.
|
||||||
|
pub fn getPwd(self: *Self) ?[:0]const u8 {
|
||||||
|
return self.private().pwd;
|
||||||
|
}
|
||||||
|
|
||||||
fn propConfig(
|
fn propConfig(
|
||||||
self: *Self,
|
self: *Self,
|
||||||
_: *gobject.ParamSpec,
|
_: *gobject.ParamSpec,
|
||||||
|
|
@ -1893,6 +1962,10 @@ pub const Surface = extern struct {
|
||||||
);
|
);
|
||||||
defer config.deinit();
|
defer config.deinit();
|
||||||
|
|
||||||
|
// Properties that can impact surface init
|
||||||
|
if (priv.font_size_request) |size| config.@"font-size" = size.points;
|
||||||
|
if (priv.pwd) |pwd| config.@"working-directory" = pwd;
|
||||||
|
|
||||||
// Initialize the surface
|
// Initialize the surface
|
||||||
surface.init(
|
surface.init(
|
||||||
alloc,
|
alloc,
|
||||||
|
|
@ -1996,6 +2069,7 @@ pub const Surface = extern struct {
|
||||||
gobject.ext.registerProperties(class, &.{
|
gobject.ext.registerProperties(class, &.{
|
||||||
properties.config.impl,
|
properties.config.impl,
|
||||||
properties.@"child-exited".impl,
|
properties.@"child-exited".impl,
|
||||||
|
properties.@"font-size-request".impl,
|
||||||
properties.focused.impl,
|
properties.focused.impl,
|
||||||
properties.@"mouse-shape".impl,
|
properties.@"mouse-shape".impl,
|
||||||
properties.@"mouse-hidden".impl,
|
properties.@"mouse-hidden".impl,
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ const adw = @import("adw");
|
||||||
const gobject = @import("gobject");
|
const gobject = @import("gobject");
|
||||||
const gtk = @import("gtk");
|
const gtk = @import("gtk");
|
||||||
|
|
||||||
|
const CoreSurface = @import("../../../Surface.zig");
|
||||||
const gresource = @import("../build/gresource.zig");
|
const gresource = @import("../build/gresource.zig");
|
||||||
const Common = @import("../class.zig").Common;
|
const Common = @import("../class.zig").Common;
|
||||||
const Application = @import("application.zig").Application;
|
const Application = @import("application.zig").Application;
|
||||||
|
|
@ -30,8 +31,17 @@ pub const Window = extern struct {
|
||||||
pub var offset: c_int = 0;
|
pub var offset: c_int = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn new(app: *Application) *Self {
|
pub fn new(app: *Application, parent_: ?*CoreSurface) *Self {
|
||||||
return gobject.ext.newInstance(Self, .{ .application = app });
|
const self = gobject.ext.newInstance(Self, .{
|
||||||
|
.application = app,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (parent_) |parent| {
|
||||||
|
const priv = self.private();
|
||||||
|
priv.surface.setParent(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(self: *Self, _: *Class) callconv(.C) void {
|
fn init(self: *Self, _: *Class) callconv(.C) void {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
|
const build_config = @import("../build_config.zig");
|
||||||
const options = @import("main.zig").options;
|
const options = @import("main.zig").options;
|
||||||
const Metrics = @import("main.zig").Metrics;
|
const Metrics = @import("main.zig").Metrics;
|
||||||
const config = @import("../config.zig");
|
const config = @import("../config.zig");
|
||||||
|
|
@ -55,6 +56,16 @@ pub const DesiredSize = struct {
|
||||||
// 1 point = 1/72 inch
|
// 1 point = 1/72 inch
|
||||||
return @intFromFloat(@round((self.points * @as(f32, @floatFromInt(self.ydpi))) / 72));
|
return @intFromFloat(@round((self.points * @as(f32, @floatFromInt(self.ydpi))) / 72));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Make this a valid gobject if we're in a GTK environment.
|
||||||
|
pub const getGObjectType = switch (build_config.app_runtime) {
|
||||||
|
.gtk, .@"gtk-ng" => @import("gobject").ext.defineBoxed(
|
||||||
|
DesiredSize,
|
||||||
|
.{ .name = "GhosttyFontDesiredSize" },
|
||||||
|
),
|
||||||
|
|
||||||
|
.none => void,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A font variation setting. The best documentation for this I know of
|
/// A font variation setting. The best documentation for this I know of
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue