Bug 1410894 - Add decoration drawing setup to nsWindow, r?jhorak
MozReview-Commit-ID: BHtqoOdfRpS
--- 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__ */