Bug 1456451 - [CSD] Update toplevel GdkWindow property when it's recreated at nsWindow::SetDrawsInTitlebar(). r=jhorak, a=RyanVM
authorMartin Stransky <stransky@redhat.com>
Thu, 10 May 2018 16:38:17 +0200
changeset 473494 982e4bff688adbae25274a9f0aca6f288f3fa8e5
parent 473493 1f8717a7f5b16f1c77ae46839df6c10ef261baeb
child 473495 d44d4c2a178ffb0af2860fa6a0b7c2640828260d
push id1728
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:12:27 +0000
treeherdermozilla-release@c296fde26f5f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjhorak, RyanVM
bugs1456451
milestone61.0
Bug 1456451 - [CSD] Update toplevel GdkWindow property when it's recreated at nsWindow::SetDrawsInTitlebar(). r=jhorak, a=RyanVM Implement SetCompositorHint() which sets _NET_WM_BYPASS_COMPOSITOR GtkWindow property when it's recreated at nsWindow::SetDrawsInTitlebar(). Window role/class is handled by nsWindow::RefreshWindowClass(), it uses stored window class passed to nsWindow::SetWindowClass(). MozReview-Commit-ID: 1JJsK1ZQyvu
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -3885,27 +3885,17 @@ nsWindow::Create(nsIWidget* aParent,
         }
 
 #ifdef MOZ_X11
         // Set window manager hint to keep fullscreen windows composited.
         //
         // If the window were to get unredirected, there could be visible
         // tearing because Gecko does not align its framebuffer updates with
         // vblank.
-        if (mIsX11Display) {
-            gulong value = 2; // Opt out of unredirection
-            GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
-            gdk_property_change(gtk_widget_get_window(mShell),
-                                gdk_atom_intern("_NET_WM_BYPASS_COMPOSITOR", FALSE),
-                                cardinal_atom,
-                                32, // format
-                                GDK_PROP_MODE_REPLACE,
-                                (guchar*)&value,
-                                1);
-        }
+        SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED);
 #endif
     }
         break;
 
     case eWindowType_plugin:
     case eWindowType_plugin_ipc_chrome:
     case eWindowType_plugin_ipc_content:
         MOZ_ASSERT_UNREACHABLE("Unexpected eWindowType_plugin*");
@@ -4109,70 +4099,80 @@ nsWindow::Create(nsIWidget* aParent,
       mSurfaceProvider.Initialize(this);
     }
 #endif
 #endif
     return NS_OK;
 }
 
 void
-nsWindow::SetWindowClass(const nsAString &xulWinType)
-{
-  if (!mShell)
-    return;
-
-  const char *res_class = gdk_get_program_class();
-  if (!res_class)
-    return;
-
-  char *res_name = ToNewCString(xulWinType);
-  if (!res_name)
-    return;
-
-  const char *role = nullptr;
-
-  // Parse res_name into a name and role. Characters other than
-  // [A-Za-z0-9_-] are converted to '_'. Anything after the first
-  // colon is assigned to role; if there's no colon, assign the
-  // whole thing to both role and res_name.
-  for (char *c = res_name; *c; c++) {
-    if (':' == *c) {
-      *c = 0;
-      role = c + 1;
-    }
-    else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
-      *c = '_';
-  }
-  res_name[0] = toupper(res_name[0]);
-  if (!role) role = res_name;
-
-  GdkWindow* gdkWindow = gtk_widget_get_window(mShell);
-  gdk_window_set_role(gdkWindow, role);
+nsWindow::RefreshWindowClass(void)
+{
+    if (mGtkWindowTypeName.IsEmpty() || mGtkWindowRoleName.IsEmpty())
+        return;
+
+    GdkWindow* gdkWindow = gtk_widget_get_window(mShell);
+    gdk_window_set_role(gdkWindow, mGtkWindowRoleName.get());
 
 #ifdef MOZ_X11
-  if (mIsX11Display) {
-      XClassHint *class_hint = XAllocClassHint();
-      if (!class_hint) {
-        free(res_name);
-        return;
+    if (mIsX11Display) {
+        XClassHint *class_hint = XAllocClassHint();
+        if (!class_hint) {
+          return;
+        }
+        const char *res_class = gdk_get_program_class();
+        if (!res_class)
+          return;
+
+        class_hint->res_name = const_cast<char*>(mGtkWindowTypeName.get());
+        class_hint->res_class = const_cast<char*>(res_class);
+
+        // Can't use gtk_window_set_wmclass() for this; it prints
+        // a warning & refuses to make the change.
+        GdkDisplay *display = gdk_display_get_default();
+        XSetClassHint(GDK_DISPLAY_XDISPLAY(display),
+                      gdk_x11_window_get_xid(gdkWindow),
+                      class_hint);
+        XFree(class_hint);
+    }
+#endif /* MOZ_X11 */
+}
+
+void
+nsWindow::SetWindowClass(const nsAString &xulWinType)
+{
+    if (!mShell)
+      return;
+
+    char *res_name = ToNewCString(xulWinType);
+    if (!res_name)
+      return;
+
+    const char *role = nullptr;
+
+    // Parse res_name into a name and role. Characters other than
+    // [A-Za-z0-9_-] are converted to '_'. Anything after the first
+    // colon is assigned to role; if there's no colon, assign the
+    // whole thing to both role and res_name.
+    for (char *c = res_name; *c; c++) {
+      if (':' == *c) {
+        *c = 0;
+        role = c + 1;
       }
-      class_hint->res_name = res_name;
-      class_hint->res_class = const_cast<char*>(res_class);
-
-      // Can't use gtk_window_set_wmclass() for this; it prints
-      // a warning & refuses to make the change.
-      GdkDisplay *display = gdk_display_get_default();
-      XSetClassHint(GDK_DISPLAY_XDISPLAY(display),
-                    gdk_x11_window_get_xid(gdkWindow),
-                    class_hint);
-      XFree(class_hint);
-  }
-#endif /* MOZ_X11 */
-
-  free(res_name);
+      else if (!isascii(*c) || (!isalnum(*c) && ('_' != *c) && ('-' != *c)))
+        *c = '_';
+    }
+    res_name[0] = toupper(res_name[0]);
+    if (!role) role = res_name;
+
+    mGtkWindowTypeName = res_name;
+    mGtkWindowRoleName = role;
+    free(res_name);
+
+    RefreshWindowClass();
 }
 
 void
 nsWindow::NativeResize()
 {
     if (!AreBoundsSane()) {
         // If someone has set this so that the needs show flag is false
         // and it needs to be hidden, update the flag and hide the
@@ -6726,16 +6726,20 @@ nsWindow::SetDrawsInTitlebar(bool aState
         gtk_widget_reparent(GTK_WIDGET(mContainer), GTK_WIDGET(mShell));
         mNeedsShow = true;
         NativeResize();
 
         // Label mShell toplevel window so property_notify_event_cb callback
         // can find its way home.
         g_object_set_data(G_OBJECT(gtk_widget_get_window(mShell)),
                           "nsWindow", this);
+#ifdef MOZ_X11
+        SetCompositorHint(GTK_WIDGET_COMPOSIDED_ENABLED);
+#endif
+        RefreshWindowClass();
 
         // When we use system titlebar setup managed by Gtk+ we also get
         // _NET_FRAME_EXTENTS property for our toplevel window so we can't
         // update the client offset it here.
         if (aState) {
             UpdateClientOffsetForCSDWindow();
         }
 
@@ -7207,8 +7211,26 @@ nsWindow::SetProgress(unsigned long prog
 
   progressPercent = MIN(progressPercent, 100);
 
   set_window_hint_cardinal(GDK_WINDOW_XID(gtk_widget_get_window(mShell)),
                            PROGRESS_HINT,
                            progressPercent);
 #endif // MOZ_X11
 }
+
+#ifdef MOZ_X11
+void
+nsWindow::SetCompositorHint(WindowComposeRequest aState)
+{
+    if (mIsX11Display) {
+        gulong value = aState;
+        GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
+        gdk_property_change(gtk_widget_get_window(mShell),
+                            gdk_atom_intern("_NET_WM_BYPASS_COMPOSITOR", FALSE),
+                            cardinal_atom,
+                            32, // format
+                            GDK_PROP_MODE_REPLACE,
+                            (guchar*)&value,
+                            1);
+    }
+}
+#endif
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -476,16 +476,28 @@ private:
                                    GdkWindow** aWindow, gint* aButton,
                                    gint* aRootX, gint* aRootY);
     void               ClearCachedResources();
     nsIWidgetListener* GetListener();
     bool               IsComposited() const;
 
     void               UpdateClientOffsetForCSDWindow();
 
+#ifdef MOZ_X11
+    typedef enum { GTK_WIDGET_COMPOSIDED_DEFAULT = 0,
+                   GTK_WIDGET_COMPOSIDED_DISABLED = 1,
+                   GTK_WIDGET_COMPOSIDED_ENABLED = 2
+    } WindowComposeRequest;
+
+    void                SetCompositorHint(WindowComposeRequest aState);
+#endif
+    nsCString           mGtkWindowTypeName;
+    nsCString           mGtkWindowRoleName;
+    void                RefreshWindowClass();
+
     GtkWidget          *mShell;
     MozContainer       *mContainer;
     GdkWindow          *mGdkWindow;
     PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate;
 
 
     uint32_t            mHasMappedToplevel : 1,
                         mIsFullyObscured : 1,