gtk: close surface works

This commit is contained in:
Mitchell Hashimoto
2023-02-24 17:50:20 -08:00
parent a1a754530f
commit c80270ff50

View File

@ -133,11 +133,7 @@ pub const App = struct {
/// Close the given surface. /// Close the given surface.
pub fn closeSurface(self: *App, surface: *Surface) void { pub fn closeSurface(self: *App, surface: *Surface) void {
_ = self; _ = self;
_ = surface; surface.close();
// This shouldn't be called because we should be working within
// the GTK lifecycle and we can't just deallocate surfaces here.
@panic("This should not be called with GTK.");
} }
pub fn redrawSurface(self: *App, surface: *Surface) void { pub fn redrawSurface(self: *App, surface: *Surface) void {
@ -278,6 +274,7 @@ const Window = struct {
const page = c.gtk_notebook_get_page(self.notebook, gl_area) orelse const page = c.gtk_notebook_get_page(self.notebook, gl_area) orelse
return error.GtkNotebookPageNotFound; return error.GtkNotebookPageNotFound;
c.g_object_set_data(@ptrCast(*c.GObject, label_close), TAB_CLOSE_PAGE, page); c.g_object_set_data(@ptrCast(*c.GObject, label_close), TAB_CLOSE_PAGE, page);
c.g_object_set_data(@ptrCast(*c.GObject, gl_area), TAB_CLOSE_PAGE, page);
// Switch to the new tab // Switch to the new tab
c.gtk_notebook_set_current_page(self.notebook, page_idx); c.gtk_notebook_set_current_page(self.notebook, page_idx);
@ -288,22 +285,10 @@ const Window = struct {
_ = c.gtk_widget_grab_focus(widget); _ = c.gtk_widget_grab_focus(widget);
} }
fn gtkTabAddClick(_: *c.GtkButton, ud: ?*anyopaque) callconv(.C) void { /// Close the tab for the given notebook page. This will automatically
const self = userdataSelf(ud.?); /// handle closing the window if there are no more tabs.
self.newTab() catch |err| { fn closeTab(self: *Window, page: *c.GtkNotebookPage) void {
log.warn("error adding new tab: {}", .{err}); // Get the page index from the page
return;
};
}
fn gtkTabCloseClick(btn: *c.GtkButton, ud: ?*anyopaque) callconv(.C) void {
// Get the notebook page
const page = @ptrCast(*c.GtkNotebookPage, @alignCast(
@alignOf(c.GtkNotebookPage),
c.g_object_get_data(@ptrCast(*c.GObject, btn), TAB_CLOSE_PAGE),
));
// Get the page index
var value: c.GValue = std.mem.zeroes(c.GValue); var value: c.GValue = std.mem.zeroes(c.GValue);
defer c.g_value_unset(&value); defer c.g_value_unset(&value);
_ = c.g_value_init(&value, c.G_TYPE_INT); _ = c.g_value_init(&value, c.G_TYPE_INT);
@ -313,8 +298,8 @@ const Window = struct {
&value, &value,
); );
// Remove the page
const page_idx = c.g_value_get_int(&value); const page_idx = c.g_value_get_int(&value);
const self = userdataSelf(ud.?);
c.gtk_notebook_remove_page(self.notebook, page_idx); c.gtk_notebook_remove_page(self.notebook, page_idx);
const remaining = c.gtk_notebook_get_n_pages(self.notebook); const remaining = c.gtk_notebook_get_n_pages(self.notebook);
@ -329,6 +314,25 @@ const Window = struct {
} }
} }
/// Close the surface. This surface must be definitely part of this window.
fn closeSurface(self: *Window, surface: *Surface) void {
assert(surface.window == self);
self.closeTab(getNotebookPage(@ptrCast(*c.GObject, surface.gl_area)) orelse return);
}
fn gtkTabAddClick(_: *c.GtkButton, ud: ?*anyopaque) callconv(.C) void {
const self = userdataSelf(ud.?);
self.newTab() catch |err| {
log.warn("error adding new tab: {}", .{err});
return;
};
}
fn gtkTabCloseClick(btn: *c.GtkButton, ud: ?*anyopaque) callconv(.C) void {
const self = userdataSelf(ud.?);
self.closeTab(getNotebookPage(@ptrCast(*c.GObject, btn)) orelse return);
}
/// "destroy" signal for the window /// "destroy" signal for the window
fn gtkDestroy(v: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) void { fn gtkDestroy(v: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) void {
_ = v; _ = v;
@ -340,6 +344,15 @@ const Window = struct {
alloc.destroy(self); alloc.destroy(self);
} }
/// Get the GtkNotebookPage for the given object. You must be sure the
/// object has the notebook page property set.
fn getNotebookPage(obj: *c.GObject) ?*c.GtkNotebookPage {
return @ptrCast(*c.GtkNotebookPage, @alignCast(
@alignOf(c.GtkNotebookPage),
c.g_object_get_data(obj, TAB_CLOSE_PAGE) orelse return null,
));
}
fn userdataSelf(ud: *anyopaque) *Window { fn userdataSelf(ud: *anyopaque) *Window {
return @ptrCast(*Window, @alignCast(@alignOf(Window), ud)); return @ptrCast(*Window, @alignCast(@alignOf(Window), ud));
} }
@ -532,6 +545,11 @@ pub const Surface = struct {
c.gtk_gl_area_queue_render(self.gl_area); c.gtk_gl_area_queue_render(self.gl_area);
} }
/// Close this surface.
fn close(self: *Surface) void {
self.window.closeSurface(self);
}
pub fn setShouldClose(self: *Surface) void { pub fn setShouldClose(self: *Surface) void {
_ = self; _ = self;
} }