mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-17 09:16:11 +03:00
apprt/gtk: convert surface to overlay so we can support the url overlay
This commit is contained in:
@ -72,7 +72,7 @@ pub const Container = union(enum) {
|
|||||||
/// element
|
/// element
|
||||||
pub fn widget(self: Elem) *c.GtkWidget {
|
pub fn widget(self: Elem) *c.GtkWidget {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
.surface => |s| @ptrCast(s.gl_area),
|
.surface => |s| s.primaryWidget(),
|
||||||
.split => |s| @ptrCast(@alignCast(s.paned)),
|
.split => |s| @ptrCast(@alignCast(s.paned)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -223,9 +223,15 @@ container: Container = .{ .none = {} },
|
|||||||
/// The app we're part of
|
/// The app we're part of
|
||||||
app: *App,
|
app: *App,
|
||||||
|
|
||||||
|
/// The overlay, this is the primary widget
|
||||||
|
overlay: *c.GtkOverlay,
|
||||||
|
|
||||||
/// Our GTK area
|
/// Our GTK area
|
||||||
gl_area: *c.GtkGLArea,
|
gl_area: *c.GtkGLArea,
|
||||||
|
|
||||||
|
/// If non-null this is the widget on the overlay that shows the URL.
|
||||||
|
url_widget: ?*c.GtkWidget = null,
|
||||||
|
|
||||||
/// Any active cursor we may have
|
/// Any active cursor we may have
|
||||||
cursor: ?*c.GdkCursor = null,
|
cursor: ?*c.GdkCursor = null,
|
||||||
|
|
||||||
@ -271,15 +277,19 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
|
|||||||
const widget: *c.GtkWidget = c.gtk_gl_area_new();
|
const widget: *c.GtkWidget = c.gtk_gl_area_new();
|
||||||
const gl_area: *c.GtkGLArea = @ptrCast(widget);
|
const gl_area: *c.GtkGLArea = @ptrCast(widget);
|
||||||
|
|
||||||
// We grab the floating reference to GL area. This lets the
|
// Create an overlay so we can layer the GL area with other widgets.
|
||||||
// GL area be moved around i.e. between a split, a tab, etc.
|
const overlay: *c.GtkOverlay = @ptrCast(c.gtk_overlay_new());
|
||||||
|
c.gtk_overlay_set_child(@ptrCast(overlay), widget);
|
||||||
|
|
||||||
|
// We grab the floating reference to the primary widget. This allows the
|
||||||
|
// widget tree to be moved around i.e. between a split, a tab, etc.
|
||||||
// without having to be really careful about ordering to
|
// without having to be really careful about ordering to
|
||||||
// prevent a destroy.
|
// prevent a destroy.
|
||||||
//
|
//
|
||||||
// This is unref'd in the unref() method that's called by the
|
// This is unref'd in the unref() method that's called by the
|
||||||
// self.container through Elem.deinit.
|
// self.container through Elem.deinit.
|
||||||
_ = c.g_object_ref_sink(@ptrCast(gl_area));
|
_ = c.g_object_ref_sink(@ptrCast(overlay));
|
||||||
errdefer c.g_object_unref(@ptrCast(gl_area));
|
errdefer c.g_object_unref(@ptrCast(overlay));
|
||||||
|
|
||||||
// We want the gl area to expand to fill the parent container.
|
// We want the gl area to expand to fill the parent container.
|
||||||
c.gtk_widget_set_hexpand(widget, 1);
|
c.gtk_widget_set_hexpand(widget, 1);
|
||||||
@ -381,6 +391,7 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void {
|
|||||||
self.* = .{
|
self.* = .{
|
||||||
.app = app,
|
.app = app,
|
||||||
.container = .{ .none = {} },
|
.container = .{ .none = {} },
|
||||||
|
.overlay = overlay,
|
||||||
.gl_area = gl_area,
|
.gl_area = gl_area,
|
||||||
.title_text = null,
|
.title_text = null,
|
||||||
.core_surface = undefined,
|
.core_surface = undefined,
|
||||||
@ -488,7 +499,7 @@ pub fn deinit(self: *Surface) void {
|
|||||||
// unref removes the long-held reference to the gl_area and kicks off the
|
// unref removes the long-held reference to the gl_area and kicks off the
|
||||||
// deinit/destroy process for this surface.
|
// deinit/destroy process for this surface.
|
||||||
pub fn unref(self: *Surface) void {
|
pub fn unref(self: *Surface) void {
|
||||||
c.g_object_unref(self.gl_area);
|
c.g_object_unref(self.overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *Surface, alloc: Allocator) void {
|
pub fn destroy(self: *Surface, alloc: Allocator) void {
|
||||||
@ -496,6 +507,10 @@ pub fn destroy(self: *Surface, alloc: Allocator) void {
|
|||||||
alloc.destroy(self);
|
alloc.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn primaryWidget(self: *Surface) *c.GtkWidget {
|
||||||
|
return @ptrCast(@alignCast(self.overlay));
|
||||||
|
}
|
||||||
|
|
||||||
fn render(self: *Surface) !void {
|
fn render(self: *Surface) !void {
|
||||||
try self.core_surface.renderer.drawFrame(self);
|
try self.core_surface.renderer.drawFrame(self);
|
||||||
}
|
}
|
||||||
@ -879,10 +894,34 @@ pub fn setMouseVisibility(self: *Surface, visible: bool) void {
|
|||||||
c.gtk_widget_set_cursor(@ptrCast(self.gl_area), self.app.cursor_none);
|
c.gtk_widget_set_cursor(@ptrCast(self.gl_area), self.app.cursor_none);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouseOverLink(self: *Surface, uri: ?[]const u8) void {
|
pub fn mouseOverLink(self: *Surface, uri_: ?[]const u8) void {
|
||||||
// TODO: GTK
|
const uri = uri_ orelse {
|
||||||
_ = self;
|
if (self.url_widget) |widget| {
|
||||||
_ = uri;
|
c.gtk_overlay_remove_overlay(@ptrCast(self.overlay), widget);
|
||||||
|
self.url_widget = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
// We need a null-terminated string
|
||||||
|
const alloc = self.app.core_app.alloc;
|
||||||
|
const uriZ = alloc.dupeZ(u8, uri) catch return;
|
||||||
|
defer alloc.free(uriZ);
|
||||||
|
|
||||||
|
// If we have a URL widget already just change the text.
|
||||||
|
if (self.url_widget) |widget| {
|
||||||
|
c.gtk_label_set_text(@ptrCast(widget), uriZ.ptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the widget
|
||||||
|
const label = c.gtk_label_new(uriZ.ptr);
|
||||||
|
c.gtk_widget_set_halign(label, c.GTK_ALIGN_START);
|
||||||
|
c.gtk_widget_set_valign(label, c.GTK_ALIGN_END);
|
||||||
|
c.gtk_widget_set_margin_bottom(label, 2);
|
||||||
|
c.gtk_overlay_add_overlay(@ptrCast(self.overlay), label);
|
||||||
|
self.url_widget = label;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clipboardRequest(
|
pub fn clipboardRequest(
|
||||||
|
@ -104,8 +104,7 @@ pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void {
|
|||||||
self.elem = .{ .surface = surface };
|
self.elem = .{ .surface = surface };
|
||||||
|
|
||||||
// Add Surface to the Tab
|
// Add Surface to the Tab
|
||||||
const gl_area_widget = @as(*c.GtkWidget, @ptrCast(surface.gl_area));
|
c.gtk_box_append(self.box, surface.primaryWidget());
|
||||||
c.gtk_box_append(self.box, gl_area_widget);
|
|
||||||
|
|
||||||
// Add the notebook page (create tab).
|
// Add the notebook page (create tab).
|
||||||
const parent_page_idx = switch (window.app.config.@"window-new-tab-position") {
|
const parent_page_idx = switch (window.app.config.@"window-new-tab-position") {
|
||||||
|
Reference in New Issue
Block a user