From ce4cdce4b8b333193d342a977be5edff5587ba5a Mon Sep 17 00:00:00 2001 From: Andrew Comminos Date: Mon, 13 Jul 2015 08:58:00 -0400 Subject: [PATCH] Bug 1178799 - Filter X11 SelectionRequest events with an invalid requestor on GTK3. r=karlt --HG-- extra : rebase_source : cd7370af74195ad1c7736c8148d537e3a47bd4d1 --- widget/gtk/compat/gdk/gdkx.h | 8 ++++++++ widget/gtk/mozgtk/mozgtk.c | 1 + widget/gtk/nsClipboard.cpp | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/widget/gtk/compat/gdk/gdkx.h b/widget/gtk/compat/gdk/gdkx.h index dc9d296360a8..5d59720d2f91 100644 --- a/widget/gtk/compat/gdk/gdkx.h +++ b/widget/gtk/compat/gdk/gdkx.h @@ -5,12 +5,20 @@ #ifndef GDKX_WRAPPER_H #define GDKX_WRAPPER_H +#define gdk_x11_window_foreign_new_for_display gdk_x11_window_foreign_new_for_display_ #define gdk_x11_window_lookup_for_display gdk_x11_window_lookup_for_display_ #define gdk_x11_window_get_xid gdk_x11_window_get_xid_ #include_next +#undef gdk_x11_window_foreign_new_for_display #undef gdk_x11_window_lookup_for_display #undef gdk_x11_window_get_xid +static inline GdkWindow * +gdk_x11_window_foreign_new_for_display(GdkDisplay *display, Window window) +{ + return gdk_window_foreign_new_for_display(display, window); +} + static inline GdkWindow * gdk_x11_window_lookup_for_display(GdkDisplay *display, Window window) { diff --git a/widget/gtk/mozgtk/mozgtk.c b/widget/gtk/mozgtk/mozgtk.c index e42458b49981..697de376cec9 100644 --- a/widget/gtk/mozgtk/mozgtk.c +++ b/widget/gtk/mozgtk/mozgtk.c @@ -123,6 +123,7 @@ STUB(gdk_x11_get_xatom_by_name) STUB(gdk_x11_lookup_xdisplay) STUB(gdk_x11_screen_get_xscreen) STUB(gdk_x11_visual_get_xvisual) +STUB(gdk_x11_window_foreign_new_for_display) STUB(gdk_x11_window_lookup_for_display) STUB(gdk_x11_window_set_user_time) STUB(gdk_x11_xatom_to_atom) diff --git a/widget/gtk/nsClipboard.cpp b/widget/gtk/nsClipboard.cpp index a78ae435865f..dc2f402dba63 100644 --- a/widget/gtk/nsClipboard.cpp +++ b/widget/gtk/nsClipboard.cpp @@ -72,6 +72,11 @@ wait_for_contents (GtkClipboard *clipboard, GdkAtom target); static gchar * wait_for_text (GtkClipboard *clipboard); +static GdkFilterReturn +selection_request_filter (GdkXEvent *gdk_xevent, + GdkEvent *event, + gpointer data); + nsClipboard::nsClipboard() { } @@ -99,6 +104,13 @@ nsClipboard::Init(void) os->AddObserver(this, "quit-application", false); + // A custom event filter to workaround attempting to dereference a null + // selection requestor in GTK3 versions before 3.11.3. See bug 1178799. +#if (MOZ_WIDGET_GTK == 3) && defined(MOZ_X11) + if (gtk_check_version(3, 11, 3)) + gdk_window_add_filter(nullptr, selection_request_filter, nullptr); +#endif + return NS_OK; } @@ -108,6 +120,7 @@ nsClipboard::Observe(nsISupports *aSubject, const char *aTopic, const char16_t * if (strcmp(aTopic, "quit-application") == 0) { // application is going to quit, save clipboard content Store(); + gdk_window_remove_filter(nullptr, selection_request_filter, nullptr); } return NS_OK; } @@ -1013,3 +1026,26 @@ wait_for_text(GtkClipboard *clipboard) gtk_clipboard_request_text(clipboard, clipboard_text_received, context.get()); return static_cast(context->Wait()); } + +static GdkFilterReturn +selection_request_filter(GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) +{ + XEvent *xevent = static_cast(gdk_xevent); + if (xevent->xany.type == SelectionRequest) { + if (xevent->xselectionrequest.requestor == None) + return GDK_FILTER_REMOVE; + + GdkDisplay *display = gdk_x11_lookup_xdisplay( + xevent->xselectionrequest.display); + if (!display) + return GDK_FILTER_REMOVE; + + GdkWindow *window = gdk_x11_window_foreign_new_for_display(display, + xevent->xselectionrequest.requestor); + if (!window) + return GDK_FILTER_REMOVE; + + g_object_unref(window); + } + return GDK_FILTER_CONTINUE; +}