From c378d935f34b26269719489d8fb04d3c410c3a72 Mon Sep 17 00:00:00 2001 From: "Ian M. Jones" Date: Fri, 4 Mar 2022 06:50:43 +0000 Subject: [PATCH] Fix linux unexpected signal errors (#1200) * Fix fatal error on otherwise clean exit. * Fix race condition while setting title during window creation. * Fix unexpected signal error when clicking webview should initiate a drag window operation. * Ensure ExecuteOnMainThread callbacks are removed from the event source list on completion. * Ensure all ExecuteOnMainThread callbacks use the expected return value on completion. * Fix potential memory leak when exiting early from startDrag. --- v2/internal/frontend/desktop/linux/window.go | 83 ++++++++++++++------ 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/v2/internal/frontend/desktop/linux/window.go b/v2/internal/frontend/desktop/linux/window.go index 2f9133f6b..fad07ea05 100644 --- a/v2/internal/frontend/desktop/linux/window.go +++ b/v2/internal/frontend/desktop/linux/window.go @@ -57,8 +57,7 @@ GdkRectangle getCurrentMonitorGeometry(GtkWindow *window) { return result; } -void Center(gpointer data) -{ +gboolean Center(gpointer data) { GtkWindow *window = (GtkWindow*)data; // Get the geometry of the monitor @@ -73,6 +72,8 @@ void Center(gpointer data) // Place the window at the center of the monitor gtk_window_move(window, newX, newY); + + return G_SOURCE_REMOVE; } int IsFullscreen(GtkWidget *widget) { @@ -196,16 +197,20 @@ typedef struct DragOptions { GtkWindow* mainwindow; } DragOptions; -static void startDrag(gpointer data) -{ +static gboolean startDrag(gpointer data) { DragOptions* options = (DragOptions*)data; - // Ignore non-toplevel widgets - GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(options->webview)); - if (!GTK_IS_WINDOW(window)) return; + // Ignore non-toplevel widgets + GtkWidget *window = gtk_widget_get_toplevel(GTK_WIDGET(options->webview)); + if (!GTK_IS_WINDOW(window)) { + free(data); + return G_SOURCE_REMOVE; + } - gtk_window_begin_move_drag(options->mainwindow, 1, xroot, yroot, dragTime); + gtk_window_begin_move_drag(options->mainwindow, 1, xroot, yroot, dragTime); free(data); + + return G_SOURCE_REMOVE; } static void StartDrag(void *webview, GtkWindow* mainwindow) { @@ -220,7 +225,7 @@ typedef struct JSCallback { char* script; } JSCallback; -int executeJS(gpointer data) { +gboolean executeJS(gpointer data) { struct JSCallback *js = data; webkit_web_view_run_javascript(js->webview, js->script, NULL, NULL, NULL); free(js->script); @@ -236,7 +241,7 @@ typedef struct MessageDialogOptions { int messageType; } MessageDialogOptions; -void messageDialog(gpointer data) { +gboolean messageDialog(gpointer data) { GtkDialogFlags flags; GtkMessageType messageType; @@ -278,6 +283,8 @@ void messageDialog(gpointer data) { gtk_widget_destroy(dialog); free(options->title); free(options->message); + + return G_SOURCE_REMOVE; } void extern processOpenFileResult(void*); @@ -302,7 +309,7 @@ void freeFileFilterArray(GtkFileFilter** filters) { free(filters); } -int opendialog(gpointer data) { +gboolean opendialog(gpointer data) { struct OpenFileDialogOptions *options = data; char *label = "_Open"; if (options->action == GTK_FILE_CHOOSER_ACTION_SAVE) { @@ -407,10 +414,12 @@ typedef struct RGBAOptions { void *webview; } RGBAOptions; -void setRGBA(gpointer* data) { +gboolean setRGBA(gpointer* data) { RGBAOptions* options = (RGBAOptions*)data; GdkRGBA colour = {options->r / 255.0, options->g / 255.0, options->b / 255.0, options->a / 255.0}; webkit_web_view_set_background_color(WEBKIT_WEB_VIEW(options->webview), &colour); + + return G_SOURCE_REMOVE; } typedef struct SetTitleArgs { @@ -418,11 +427,13 @@ typedef struct SetTitleArgs { char* title; } SetTitleArgs; -void setTitle(gpointer data) { +gboolean setTitle(gpointer data) { SetTitleArgs* args = (SetTitleArgs*)data; gtk_window_set_title(args->window, args->title); free((void*)args->title); free((void*)data); + + return G_SOURCE_REMOVE; } void SetTitle(GtkWindow* window, char* title) { @@ -438,10 +449,12 @@ typedef struct SetPositionArgs { void* window; } SetPositionArgs; -void setPosition(gpointer data) { +gboolean setPosition(gpointer data) { SetPositionArgs* args = (SetPositionArgs*)data; gtk_window_move((GtkWindow*)args->window, args->x, args->y); free(args); + + return G_SOURCE_REMOVE; } void SetPosition(void* window, int x, int y) { @@ -453,28 +466,52 @@ void SetPosition(void* window, int x, int y) { ExecuteOnMainThread(setPosition, (gpointer)args); } -void Show(gpointer data) { +gboolean Show(gpointer data) { gtk_widget_show((GtkWidget*)data); + + return G_SOURCE_REMOVE; } -void Hide(gpointer data) { +gboolean Hide(gpointer data) { gtk_widget_hide((GtkWidget*)data); + + return G_SOURCE_REMOVE; } -void Maximise(gpointer data) { +gboolean Maximise(gpointer data) { gtk_window_maximize((GtkWindow*)data); + + return G_SOURCE_REMOVE; } -void UnMaximise(gpointer data) { +gboolean UnMaximise(gpointer data) { gtk_window_unmaximize((GtkWindow*)data); + + return G_SOURCE_REMOVE; } -void Minimise(gpointer data) { +gboolean Minimise(gpointer data) { gtk_window_iconify((GtkWindow*)data); + + return G_SOURCE_REMOVE; } -void UnMinimise(gpointer data) { +gboolean UnMinimise(gpointer data) { gtk_window_present((GtkWindow*)data); + + return G_SOURCE_REMOVE; +} + +gboolean Fullscreen(gpointer data) { + gtk_window_fullscreen((GtkWindow*)data); + + return G_SOURCE_REMOVE; +} + +gboolean UnFullscreen(gpointer data) { + gtk_window_unfullscreen((GtkWindow*)data); + + return G_SOURCE_REMOVE; } bool disableContextMenu(GtkWindow* window) { @@ -596,21 +633,21 @@ func (w *Window) cWebKitUserContentManager() *C.WebKitUserContentManager { func (w *Window) Fullscreen() { C.SetMinMaxSize(w.asGTKWindow(), C.int(0), C.int(0), C.int(0), C.int(0)) - C.ExecuteOnMainThread(C.gtk_window_fullscreen, C.gpointer(w.asGTKWindow())) + C.ExecuteOnMainThread(C.Fullscreen, C.gpointer(w.asGTKWindow())) } func (w *Window) UnFullscreen() { if !w.IsFullScreen() { return } - C.ExecuteOnMainThread(C.gtk_window_unfullscreen, C.gpointer(w.asGTKWindow())) + C.ExecuteOnMainThread(C.UnFullscreen, C.gpointer(w.asGTKWindow())) w.SetMinSize(w.minWidth, w.minHeight) w.SetMaxSize(w.maxWidth, w.maxHeight) } func (w *Window) Destroy() { - C.g_object_unref(C.gpointer(w.gtkWindow)) C.gtk_widget_destroy(w.asGTKWidget()) + C.g_object_unref(C.gpointer(w.gtkWindow)) } func (w *Window) Close() {