From f1547465cc227f63aa1038da59b715af41b3fa58 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 1 Nov 2023 22:38:22 -0700 Subject: [PATCH] apprt/gtk: new surface options down to just a couple --- src/apprt/gtk/Surface.zig | 68 ++++++++++++++++++++++++--------------- src/apprt/gtk/Tab.zig | 27 +++------------- 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index ed485d06b..40167d1e1 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -4,6 +4,7 @@ const Surface = @This(); const std = @import("std"); +const Allocator = std.mem.Allocator; const configpkg = @import("../../config.zig"); const apprt = @import("../../apprt.zig"); const font = @import("../../font/main.zig"); @@ -28,21 +29,12 @@ const log = std.log.scoped(.gtk_surface); pub const opengl_single_threaded_draw = true; pub const Options = struct { + /// The parent surface to inherit settings such as font size, working + /// directory, etc. from. + parent2: ?*CoreSurface = null, + /// The parent this surface is created under. parent: Parent, - - /// The GL area that this surface should draw to. - gl_area: *c.GtkGLArea, - - /// A font size to set on the surface once it is initialized. - font_size: ?font.face.DesiredSize = null, - - /// True if this surface has a parent. This is a bit of a hack currently - /// to work around newConfig unconditinally inheriting the working - /// directory. The proper long term fix is to have the working directory - /// inherited upstream likely at the point where this field would be set, - /// then remove this field. - parentSurface: bool = false, }; /// The container that this surface is directly attached to. @@ -129,12 +121,24 @@ im_composing: bool = false, im_buf: [128]u8 = undefined, im_len: u7 = 0, +pub fn create(alloc: Allocator, app: *App, opts: Options) !*Surface { + var surface = try alloc.create(Surface); + errdefer alloc.destroy(surface); + try surface.init(app, opts); + return surface; +} + pub fn init(self: *Surface, app: *App, opts: Options) !void { - const widget = @as(*c.GtkWidget, @ptrCast(opts.gl_area)); - c.gtk_gl_area_set_required_version(opts.gl_area, 3, 3); - c.gtk_gl_area_set_has_stencil_buffer(opts.gl_area, 0); - c.gtk_gl_area_set_has_depth_buffer(opts.gl_area, 0); - c.gtk_gl_area_set_use_es(opts.gl_area, 0); + const widget: *c.GtkWidget = c.gtk_gl_area_new(); + const gl_area: *c.GtkGLArea = @ptrCast(widget); + c.gtk_widget_set_hexpand(widget, 1); + c.gtk_widget_set_vexpand(widget, 1); + + c.gtk_widget_set_cursor_from_name(@ptrCast(gl_area), "text"); + c.gtk_gl_area_set_required_version(gl_area, 3, 3); + c.gtk_gl_area_set_has_stencil_buffer(gl_area, 0); + c.gtk_gl_area_set_has_depth_buffer(gl_area, 0); + c.gtk_gl_area_set_use_es(gl_area, 0); // Key event controller will tell us about raw keypress events. const ec_key = c.gtk_event_controller_key_new(); @@ -184,17 +188,24 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void { c.gtk_widget_set_focusable(widget, 1); c.gtk_widget_set_focus_on_click(widget, 1); + // Inherit the parent's font size if we have a parent. + const font_size: ?font.face.DesiredSize = font_size: { + if (!app.config.@"window-inherit-font-size") break :font_size null; + const parent = opts.parent2 orelse break :font_size null; + break :font_size parent.font_size; + }; + // Build our result self.* = .{ .app = app, .container = .{ .none = {} }, .parent = opts.parent, - .gl_area = opts.gl_area, + .gl_area = gl_area, .title_text_buf = undefined, .title_text_buf_len = 0, .core_surface = undefined, - .font_size = opts.font_size, - .parentSurface = opts.parentSurface, + .font_size = font_size, + .parentSurface = opts.parent2 != null, .size = .{ .width = 800, .height = 600 }, .cursor_pos = .{ .x = 0, .y = 0 }, .im_context = im_context, @@ -205,11 +216,11 @@ pub fn init(self: *Surface, app: *App, opts: Options) !void { try self.setMouseShape(.text); // GL events - _ = c.g_signal_connect_data(opts.gl_area, "realize", c.G_CALLBACK(>kRealize), self, null, c.G_CONNECT_DEFAULT); - _ = c.g_signal_connect_data(opts.gl_area, "unrealize", c.G_CALLBACK(>kUnrealize), self, null, c.G_CONNECT_DEFAULT); - _ = c.g_signal_connect_data(opts.gl_area, "destroy", c.G_CALLBACK(>kDestroy), self, null, c.G_CONNECT_DEFAULT); - _ = c.g_signal_connect_data(opts.gl_area, "render", c.G_CALLBACK(>kRender), self, null, c.G_CONNECT_DEFAULT); - _ = c.g_signal_connect_data(opts.gl_area, "resize", c.G_CALLBACK(>kResize), self, null, c.G_CONNECT_DEFAULT); + _ = c.g_signal_connect_data(gl_area, "realize", c.G_CALLBACK(>kRealize), self, null, c.G_CONNECT_DEFAULT); + _ = c.g_signal_connect_data(gl_area, "unrealize", c.G_CALLBACK(>kUnrealize), self, null, c.G_CONNECT_DEFAULT); + _ = c.g_signal_connect_data(gl_area, "destroy", c.G_CALLBACK(>kDestroy), self, null, c.G_CONNECT_DEFAULT); + _ = c.g_signal_connect_data(gl_area, "render", c.G_CALLBACK(>kRender), self, null, c.G_CONNECT_DEFAULT); + _ = c.g_signal_connect_data(gl_area, "resize", c.G_CALLBACK(>kResize), self, null, c.G_CONNECT_DEFAULT); _ = c.g_signal_connect_data(ec_key_press, "key-pressed", c.G_CALLBACK(>kKeyPressed), self, null, c.G_CONNECT_DEFAULT); _ = c.g_signal_connect_data(ec_key_press, "key-released", c.G_CALLBACK(>kKeyReleased), self, null, c.G_CONNECT_DEFAULT); @@ -267,6 +278,11 @@ fn realize(self: *Surface) !void { self.realized = true; } +pub fn destroy(self: *Surface, alloc: Allocator) void { + self.deinit(); + alloc.free(self); +} + pub fn deinit(self: *Surface) void { // We don't allocate anything if we aren't realized. if (!self.realized) return; diff --git a/src/apprt/gtk/Tab.zig b/src/apprt/gtk/Tab.zig index a16f9f061..b1abbfbf2 100644 --- a/src/apprt/gtk/Tab.zig +++ b/src/apprt/gtk/Tab.zig @@ -148,33 +148,14 @@ pub fn deinit(self: *Tab) void { /// Allocates and initializes a new Surface, but doesn't add it to the Tab yet. /// Can also be added to a Paned. pub fn newSurface(self: *Tab, parent_: ?*CoreSurface) !*Surface { - // Grab a surface allocation we'll need it later. - var surface = try self.window.app.core_app.alloc.create(Surface); - errdefer self.window.app.core_app.alloc.destroy(surface); - - // Inherit the parent's font size if we are configured to. - const font_size: ?font.face.DesiredSize = font_size: { - if (!self.window.app.config.@"window-inherit-font-size") break :font_size null; - const parent = parent_ orelse break :font_size null; - break :font_size parent.font_size; - }; - - // Initialize the GtkGLArea and attach it to our surface. - // The surface starts in the "unrealized" state because we have to - // wait for the "realize" callback from GTK to know that the OpenGL - // context is ready. See Surface docs for more info. - const gl_area = c.gtk_gl_area_new(); - c.gtk_widget_set_hexpand(gl_area, 1); - c.gtk_widget_set_vexpand(gl_area, 1); - - try surface.init(self.window.app, .{ + const alloc = self.window.app.core_app.alloc; + var surface = try Surface.create(alloc, self.window.app, .{ + .parent2 = parent_, .parent = .{ .tab = self, }, - .parentSurface = parent_ != null, - .gl_area = @ptrCast(gl_area), - .font_size = font_size, }); + errdefer surface.destroy(alloc); surface.setContainer(.{ .tab_ = self }); return surface;