Bug 1441873 - [CSD] Remove nsWindow::mIsCSDAvailable and replace with CSDSupportLevel state, r?jhorak draft
authorMartin Stransky <stransky@redhat.com>
Thu, 22 Mar 2018 13:22:38 +0100
changeset 771105 ddb5c619009b09afee0a9e077b0498dcc17b520f
parent 771093 7771df14ea181add1dc4133f0f5559bf620bf976
push id103562
push userstransky@redhat.com
push dateThu, 22 Mar 2018 12:23:09 +0000
reviewersjhorak
bugs1441873
milestone61.0a1
Bug 1441873 - [CSD] Remove nsWindow::mIsCSDAvailable and replace with CSDSupportLevel state, r?jhorak MozReview-Commit-ID: KOiSzNvZfjg
widget/gtk/nsLookAndFeel.cpp
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
--- a/widget/gtk/nsLookAndFeel.cpp
+++ b/widget/gtk/nsLookAndFeel.cpp
@@ -1076,19 +1076,18 @@ nsLookAndFeel::EnsureInit()
                          nullptr);
 
     GetSystemFontInfo(gtk_widget_get_style_context(entry),
                       &mFieldFontName, &mFieldFontStyle);
 
     gtk_widget_destroy(window);
     g_object_unref(labelWidget);
 
-    // Require GTK 3.10 for GtkHeaderBar support and compatible window manager.
-    mCSDAvailable = (gtk_check_version(3, 10, 0) == nullptr &&
-        nsWindow::GetCSDSupportLevel() != nsWindow::CSD_SUPPORT_NONE);
+    mCSDAvailable =
+        nsWindow::GetSystemCSDSupportLevel() != nsWindow::CSD_SUPPORT_NONE;
 
     mCSDCloseButton = false;
     mCSDMinimizeButton = false;
     mCSDMaximizeButton = false;
 
     // We need to initialize whole CSD config explicitly because it's queried
     // as -moz-gtk* media features.
     WidgetNodeType buttonLayout[TOOLBAR_BUTTONS];
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -474,18 +474,18 @@ nsWindow::nsWindow()
 
     mTransparencyBitmapWidth  = 0;
     mTransparencyBitmapHeight = 0;
 
 #if GTK_CHECK_VERSION(3,4,0)
     mLastScrollEventTime = GDK_CURRENT_TIME;
 #endif
     mPendingConfigures = 0;
-    mIsCSDAvailable = false;
-    mIsCSDEnabled = false;
+    mCSDSupportLevel = CSD_SUPPORT_NONE;
+    mDrawInTitlebar = false;
 }
 
 nsWindow::~nsWindow()
 {
     LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this));
 
     delete[] mTransparencyBitmap;
     mTransparencyBitmap = nullptr;
@@ -2814,17 +2814,17 @@ nsWindow::OnButtonReleaseEvent(GdkEventB
     LayoutDeviceIntPoint pos = event.mRefPoint;
 
     nsEventStatus eventStatus = DispatchInputEvent(&event);
 
     bool defaultPrevented = (eventStatus == nsEventStatus_eConsumeNoDefault);
     // Check if mouse position in titlebar and doubleclick happened to
     // trigger restore/maximize.
     if (!defaultPrevented
-             && mIsCSDEnabled
+             && mDrawInTitlebar
              && event.button == WidgetMouseEvent::eLeftButton
              && event.mClickCount == 2
              && mDraggableRegion.Contains(pos.x, pos.y)) {
 
         if (mSizeState == nsSizeMode_Maximized) {
             SetSizeMode(nsSizeMode_Normal);
         } else {
             SetSizeMode(nsSizeMode_Maximized);
@@ -3758,22 +3758,18 @@ nsWindow::Create(nsIWidget* aParent,
             gtk_window_set_wmclass(GTK_WINDOW(mShell), "Toplevel",
                                    gdk_get_program_class());
 
             // each toplevel window gets its own window group
             GtkWindowGroup *group = gtk_window_group_new();
             gtk_window_group_add_window(group, GTK_WINDOW(mShell));
             g_object_unref(group);
 
-            int32_t isCSDAvailable = false;
-            nsresult rv = LookAndFeel::GetInt(LookAndFeel::eIntID_GTKCSDAvailable,
-                                              &isCSDAvailable);
-            if (NS_SUCCEEDED(rv)) {
-               mIsCSDAvailable = isCSDAvailable;
-            }
+            // We enable titlebar rendering for toplevel windows only.
+            mCSDSupportLevel = GetSystemCSDSupportLevel();
         }
 
         // Create a container to hold child windows and child GtkWidgets.
         GtkWidget *container = moz_container_new();
         mContainer = MOZ_CONTAINER(container);
 
         // "csd" style is set when widget is realized so we need to call
         // it explicitly now.
@@ -3788,17 +3784,17 @@ nsWindow::Create(nsIWidget* aParent,
          *    are drawn by Gtk+ to mShell. Content is rendered to mContainer
          *    and we listen to the Gtk+ events on mContainer.
          * 3) We're running on Wayland. All gecko content is rendered
          *    to mContainer and we listen to the Gtk+ events on mContainer.
          */
         GtkStyleContext* style = gtk_widget_get_style_context(mShell);
         drawToContainer =
             !mIsX11Display ||
-            (mIsCSDAvailable && GetCSDSupportLevel() == CSD_SUPPORT_CLIENT) ||
+            (mCSDSupportLevel == CSD_SUPPORT_CLIENT) ||
             gtk_style_context_has_class(style, "csd");
         eventWidget = (drawToContainer) ? container : mShell;
 
         gtk_widget_add_events(eventWidget, kEvents);
         if (drawToContainer)
             gtk_widget_add_events(mShell, GDK_PROPERTY_CHANGE_MASK);
 
         // Prevent GtkWindow from painting a background to avoid flickering.
@@ -6581,90 +6577,91 @@ nsWindow::ClearCachedResources()
             window->ClearCachedResources();
         }
     }
 }
 
 nsresult
 nsWindow::SetNonClientMargins(LayoutDeviceIntMargin &aMargins)
 {
-  SetDrawsInTitlebar(aMargins.top == 0);
-  return NS_OK;
+    SetDrawsInTitlebar(aMargins.top == 0);
+    return NS_OK;
 }
 
 void
 nsWindow::SetDrawsInTitlebar(bool aState)
 {
-  if (!mIsCSDAvailable || aState == mIsCSDEnabled)
-      return;
-
-  if (mShell) {
-      if (GetCSDSupportLevel() == CSD_SUPPORT_SYSTEM) {
-          SetWindowDecoration(aState ? eBorderStyle_border : mBorderStyle);
-      }
-      else {
-          /* Window manager does not support GDK_DECOR_BORDER,
-           * emulate it by CSD.
-           *
-           * gtk_window_set_titlebar() works on unrealized widgets only,
-           * we need to handle mShell carefully here.
-           * When CSD is enabled mGdkWindow is owned by mContainer which is good
-           * as we can't delete our mGdkWindow. To make mShell unrealized while
-           * mContainer is preserved we temporary reparent mContainer to an
-           * invisible GtkWindow.
-           */
-          NativeShow(false);
-
-          // Using GTK_WINDOW_POPUP rather than
-          // GTK_WINDOW_TOPLEVEL in the hope that POPUP results in less
-          // initialization and window manager interaction.
-          GtkWidget* tmpWindow = gtk_window_new(GTK_WINDOW_POPUP);
-          gtk_widget_realize(tmpWindow);
-
-          gtk_widget_reparent(GTK_WIDGET(mContainer), tmpWindow);
-          gtk_widget_unrealize(GTK_WIDGET(mShell));
-
-          // Available as of GTK 3.10+
-          static auto sGtkWindowSetTitlebar = (void (*)(GtkWindow*, GtkWidget*))
-              dlsym(RTLD_DEFAULT, "gtk_window_set_titlebar");
-          MOZ_ASSERT(sGtkWindowSetTitlebar,
-              "Missing gtk_window_set_titlebar(), old Gtk+ library?");
-
-          if (aState) {
-              // Add a hidden titlebar widget to trigger CSD, but disable the default
-              // titlebar.  GtkFixed is a somewhat random choice for a simple unused
-              // widget. gtk_window_set_titlebar() takes ownership of the titlebar
-              // widget.
-              sGtkWindowSetTitlebar(GTK_WINDOW(mShell), gtk_fixed_new());
-          } else {
-              sGtkWindowSetTitlebar(GTK_WINDOW(mShell), nullptr);
-          }
-
-          /* A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=791081
-           * gtk_widget_realize() throws:
-           * "In pixman_region32_init_rect: Invalid rectangle passed"
-           * when mShell has default 1x1 size.
-           */
-          GtkAllocation allocation = {0, 0, 0, 0};
-          gtk_widget_get_preferred_width(GTK_WIDGET(mShell), nullptr,
-                                         &allocation.width);
-          gtk_widget_get_preferred_height(GTK_WIDGET(mShell), nullptr,
-                                          &allocation.height);
-          gtk_widget_size_allocate(GTK_WIDGET(mShell), &allocation);
-
-          gtk_widget_realize(GTK_WIDGET(mShell));
-          gtk_widget_reparent(GTK_WIDGET(mContainer), GTK_WIDGET(mShell));
-          mNeedsShow = true;
-          NativeResize();
-
-          gtk_widget_destroy(tmpWindow);
-      }
-  }
-
-  mIsCSDEnabled = aState;
+    if (!mShell ||
+        mCSDSupportLevel == CSD_SUPPORT_NONE ||
+        aState == mDrawInTitlebar) {
+        return;
+    }
+
+    if (mCSDSupportLevel == CSD_SUPPORT_SYSTEM) {
+        SetWindowDecoration(aState ? eBorderStyle_border : mBorderStyle);
+    }
+    else if (mCSDSupportLevel == CSD_SUPPORT_CLIENT) {
+        /* Window manager does not support GDK_DECOR_BORDER,
+         * emulate it by CSD.
+         *
+         * gtk_window_set_titlebar() works on unrealized widgets only,
+         * we need to handle mShell carefully here.
+         * When CSD is enabled mGdkWindow is owned by mContainer which is good
+         * as we can't delete our mGdkWindow. To make mShell unrealized while
+         * mContainer is preserved we temporary reparent mContainer to an
+         * invisible GtkWindow.
+         */
+        NativeShow(false);
+
+        // Using GTK_WINDOW_POPUP rather than
+        // GTK_WINDOW_TOPLEVEL in the hope that POPUP results in less
+        // initialization and window manager interaction.
+        GtkWidget* tmpWindow = gtk_window_new(GTK_WINDOW_POPUP);
+        gtk_widget_realize(tmpWindow);
+
+        gtk_widget_reparent(GTK_WIDGET(mContainer), tmpWindow);
+        gtk_widget_unrealize(GTK_WIDGET(mShell));
+
+        // Available as of GTK 3.10+
+        static auto sGtkWindowSetTitlebar = (void (*)(GtkWindow*, GtkWidget*))
+            dlsym(RTLD_DEFAULT, "gtk_window_set_titlebar");
+        MOZ_ASSERT(sGtkWindowSetTitlebar,
+            "Missing gtk_window_set_titlebar(), old Gtk+ library?");
+
+        if (aState) {
+            // Add a hidden titlebar widget to trigger CSD, but disable the default
+            // titlebar.  GtkFixed is a somewhat random choice for a simple unused
+            // widget. gtk_window_set_titlebar() takes ownership of the titlebar
+            // widget.
+            sGtkWindowSetTitlebar(GTK_WINDOW(mShell), gtk_fixed_new());
+        } else {
+            sGtkWindowSetTitlebar(GTK_WINDOW(mShell), nullptr);
+        }
+
+        /* A workaround for https://bugzilla.gnome.org/show_bug.cgi?id=791081
+         * gtk_widget_realize() throws:
+         * "In pixman_region32_init_rect: Invalid rectangle passed"
+         * when mShell has default 1x1 size.
+         */
+        GtkAllocation allocation = {0, 0, 0, 0};
+        gtk_widget_get_preferred_width(GTK_WIDGET(mShell), nullptr,
+                                       &allocation.width);
+        gtk_widget_get_preferred_height(GTK_WIDGET(mShell), nullptr,
+                                        &allocation.height);
+        gtk_widget_size_allocate(GTK_WIDGET(mShell), &allocation);
+
+        gtk_widget_realize(GTK_WIDGET(mShell));
+        gtk_widget_reparent(GTK_WIDGET(mContainer), GTK_WIDGET(mShell));
+        mNeedsShow = true;
+        NativeResize();
+
+        gtk_widget_destroy(tmpWindow);
+    }
+
+    mDrawInTitlebar = aState;
 }
 
 gint
 nsWindow::GdkScaleFactor()
 {
 #if (MOZ_WIDGET_GTK >= 3)
     // Available as of GTK 3.10+
     static auto sGdkWindowGetScaleFactorPtr = (gint (*)(GdkWindow*))
@@ -6923,28 +6920,28 @@ nsWindow::SynthesizeNativeTouchPoint(uin
   event.touch.y = DevicePixelsToGdkCoordRoundDown(pointInWindow.y);
 
   gdk_event_put(&event);
 
   return NS_OK;
 }
 #endif
 
-bool
-nsWindow::DoDrawTitlebar() const
-{
-    return mIsCSDEnabled && mSizeState == nsSizeMode_Normal;
-}
-
 nsWindow::CSDSupportLevel
-nsWindow::GetCSDSupportLevel() {
+nsWindow::GetSystemCSDSupportLevel() {
     if (sCSDSupportLevel != CSD_SUPPORT_UNKNOWN) {
         return sCSDSupportLevel;
     }
 
+    // Require GTK 3.10 for GtkHeaderBar support and compatible window manager.
+    if (gtk_check_version(3, 10, 0) != nullptr) {
+        sCSDSupportLevel = CSD_SUPPORT_NONE;
+        return sCSDSupportLevel;
+    }
+
     const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP");
     if (currentDesktop) {
         // GNOME Flashback (fallback)
         if (strstr(currentDesktop, "GNOME-Flashback:GNOME") != nullptr) {
             sCSDSupportLevel = CSD_SUPPORT_CLIENT;
         // gnome-shell
         } else if (strstr(currentDesktop, "GNOME") != nullptr) {
             sCSDSupportLevel = CSD_SUPPORT_SYSTEM;
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -395,28 +395,26 @@ public:
     // From GDK
     int GdkCoordToDevicePixels(gint coord);
     LayoutDeviceIntPoint GdkPointToDevicePixels(GdkPoint point);
     LayoutDeviceIntPoint GdkEventCoordsToDevicePixels(gdouble x, gdouble y);
     LayoutDeviceIntRect GdkRectToDevicePixels(GdkRectangle rect);
 
     virtual bool WidgetTypeSupportsAcceleration() override;
 
-    bool DoDrawTitlebar() const;
-
     typedef enum { CSD_SUPPORT_SYSTEM,    // CSD including shadows
                    CSD_SUPPORT_CLIENT,    // CSD without shadows
                    CSD_SUPPORT_NONE,      // WM does not support CSD at all
                    CSD_SUPPORT_UNKNOWN
     } CSDSupportLevel;
     /**
      * Get the support of Client Side Decoration by checking
      * the XDG_CURRENT_DESKTOP environment variable.
      */
-    static CSDSupportLevel GetCSDSupportLevel();
+    static CSDSupportLevel GetSystemCSDSupportLevel();
 
 protected:
     virtual ~nsWindow();
 
     // event handling code
     void DispatchActivateEvent(void);
     void DispatchDeactivateEvent(void);
     void DispatchResized();
@@ -512,19 +510,21 @@ private:
     int                 mXDepth;
     mozilla::widget::WindowSurfaceProvider mSurfaceProvider;
 #endif
 
     // Upper bound on pending ConfigureNotify events to be dispatched to the
     // window. See bug 1225044.
     unsigned int mPendingConfigures;
 
-    bool               mIsCSDAvailable;
+    // Window titlebar rendering mode, CSD_SUPPORT_NONE if it's disabled
+    // for this window.
+    CSDSupportLevel    mCSDSupportLevel;
     // If true, draw our own window titlebar.
-    bool               mIsCSDEnabled;
+    bool               mDrawInTitlebar;
     // Draggable titlebar region maintained by UpdateWindowDraggingRegion
     LayoutDeviceIntRegion mDraggableRegion;
 
 #ifdef ACCESSIBILITY
     RefPtr<mozilla::a11y::Accessible> mRootAccessible;
 
     /**
      * Request to create the accessible for this window if it is top level.