Bug 1456451 - [CSD] Update toplevel GdkWindow property when it's recreated at nsWindow::SetDrawsInTitlebar(), r=jhorak
authorMartin Stransky <stransky@redhat.com>
Thu, 10 May 2018 16:38:17 +0200
changeset 474772 b44a1b57b3012a237f0da3dcbbf2ceb103207b6e
parent 474765 3985ccc415e92eb0be073e7a6bba94e6751bcfc6
child 474773 02f1065a7bea5bff4cb583b0566422a2d849b317
push id1757
push userffxbld-merge
push dateFri, 24 Aug 2018 17:02:43 +0000
treeherdermozilla-release@736023aebdb1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjhorak
bugs1456451
milestone62.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 1456451 - [CSD] Update toplevel GdkWindow property when it's recreated at nsWindow::SetDrawsInTitlebar(), r=jhorak 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,