bug 1199602 emit resume-events on GdkFrameClock if flush/resume not balanced at dispose r?acomminos draft
authorKarl Tomlinson <karlt+@karlt.net>
Fri, 26 Feb 2016 11:19:24 +1300
changeset 334709 fa8d70fa75158881af880749ecfd1d9837ed8dce
parent 334708 9b087c08a228dcfbd10ff7219106293e35eb3518
child 514975 86408bc2be558808f82bd729ff306e3e8d855156
push id11615
push userktomlinson@mozilla.com
push dateThu, 25 Feb 2016 22:28:06 +0000
reviewersacomminos
bugs1199602, 742636
milestone47.0a1
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. MozReview-Commit-ID: JZ3kVlXFh0R
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);