Bug 1410894 - Add decoration drawing setup to nsWindow, r?jhorak draft
authorMartin Stransky <stransky@redhat.com>
Fri, 27 Oct 2017 11:19:08 +0200
changeset 687564 1ef8e5dc63f083ef56739ef1b7d510760c125322
parent 686801 0d1e55d87931fe70ec1d007e886bcd58015ff770
child 687565 341811107ae036379b4cfe5c98529635df25a4d5
push id86539
push userstransky@redhat.com
push dateFri, 27 Oct 2017 12:01:37 +0000
reviewersjhorak
bugs1410894
milestone58.0a1
Bug 1410894 - Add decoration drawing setup to nsWindow, r?jhorak MozReview-Commit-ID: BHtqoOdfRpS
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -286,16 +286,18 @@ static guint32 sLastUserInputTime = GDK_
 static guint32 sRetryGrabTime;
 
 static SystemTimeConverter<guint32>&
 TimeConverter() {
     static SystemTimeConverter<guint32> sTimeConverterSingleton;
     return sTimeConverterSingleton;
 }
 
+nsWindow::CSDSupportLevel nsWindow::sCSDSupportLevel = CSD_SUPPORT_UNKNOWN;
+
 namespace mozilla {
 
 class CurrentX11TimeGetter
 {
 public:
     explicit CurrentX11TimeGetter(GdkWindow* aWindow)
         : mWindow(aWindow)
         , mAsyncUpdateStart()
@@ -475,16 +477,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;
 }
 
 nsWindow::~nsWindow()
 {
     LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this));
 
     delete[] mTransparencyBitmap;
     mTransparencyBitmap = nullptr;
@@ -6597,16 +6601,31 @@ nsWindow::ClearCachedResources()
     for (GList* list = children; list; list = list->next) {
         nsWindow* window = get_window_for_gdk_window(GDK_WINDOW(list->data));
         if (window) {
             window->ClearCachedResources();
         }
     }
 }
 
+void
+nsWindow::SetDrawsInTitlebar(bool aState)
+{
+  if (!mIsCSDAvailable || aState == mIsCSDEnabled)
+      return;
+
+  if (mShell) {
+      gint wmd = aState ? GDK_DECOR_BORDER : ConvertBorderStyles(mBorderStyle);
+      gdk_window_set_decorations(gtk_widget_get_window(mShell),
+                                 (GdkWMDecoration) wmd);
+  }
+
+  mIsCSDEnabled = aState;
+}
+
 gint
 nsWindow::GdkScaleFactor()
 {
 #if (MOZ_WIDGET_GTK >= 3)
     // Available as of GTK 3.10+
     static auto sGdkWindowGetScaleFactorPtr = (gint (*)(GdkWindow*))
         dlsym(RTLD_DEFAULT, "gdk_window_get_scale_factor");
     if (sGdkWindowGetScaleFactorPtr && mGdkWindow)
@@ -6867,16 +6886,51 @@ 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() {
+    if (sCSDSupportLevel != CSD_SUPPORT_UNKNOWN) {
+        return sCSDSupportLevel;
+    }
+    // TODO: MATE
+    const char* currentDesktop = getenv("XDG_CURRENT_DESKTOP");
+    if (currentDesktop) {
+        if (strcmp(currentDesktop, "GNOME") == 0) {
+            sCSDSupportLevel = CSD_SUPPORT_FULL;
+        } else if (strcmp(currentDesktop, "XFCE") == 0) {
+            sCSDSupportLevel = CSD_SUPPORT_FULL;
+        } else if (strcmp(currentDesktop, "X-Cinnamon") == 0) {
+            sCSDSupportLevel = CSD_SUPPORT_FULL;
+        } else if (strcmp(currentDesktop, "KDE") == 0) {
+            sCSDSupportLevel = CSD_SUPPORT_FLAT;
+        } else if (strcmp(currentDesktop, "LXDE") == 0) {
+            sCSDSupportLevel = CSD_SUPPORT_FLAT;
+        } else if (strcmp(currentDesktop, "openbox") == 0) {
+            sCSDSupportLevel = CSD_SUPPORT_FLAT;
+        } else if (strcmp(currentDesktop, "i3") == 0) {
+            sCSDSupportLevel = CSD_SUPPORT_NONE;
+        } else {
+            sCSDSupportLevel = CSD_SUPPORT_NONE;
+        }
+    }
+    return sCSDSupportLevel;
+}
+
 int32_t
 nsWindow::RoundsWidgetCoordinatesTo()
 {
     return GdkScaleFactor();
 }
 
 void nsWindow::GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData)
 {
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -346,32 +346,36 @@ public:
                                                 nsIObserver* aObserver) override;
 #endif
 
 #ifdef MOZ_X11
     Display* XDisplay() { return mXDisplay; }
 #endif
     virtual void GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) override;
 
+    void SetDrawsInTitlebar(bool aState) override;
+
     // HiDPI scale conversion
     gint GdkScaleFactor();
 
     // To GDK
     gint DevicePixelsToGdkCoordRoundUp(int pixels);
     gint DevicePixelsToGdkCoordRoundDown(int pixels);
     GdkPoint DevicePixelsToGdkPointRoundDown(LayoutDeviceIntPoint point);
     GdkRectangle DevicePixelsToGdkSizeRoundUp(LayoutDeviceIntSize pixelSize);
 
     // 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;
 protected:
     virtual ~nsWindow();
 
     // event handling code
     void DispatchActivateEvent(void);
     void DispatchDeactivateEvent(void);
     void DispatchResized();
     void MaybeDispatchResized();
@@ -466,16 +470,20 @@ 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;
+    // If true, draw our own window titlebar.
+    bool               mIsCSDEnabled;
+
 #ifdef ACCESSIBILITY
     RefPtr<mozilla::a11y::Accessible> mRootAccessible;
 
     /**
      * Request to create the accessible for this window if it is top level.
      */
     void                CreateRootAccessible();
 
@@ -562,11 +570,22 @@ private:
      * ancestor widget's instance.  So, one set of IM contexts is created for
      * all windows in a hierarchy.  If the children are released after the top
      * level window is released, the children still have a valid pointer,
      * however, IME doesn't work at that time.
      */
     RefPtr<mozilla::widget::IMContextWrapper> mIMContext;
 
     mozilla::UniquePtr<mozilla::CurrentX11TimeGetter> mCurrentTimeGetter;
+    typedef enum { CSD_SUPPORT_FULL,    // CSD including shadows
+                   CSD_SUPPORT_FLAT,    // 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 sCSDSupportLevel;
 };
 
 #endif /* __nsWindow_h__ */