Bug 1283299 - Part 7: Report GTK CSD shadow extents to window manager. r?karlt draft
authorAndrew Comminos <andrew@comminos.com>
Tue, 05 Jul 2016 16:42:03 -0400
changeset 384224 1da2d6f52f42
parent 384223 74b7a833bc8e
child 384225 f511ac18ce61
push id22212
push userbmo:andrew@comminos.com
push dateTue, 05 Jul 2016 20:52:16 +0000
reviewerskarlt
bugs1283299
milestone50.0a1
Bug 1283299 - Part 7: Report GTK CSD shadow extents to window manager. r?karlt MozReview-Commit-ID: bRlcu4RGlH
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -124,16 +124,18 @@ using namespace mozilla::widget;
 #include "nsIDOMWheelEvent.h"
 
 #include "NativeKeyBindings.h"
 
 #include <dlfcn.h>
 
 #include "mozilla/layers/APZCTreeManager.h"
 
+#include "gtkdrawing.h"
+
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::widget;
 using namespace mozilla::layers;
 using mozilla::gl::GLContext;
 
 // Don't put more than this many rects in the dirty region, just fluff
 // out to the bounding-box if there are more
@@ -3359,16 +3361,18 @@ nsWindow::OnWindowStateEvent(GtkWidget *
     else {
         LOG(("\tNormal\n"));
         mSizeState = nsSizeMode_Normal;
 #ifdef ACCESSIBILITY
         DispatchRestoreEventAccessible();
 #endif //ACCESSIBILITY
     }
 
+    UpdateClientShadowWidth();
+
     if (mWidgetListener) {
       mWidgetListener->SizeModeChanged(mSizeState);
       if (aEvent->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) {
         mWidgetListener->FullscreenChanged(
           aEvent->new_window_state & GDK_WINDOW_STATE_FULLSCREEN);
       }
     }
 }
@@ -3423,16 +3427,17 @@ nsWindow::OnCompositedChanged()
 {
   if (mWidgetListener) {
     nsIPresShell* presShell = mWidgetListener->GetPresShell();
     if (presShell) {
       // Update CSD after the change in alpha visibility
       presShell->ThemeChanged();
     }
   }
+  UpdateClientShadowWidth();
   CleanLayerManagerRecursive();
 }
 
 void
 nsWindow::DispatchDragEvent(EventMessage aMsg, const LayoutDeviceIntPoint& aRefPoint,
                             guint aTime)
 {
     WidgetDragEvent event(true, aMsg, this);
@@ -6901,16 +6906,18 @@ nsWindow::SetDrawsInTitlebar(bool aState
     return;
 
   if (mShell) {
     NS_WARNING("gtk_window_set_decorated may not have any effect when called on a window that is already visible.");
     gtk_window_set_decorated(GTK_WINDOW(mShell), !aState);
   }
 
   mDrawsInTitlebar = aState;
+
+  UpdateClientShadowWidth();
 }
 
 bool
 nsWindow::HasARGBVisual() const
 {
   if (!mGdkWindow) {
     NS_WARNING("nsWindow::HasARGBVisual called before realization!");
     return false;
@@ -7207,8 +7214,25 @@ nsWindow::RoundsWidgetCoordinatesTo()
     return GdkScaleFactor();
 }
 
 bool
 nsWindow::IsClientDecorated() const
 {
     return mDrawsInTitlebar;
 }
+void
+nsWindow::UpdateClientShadowWidth()
+{
+  if (gtk_check_version(3, 12, 0) != nullptr)
+    return;
+
+  // Shadows are only used for normal, non-solid client windows with CSD.
+  gint top = 0, right = 0, bottom = 0, left = 0;
+  if (IsClientDecorated() && !UseSolidCSD() && mSizeState == nsSizeMode_Normal) {
+    moz_gtk_get_window_decoration_extents(&top, &right, &bottom, &left);
+  }
+
+  static auto sGdkWindowSetShadowWidth =
+    (void (*)(GdkWindow*, gint, gint, gint, gint))
+    dlsym(RTLD_DEFAULT, "gdk_window_set_shadow_width");
+  sGdkWindowSetShadowWidth(mGdkWindow, left, right, top, bottom);
+}
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -394,16 +394,19 @@ protected:
                                       GtkWidget* aNewContainer,
                                       GdkWindow* aNewParentWindow,
                                       GtkWidget* aOldContainer);
 
     virtual void RegisterTouchWindow() override;
 
     // Decorations
     bool IsClientDecorated() const;
+    // Informs the window manager about the size of the shadows surrounding
+    // a client-side decorated window.
+    void UpdateClientShadowWidth();
 
     nsCOMPtr<nsIWidget> mParent;
     // Is this a toplevel window?
     bool                mIsTopLevel;
     // Has this widget been destroyed yet?
     bool                mIsDestroyed;
 
     // Should we send resize events on all resizes?