bug 1199602 emit resume-events on GdkFrameClock if flush/resume not balanced at dispose r=acomminos
authorKarl Tomlinson <karlt+@karlt.net>
Fri, 26 Feb 2016 11:19:24 +1300
changeset 321993 f2f4c8ce77a3c6415ed55740be32dc75187eaaf0
parent 321992 307fa388360994c5515511320df3f2cd6085f3b0
child 321994 e7e8a495ded43f7ef0bf8e9dedc58ddc6c47c82c
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersacomminos
bugs1199602, 742636
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1199602 emit resume-events on GdkFrameClock if flush/resume not balanced at dispose r=acomminos Fixes https://bugzilla.gnome.org/show_bug.cgi?id=742636 in affected GDK versions.
widget/gtk/nsAppShell.cpp
--- a/widget/gtk/nsAppShell.cpp
+++ b/widget/gtk/nsAppShell.cpp
@@ -58,16 +58,56 @@ wrap_gtk_window_check_resize(GtkContaine
     }
 
     sReal_gtk_window_check_resize(container);
 
     if (gdk_window) {
         g_object_unref(gdk_window);
     }
 }
+
+// Emit resume-events on GdkFrameClock if flush-events has not been
+// balanced by resume-events at dispose.
+// For https://bugzilla.gnome.org/show_bug.cgi?id=742636
+static decltype(GObjectClass::constructed) sRealGdkFrameClockConstructed;
+static decltype(GObjectClass::dispose) sRealGdkFrameClockDispose;
+static GQuark sPendingResumeQuark;
+
+static void
+OnFlushEvents(GObject* clock, gpointer)
+{
+    g_object_set_qdata(clock, sPendingResumeQuark, GUINT_TO_POINTER(1));
+}
+
+static void
+OnResumeEvents(GObject* clock, gpointer)
+{
+    g_object_set_qdata(clock, sPendingResumeQuark, nullptr);
+}
+
+static void
+WrapGdkFrameClockConstructed(GObject* object)
+{
+    sRealGdkFrameClockConstructed(object);
+
+    g_signal_connect(object, "flush-events",
+                     G_CALLBACK(OnFlushEvents), nullptr);
+    g_signal_connect(object, "resume-events",
+                     G_CALLBACK(OnResumeEvents), nullptr);
+}
+
+static void
+WrapGdkFrameClockDispose(GObject* object)
+{
+    if (g_object_get_qdata(object, sPendingResumeQuark)) {
+        g_signal_emit_by_name(object, "resume-events");
+    }
+
+    sRealGdkFrameClockDispose(object);
+}
 #endif
 
 /*static*/ gboolean
 nsAppShell::EventProcessorCallback(GIOChannel *source, 
                                    GIOCondition condition,
                                    gpointer data)
 {
     nsAppShell *self = static_cast<nsAppShell *>(data);
@@ -130,16 +170,34 @@ nsAppShell::Init()
         // GtkWindow is a static class and so will leak anyway but this ref
         // makes sure it isn't recreated.
         gpointer gtk_plug_class = g_type_class_ref(GTK_TYPE_WINDOW);
         auto check_resize = &GTK_CONTAINER_CLASS(gtk_plug_class)->check_resize;
         sReal_gtk_window_check_resize = *check_resize;
         *check_resize = wrap_gtk_window_check_resize;
     }
 
+    if (!sPendingResumeQuark &&
+        gtk_check_version(3,14,7) != nullptr) { // GTK 3.0 to GTK 3.14.7.
+        // GTK 3.8 - 3.14 registered this type when creating the frame clock
+        // for the root window of the display when the display was opened.
+        GType gdkFrameClockIdleType = g_type_from_name("GdkFrameClockIdle");
+        if (gdkFrameClockIdleType) { // not in versions prior to 3.8
+            sPendingResumeQuark = g_quark_from_string("moz-resume-is-pending");
+            auto gdk_frame_clock_idle_class =
+                G_OBJECT_CLASS(g_type_class_peek_static(gdkFrameClockIdleType));
+            auto constructed = &gdk_frame_clock_idle_class->constructed;
+            sRealGdkFrameClockConstructed = *constructed;
+            *constructed = WrapGdkFrameClockConstructed;
+            auto dispose = &gdk_frame_clock_idle_class->dispose;
+            sRealGdkFrameClockDispose = *dispose;
+            *dispose = WrapGdkFrameClockDispose;
+        }
+    }
+
     // Workaround for bug 1209659 which is fixed by Gtk3.20
     if (gtk_check_version(3, 20, 0) != nullptr)
         unsetenv("GTK_CSD");
 #endif
 
     if (PR_GetEnv("MOZ_DEBUG_PAINTS"))
         gdk_window_set_debug_updates(TRUE);