mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-09-05 19:08:17 +00:00
apprt/gtk-ng: initialize window protocol
This commit is contained in:
@@ -15,6 +15,7 @@ const ext = @import("../ext.zig");
|
||||
const gtk_version = @import("../gtk_version.zig");
|
||||
const adw_version = @import("../adw_version.zig");
|
||||
const gresource = @import("../build/gresource.zig");
|
||||
const winprotopkg = @import("../winproto.zig");
|
||||
const Common = @import("../class.zig").Common;
|
||||
const Config = @import("config.zig").Config;
|
||||
const Application = @import("application.zig").Application;
|
||||
@@ -131,6 +132,26 @@ pub const Window = extern struct {
|
||||
);
|
||||
};
|
||||
|
||||
pub const @"quick-terminal" = struct {
|
||||
pub const name = "quick-terminal";
|
||||
const impl = gobject.ext.defineProperty(
|
||||
name,
|
||||
Self,
|
||||
bool,
|
||||
.{
|
||||
.nick = "Quick Terminal",
|
||||
.blurb = "Whether this window behaves like a quick terminal.",
|
||||
.default = true,
|
||||
.accessor = gobject.ext.privateFieldAccessor(
|
||||
Self,
|
||||
Private,
|
||||
&Private.offset,
|
||||
"quick_terminal",
|
||||
),
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
pub const @"tabs-autohide" = struct {
|
||||
pub const name = "tabs-autohide";
|
||||
const impl = gobject.ext.defineProperty(
|
||||
@@ -205,12 +226,19 @@ pub const Window = extern struct {
|
||||
};
|
||||
|
||||
const Private = struct {
|
||||
/// Whether this window is a quick terminal. If it is then it
|
||||
/// behaves slightly differently under certain scenarios.
|
||||
quick_terminal: bool = false,
|
||||
|
||||
/// Binding group for our active tab.
|
||||
tab_bindings: *gobject.BindingGroup,
|
||||
|
||||
/// The configuration that this surface is using.
|
||||
config: ?*Config = null,
|
||||
|
||||
/// State and logic for windowing protocol for a window.
|
||||
winproto: winprotopkg.Window,
|
||||
|
||||
/// Kind of hacky to have this but this lets us know if we've
|
||||
/// initialized any single surface yet. We need this because we
|
||||
/// gate default size on this so that we don't resize the window
|
||||
@@ -253,6 +281,10 @@ pub const Window = extern struct {
|
||||
priv.config = app.getConfig();
|
||||
}
|
||||
|
||||
// We initialize our windowing protocol to none because we can't
|
||||
// actually initialize this until we get realized.
|
||||
priv.winproto = .none;
|
||||
|
||||
// Add our dev CSS class if we're in debug mode.
|
||||
if (comptime build_config.is_debug) {
|
||||
self.as(gtk.Widget).addCssClass("devel");
|
||||
@@ -535,6 +567,11 @@ pub const Window = extern struct {
|
||||
//---------------------------------------------------------------
|
||||
// Properties
|
||||
|
||||
/// Whether this terminal is a quick terminal or not.
|
||||
pub fn isQuickTerminal(self: *Self) bool {
|
||||
return self.private().quick_terminal;
|
||||
}
|
||||
|
||||
/// Get the currently active surface. See the "active-surface" property.
|
||||
/// This does not ref the value.
|
||||
fn getActiveSurface(self: *Self) ?*Surface {
|
||||
@@ -542,6 +579,12 @@ pub const Window = extern struct {
|
||||
return tab.getActiveSurface();
|
||||
}
|
||||
|
||||
/// Returns the configuration for this window. The reference count
|
||||
/// is not increased.
|
||||
pub fn getConfig(self: *Self) ?*Config {
|
||||
return self.private().config;
|
||||
}
|
||||
|
||||
/// Get the currently selected tab as a Tab object.
|
||||
fn getSelectedTab(self: *Self) ?*Tab {
|
||||
const priv = self.private();
|
||||
@@ -731,6 +774,7 @@ pub const Window = extern struct {
|
||||
fn finalize(self: *Self) callconv(.C) void {
|
||||
const priv = self.private();
|
||||
priv.tab_bindings.unref();
|
||||
priv.winproto.deinit(Application.default().allocator());
|
||||
|
||||
gobject.Object.virtual_methods.finalize.call(
|
||||
Class.parent,
|
||||
@@ -741,6 +785,26 @@ pub const Window = extern struct {
|
||||
//---------------------------------------------------------------
|
||||
// Signal handlers
|
||||
|
||||
fn windowRealize(_: *gtk.Widget, self: *Window) callconv(.c) void {
|
||||
const app = Application.default();
|
||||
|
||||
// Initialize our window protocol logic
|
||||
if (winprotopkg.Window.init(
|
||||
app.allocator(),
|
||||
app.winproto(),
|
||||
self,
|
||||
)) |wp| {
|
||||
self.private().winproto = wp;
|
||||
} else |err| {
|
||||
log.warn("failed to initialize window protocol error={}", .{err});
|
||||
return;
|
||||
}
|
||||
|
||||
// When we are realized we always setup our appearance since this
|
||||
// calls some winproto functions.
|
||||
self.syncAppearance();
|
||||
}
|
||||
|
||||
fn btnNewTab(_: *adw.SplitButton, self: *Self) callconv(.c) void {
|
||||
self.performBindingAction(.new_tab);
|
||||
}
|
||||
@@ -1376,6 +1440,7 @@ pub const Window = extern struct {
|
||||
class.bindTemplateChildPrivate("toast_overlay", .{});
|
||||
|
||||
// Template Callbacks
|
||||
class.bindTemplateCallback("realize", &windowRealize);
|
||||
class.bindTemplateCallback("new_tab", &btnNewTab);
|
||||
class.bindTemplateCallback("overview_create_tab", &tabOverviewCreateTab);
|
||||
class.bindTemplateCallback("overview_notify_open", &tabOverviewOpen);
|
||||
|
@@ -7,6 +7,7 @@ template $GhosttyWindow: Adw.ApplicationWindow {
|
||||
]
|
||||
|
||||
close-request => $close_request();
|
||||
realize => $realize();
|
||||
notify::config => $notify_config();
|
||||
notify::fullscreened => $notify_fullscreened();
|
||||
notify::maximized => $notify_maximized();
|
||||
|
@@ -7,9 +7,7 @@ const gdk = @import("gdk");
|
||||
const Config = @import("../../config.zig").Config;
|
||||
const input = @import("../../input.zig");
|
||||
const key = @import("key.zig");
|
||||
|
||||
// TODO: As we get to these APIs the compiler should tell us
|
||||
const ApprtWindow = void;
|
||||
const ApprtWindow = @import("class/window.zig").Window;
|
||||
|
||||
pub const noop = @import("winproto/noop.zig");
|
||||
pub const x11 = @import("winproto/x11.zig");
|
||||
|
@@ -5,7 +5,7 @@ const gdk = @import("gdk");
|
||||
|
||||
const Config = @import("../../../config.zig").Config;
|
||||
const input = @import("../../../input.zig");
|
||||
const ApprtWindow = void; // TODO: fix
|
||||
const ApprtWindow = @import("../class/window.zig").Window;
|
||||
|
||||
const log = std.log.scoped(.winproto_noop);
|
||||
|
||||
|
@@ -12,7 +12,7 @@ const wayland = @import("wayland");
|
||||
|
||||
const Config = @import("../../../config.zig").Config;
|
||||
const input = @import("../../../input.zig");
|
||||
const ApprtWindow = void; // TODO: fix
|
||||
const ApprtWindow = @import("../class/window.zig").Window;
|
||||
|
||||
const wl = wayland.client.wl;
|
||||
const org = wayland.client.org;
|
||||
@@ -257,7 +257,7 @@ pub const Window = struct {
|
||||
) !Window {
|
||||
_ = alloc;
|
||||
|
||||
const gtk_native = apprt_window.window.as(gtk.Native);
|
||||
const gtk_native = apprt_window.as(gtk.Native);
|
||||
const gdk_surface = gtk_native.getSurface() orelse return error.NotWaylandSurface;
|
||||
|
||||
// This should never fail, because if we're being called at this point
|
||||
@@ -470,14 +470,14 @@ pub const Window = struct {
|
||||
monitor: *gdk.Monitor,
|
||||
apprt_window: *ApprtWindow,
|
||||
) callconv(.c) void {
|
||||
const window = apprt_window.window.as(gtk.Window);
|
||||
const config = &apprt_window.config;
|
||||
const window = apprt_window.as(gtk.Window);
|
||||
const config = if (apprt_window.getConfig()) |v| v.get() else return;
|
||||
|
||||
var monitor_size: gdk.Rectangle = undefined;
|
||||
monitor.getGeometry(&monitor_size);
|
||||
|
||||
const dims = config.quick_terminal_size.calculate(
|
||||
config.quick_terminal_position,
|
||||
const dims = config.@"quick-terminal-size".calculate(
|
||||
config.@"quick-terminal-position",
|
||||
.{
|
||||
.width = @intCast(monitor_size.f_width),
|
||||
.height = @intCast(monitor_size.f_height),
|
||||
|
@@ -20,7 +20,7 @@ pub const c = @cImport({
|
||||
|
||||
const input = @import("../../../input.zig");
|
||||
const Config = @import("../../../config.zig").Config;
|
||||
const ApprtWindow = void; // TODO: fix
|
||||
const ApprtWindow = @import("../class/window.zig").Window;
|
||||
|
||||
const log = std.log.scoped(.gtk_x11);
|
||||
|
||||
@@ -170,8 +170,7 @@ pub const App = struct {
|
||||
|
||||
pub const Window = struct {
|
||||
app: *App,
|
||||
config: *const ApprtWindow.DerivedConfig,
|
||||
gtk_window: *adw.ApplicationWindow,
|
||||
apprt_window: *ApprtWindow,
|
||||
x11_surface: *gdk_x11.X11Surface,
|
||||
|
||||
blur_region: Region = .{},
|
||||
@@ -183,9 +182,8 @@ pub const Window = struct {
|
||||
) !Window {
|
||||
_ = alloc;
|
||||
|
||||
const surface = apprt_window.window.as(
|
||||
gtk.Native,
|
||||
).getSurface() orelse return error.NotX11Surface;
|
||||
const surface = apprt_window.as(gtk.Native).getSurface() orelse
|
||||
return error.NotX11Surface;
|
||||
|
||||
const x11_surface = gobject.ext.cast(
|
||||
gdk_x11.X11Surface,
|
||||
@@ -194,8 +192,7 @@ pub const Window = struct {
|
||||
|
||||
return .{
|
||||
.app = app,
|
||||
.config = &apprt_window.config,
|
||||
.gtk_window = apprt_window.window,
|
||||
.apprt_window = apprt_window,
|
||||
.x11_surface = x11_surface,
|
||||
};
|
||||
}
|
||||
@@ -221,10 +218,10 @@ pub const Window = struct {
|
||||
var x: f64 = 0;
|
||||
var y: f64 = 0;
|
||||
|
||||
self.gtk_window.as(gtk.Native).getSurfaceTransform(&x, &y);
|
||||
self.apprt_window.as(gtk.Native).getSurfaceTransform(&x, &y);
|
||||
|
||||
// Transform surface coordinates to device coordinates.
|
||||
const scale: f64 = @floatFromInt(self.gtk_window.as(gtk.Widget).getScaleFactor());
|
||||
const scale: f64 = @floatFromInt(self.apprt_window.as(gtk.Widget).getScaleFactor());
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
|
||||
@@ -257,10 +254,10 @@ pub const Window = struct {
|
||||
// and I think it's not really noticeable enough to justify the effort.
|
||||
// (Wayland also has this visual artifact anyway...)
|
||||
|
||||
const gtk_widget = self.gtk_window.as(gtk.Widget);
|
||||
const gtk_widget = self.apprt_window.as(gtk.Widget);
|
||||
|
||||
// Transform surface coordinates to device coordinates.
|
||||
const scale = self.gtk_window.as(gtk.Widget).getScaleFactor();
|
||||
const scale = self.apprt_window.as(gtk.Widget).getScaleFactor();
|
||||
self.blur_region.width = gtk_widget.getWidth() * scale;
|
||||
self.blur_region.height = gtk_widget.getHeight() * scale;
|
||||
|
||||
|
Reference in New Issue
Block a user