mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
apprt/gtk-ng: initial size apprt action (window-width/height) (#8115)
Simple port. I might add size limits if I get to it, but finished this and it works so opened it up.
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const build_config = @import("../build_config.zig");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
const apprt = @import("../apprt.zig");
|
const apprt = @import("../apprt.zig");
|
||||||
const configpkg = @import("../config.zig");
|
const configpkg = @import("../config.zig");
|
||||||
@ -533,6 +534,16 @@ pub const SizeLimit = extern struct {
|
|||||||
pub const InitialSize = extern struct {
|
pub const InitialSize = extern struct {
|
||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
|
|
||||||
|
/// 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(
|
||||||
|
InitialSize,
|
||||||
|
.{ .name = "GhosttyApprtInitialSize" },
|
||||||
|
),
|
||||||
|
|
||||||
|
.none => void,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CellSize = extern struct {
|
pub const CellSize = extern struct {
|
||||||
|
@ -501,6 +501,8 @@ pub const Application = extern struct {
|
|||||||
|
|
||||||
.goto_tab => return Action.gotoTab(target, value),
|
.goto_tab => return Action.gotoTab(target, value),
|
||||||
|
|
||||||
|
.initial_size => return Action.initialSize(target, value),
|
||||||
|
|
||||||
.mouse_over_link => Action.mouseOverLink(target, value),
|
.mouse_over_link => Action.mouseOverLink(target, value),
|
||||||
.mouse_shape => Action.mouseShape(target, value),
|
.mouse_shape => Action.mouseShape(target, value),
|
||||||
.mouse_visibility => Action.mouseVisibility(target, value),
|
.mouse_visibility => Action.mouseVisibility(target, value),
|
||||||
@ -548,7 +550,6 @@ pub const Application = extern struct {
|
|||||||
.toggle_tab_overview => return Action.toggleTabOverview(target),
|
.toggle_tab_overview => return Action.toggleTabOverview(target),
|
||||||
|
|
||||||
// Unimplemented but todo on gtk-ng branch
|
// Unimplemented but todo on gtk-ng branch
|
||||||
.initial_size,
|
|
||||||
.size_limit,
|
.size_limit,
|
||||||
.prompt_title,
|
.prompt_title,
|
||||||
.toggle_command_palette,
|
.toggle_command_palette,
|
||||||
@ -1346,6 +1347,23 @@ const Action = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn initialSize(
|
||||||
|
target: apprt.Target,
|
||||||
|
value: apprt.action.InitialSize,
|
||||||
|
) bool {
|
||||||
|
switch (target) {
|
||||||
|
.app => return false,
|
||||||
|
.surface => |core| {
|
||||||
|
const surface = core.rt_surface.surface;
|
||||||
|
surface.setDefaultSize(
|
||||||
|
value.width,
|
||||||
|
value.height,
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mouseOverLink(
|
pub fn mouseOverLink(
|
||||||
target: apprt.Target,
|
target: apprt.Target,
|
||||||
value: apprt.action.MouseOverLink,
|
value: apprt.action.MouseOverLink,
|
||||||
|
@ -16,6 +16,7 @@ const renderer = @import("../../../renderer.zig");
|
|||||||
const terminal = @import("../../../terminal/main.zig");
|
const terminal = @import("../../../terminal/main.zig");
|
||||||
const CoreSurface = @import("../../../Surface.zig");
|
const CoreSurface = @import("../../../Surface.zig");
|
||||||
const gresource = @import("../build/gresource.zig");
|
const gresource = @import("../build/gresource.zig");
|
||||||
|
const ext = @import("../ext.zig");
|
||||||
const adw_version = @import("../adw_version.zig");
|
const adw_version = @import("../adw_version.zig");
|
||||||
const gtk_key = @import("../key.zig");
|
const gtk_key = @import("../key.zig");
|
||||||
const ApprtSurface = @import("../Surface.zig");
|
const ApprtSurface = @import("../Surface.zig");
|
||||||
@ -75,6 +76,20 @@ pub const Surface = extern struct {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const @"default-size" = struct {
|
||||||
|
pub const name = "default-size";
|
||||||
|
const impl = gobject.ext.defineProperty(
|
||||||
|
name,
|
||||||
|
Self,
|
||||||
|
?*apprt.action.InitialSize,
|
||||||
|
.{
|
||||||
|
.nick = "Default Size",
|
||||||
|
.blurb = "The default size of the window for this surface.",
|
||||||
|
.accessor = C.privateBoxedFieldAccessor("default_size"),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
pub const @"font-size-request" = struct {
|
pub const @"font-size-request" = struct {
|
||||||
pub const name = "font-size-request";
|
pub const name = "font-size-request";
|
||||||
const impl = gobject.ext.defineProperty(
|
const impl = gobject.ext.defineProperty(
|
||||||
@ -333,6 +348,9 @@ 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 default size for a window that embeds this surface.
|
||||||
|
default_size: ?*apprt.action.InitialSize = null,
|
||||||
|
|
||||||
/// The requested font size. This only applies to initialization
|
/// The requested font size. This only applies to initialization
|
||||||
/// and has no effect later.
|
/// and has no effect later.
|
||||||
font_size_request: ?*font.face.DesiredSize = null,
|
font_size_request: ?*font.face.DesiredSize = null,
|
||||||
@ -1182,6 +1200,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.default_size) |v| {
|
||||||
|
ext.boxedFree(apprt.action.InitialSize, v);
|
||||||
|
priv.default_size = null;
|
||||||
|
}
|
||||||
if (priv.font_size_request) |v| {
|
if (priv.font_size_request) |v| {
|
||||||
glib.ext.destroy(v);
|
glib.ext.destroy(v);
|
||||||
priv.font_size_request = null;
|
priv.font_size_request = null;
|
||||||
@ -1223,6 +1245,28 @@ pub const Surface = extern struct {
|
|||||||
self.as(gobject.Object).notifyByPspec(properties.config.impl.param_spec);
|
self.as(gobject.Object).notifyByPspec(properties.config.impl.param_spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the default size, if set.
|
||||||
|
pub fn getDefaultSize(self: *Self) ?*apprt.action.InitialSize {
|
||||||
|
const priv = self.private();
|
||||||
|
return priv.default_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the default size for a window that contains this surface.
|
||||||
|
/// This is up to the embedding widget to respect this. Generally, only
|
||||||
|
/// the first surface in a window respects this.
|
||||||
|
pub fn setDefaultSize(self: *Self, width: u32, height: u32) void {
|
||||||
|
const priv = self.private();
|
||||||
|
if (priv.default_size) |v| ext.boxedFree(
|
||||||
|
apprt.action.InitialSize,
|
||||||
|
v,
|
||||||
|
);
|
||||||
|
priv.default_size = ext.boxedCopy(
|
||||||
|
apprt.action.InitialSize,
|
||||||
|
&.{ .width = width, .height = height },
|
||||||
|
);
|
||||||
|
self.as(gobject.Object).notifyByPspec(properties.@"default-size".impl.param_spec);
|
||||||
|
}
|
||||||
|
|
||||||
fn propConfig(
|
fn propConfig(
|
||||||
self: *Self,
|
self: *Self,
|
||||||
_: *gobject.ParamSpec,
|
_: *gobject.ParamSpec,
|
||||||
@ -2182,6 +2226,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.@"default-size".impl,
|
||||||
properties.@"font-size-request".impl,
|
properties.@"font-size-request".impl,
|
||||||
properties.focused.impl,
|
properties.focused.impl,
|
||||||
properties.@"mouse-shape".impl,
|
properties.@"mouse-shape".impl,
|
||||||
|
@ -983,6 +983,13 @@ pub const Window = extern struct {
|
|||||||
self,
|
self,
|
||||||
.{},
|
.{},
|
||||||
);
|
);
|
||||||
|
_ = gobject.Object.signals.notify.connect(
|
||||||
|
surface,
|
||||||
|
*Self,
|
||||||
|
surfaceDefaultSize,
|
||||||
|
self,
|
||||||
|
.{ .detail = "default-size" },
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tabViewPageDetached(
|
fn tabViewPageDetached(
|
||||||
@ -1172,6 +1179,23 @@ pub const Window = extern struct {
|
|||||||
// We react to the changes in the propMaximized callback
|
// We react to the changes in the propMaximized callback
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn surfaceDefaultSize(
|
||||||
|
surface: *Surface,
|
||||||
|
_: *gobject.ParamSpec,
|
||||||
|
self: *Self,
|
||||||
|
) callconv(.c) void {
|
||||||
|
const size = surface.getDefaultSize() orelse return;
|
||||||
|
|
||||||
|
// We previously gated this on whether this was called before but
|
||||||
|
// its useful to always set this to whatever the expected value is
|
||||||
|
// so we can do a "return to default size" later. This call only
|
||||||
|
// affects the window on first load. It won't resize it again later.
|
||||||
|
self.as(gtk.Window).setDefaultSize(
|
||||||
|
@intCast(size.width),
|
||||||
|
@intCast(size.height),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn actionAbout(
|
fn actionAbout(
|
||||||
_: *gio.SimpleAction,
|
_: *gio.SimpleAction,
|
||||||
_: ?*glib.Variant,
|
_: ?*glib.Variant,
|
||||||
|
@ -9,6 +9,20 @@ const assert = std.debug.assert;
|
|||||||
const gobject = @import("gobject");
|
const gobject = @import("gobject");
|
||||||
const gtk = @import("gtk");
|
const gtk = @import("gtk");
|
||||||
|
|
||||||
|
/// Wrapper around `gobject.boxedCopy` to copy a boxed type `T`.
|
||||||
|
pub fn boxedCopy(comptime T: type, ptr: *const T) *T {
|
||||||
|
const copy = gobject.boxedCopy(T.getGObjectType(), ptr);
|
||||||
|
return @ptrCast(@alignCast(copy));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper around `gobject.boxedFree` to free a boxed type `T`.
|
||||||
|
pub fn boxedFree(comptime T: type, ptr: ?*T) void {
|
||||||
|
if (ptr) |p| gobject.boxedFree(
|
||||||
|
T.getGObjectType(),
|
||||||
|
p,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper around `gtk.Widget.getAncestor` to get the widget ancestor
|
/// Wrapper around `gtk.Widget.getAncestor` to get the widget ancestor
|
||||||
/// of the given type `T`, or null if it doesn't exist.
|
/// of the given type `T`, or null if it doesn't exist.
|
||||||
pub fn getAncestor(comptime T: type, widget: *gtk.Widget) ?*T {
|
pub fn getAncestor(comptime T: type, widget: *gtk.Widget) ?*T {
|
||||||
|
Reference in New Issue
Block a user