Bug 1194751 - Part 5. Implement ScreenHelperGTK and delete old nsScreenManagerGtk/nsScreenGtk. r=karlt
authorKan-Ru Chen <kanru@kanru.info>
Thu, 09 Mar 2017 19:29:44 +0800
changeset 349721 4be4367d022d7b97eb90b503d6eef186cdb0309f
parent 349720 b18a43068dc6d63c4f5d10d288614a4282215acc
child 349722 5a58b77947bf1146bd7080fc2e64e8b04c585861
push id31559
push usercbook@mozilla.com
push dateMon, 27 Mar 2017 10:55:45 +0000
treeherdermozilla-central@7ac8812719a1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1194751
milestone55.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 1194751 - Part 5. Implement ScreenHelperGTK and delete old nsScreenManagerGtk/nsScreenGtk. r=karlt ScreenHelperGTK is the platform dependent part of the original nsScreenManagerGtk and nsScreenGtk. It registers monitors-changed event listener from gtk and pushes updates to ScreenManager. See patch part 4. for how ScreenManager works. MozReview-Commit-ID: KBo7ZLFTjM3
gfx/thebes/gfxXlibSurface.h
widget/gtk/ScreenHelperGTK.cpp
widget/gtk/ScreenHelperGTK.h
widget/gtk/moz.build
widget/gtk/nsAppShell.cpp
widget/gtk/nsDragService.cpp
widget/gtk/nsLookAndFeel.cpp
widget/gtk/nsNativeThemeGTK.cpp
widget/gtk/nsScreenGtk.cpp
widget/gtk/nsScreenGtk.h
widget/gtk/nsScreenManagerGtk.cpp
widget/gtk/nsScreenManagerGtk.h
widget/gtk/nsWidgetFactory.cpp
widget/gtk/nsWindow.cpp
--- a/gfx/thebes/gfxXlibSurface.h
+++ b/gfx/thebes/gfxXlibSurface.h
@@ -31,51 +31,51 @@ public:
     gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual);
 
     // construct a wrapper around the specified drawable with dpy/visual,
     // and known width/height.
     gfxXlibSurface(Display *dpy, Drawable drawable, Visual *visual, const mozilla::gfx::IntSize& size);
 
     // construct a wrapper around the specified drawable with dpy/format,
     // and known width/height.
-    gfxXlibSurface(Screen *screen, Drawable drawable, XRenderPictFormat *format,
+    gfxXlibSurface(::Screen *screen, Drawable drawable, XRenderPictFormat *format,
                    const mozilla::gfx::IntSize& size);
 
     explicit gfxXlibSurface(cairo_surface_t *csurf);
 
     // create a new Pixmap and wrapper surface.
     // |relatedDrawable| provides a hint to the server for determining whether
     // the pixmap should be in video or system memory.  It must be on
     // |screen| (if specified).
     static already_AddRefed<gfxXlibSurface>
-    Create(Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size,
+    Create(::Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size,
            Drawable relatedDrawable = X11None);
     static cairo_surface_t *
-    CreateCairoSurface(Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size,
+    CreateCairoSurface(::Screen *screen, Visual *visual, const mozilla::gfx::IntSize& size,
                        Drawable relatedDrawable = X11None);
     static already_AddRefed<gfxXlibSurface>
-    Create(Screen* screen, XRenderPictFormat *format, const mozilla::gfx::IntSize& size,
+    Create(::Screen* screen, XRenderPictFormat *format, const mozilla::gfx::IntSize& size,
            Drawable relatedDrawable = X11None);
 
     virtual ~gfxXlibSurface();
 
     virtual already_AddRefed<gfxASurface>
     CreateSimilarSurface(gfxContentType aType,
                          const mozilla::gfx::IntSize& aSize) override;
     virtual void Finish() override;
 
     virtual const mozilla::gfx::IntSize GetSize() const override;
 
     Display* XDisplay() { return mDisplay; }
-    Screen* XScreen();
+    ::Screen* XScreen();
     Drawable XDrawable() { return mDrawable; }
     XRenderPictFormat* XRenderFormat();
 
-    static int DepthOfVisual(const Screen* screen, const Visual* visual);
-    static Visual* FindVisual(Screen* screen, gfxImageFormat format);
+    static int DepthOfVisual(const ::Screen* screen, const Visual* visual);
+    static Visual* FindVisual(::Screen* screen, gfxImageFormat format);
     static XRenderPictFormat *FindRenderFormat(Display *dpy, gfxImageFormat format);
     static bool GetColormapAndVisual(cairo_surface_t* aXlibSurface, Colormap* colormap, Visual **visual);
 
     // take ownership of a passed-in Pixmap, calling XFreePixmap on it
     // when the gfxXlibSurface is destroyed.
     void TakePixmap();
 
     // Release ownership of this surface's Pixmap.  This is only valid
rename from widget/gtk/nsScreenManagerGtk.cpp
rename to widget/gtk/ScreenHelperGTK.cpp
--- a/widget/gtk/nsScreenManagerGtk.cpp
+++ b/widget/gtk/ScreenHelperGTK.cpp
@@ -1,77 +1,113 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsScreenManagerGtk.h"
-
-#include "mozilla/RefPtr.h"
-#include "nsScreenGtk.h"
-#include "nsIComponentManager.h"
-#include "nsRect.h"
-#include "nsGtkUtils.h"
-
-#define SCREEN_MANAGER_LIBRARY_LOAD_FAILED ((PRLibrary*)1)
+#include "ScreenHelperGTK.h"
 
 #ifdef MOZ_X11
+#include <X11/Xatom.h>
 #include <gdk/gdkx.h>
+// from Xinerama.h
+typedef struct {
+   int   screen_number;
+   short x_org;
+   short y_org;
+   short width;
+   short height;
+} XineramaScreenInfo;
 // prototypes from Xinerama.h
 typedef Bool (*_XnrmIsActive_fn)(Display *dpy);
 typedef XineramaScreenInfo* (*_XnrmQueryScreens_fn)(Display *dpy, int *number);
 #endif
-
+#include <dlfcn.h>
 #include <gtk/gtk.h>
 
-void
+#include "gfxPlatformGtk.h"
+#include "mozilla/Logging.h"
+#include "nsGtkUtils.h"
+#include "nsTArray.h"
+
+#define SCREEN_MANAGER_LIBRARY_LOAD_FAILED ((PRLibrary*)1)
+
+namespace mozilla {
+namespace widget {
+
+static LazyLogModule sScreenLog("WidgetScreen");
+
+static void
 monitors_changed(GdkScreen* aScreen, gpointer aClosure)
 {
-  nsScreenManagerGtk *manager = static_cast<nsScreenManagerGtk*>(aClosure);
-  manager->Init();
+  MOZ_LOG(sScreenLog, LogLevel::Debug, ("Received monitors-changed event"));
+  ScreenHelperGTK* self = static_cast<ScreenHelperGTK*>(aClosure);
+  self->RefreshScreens();
 }
 
 static GdkFilterReturn
-root_window_event_filter(GdkXEvent *aGdkXEvent, GdkEvent *aGdkEvent,
+root_window_event_filter(GdkXEvent* aGdkXEvent, GdkEvent* aGdkEvent,
                          gpointer aClosure)
 {
-  nsScreenManagerGtk *manager = static_cast<nsScreenManagerGtk*>(aClosure);
 #ifdef MOZ_X11
+  ScreenHelperGTK* self = static_cast<ScreenHelperGTK*>(aClosure);
   XEvent *xevent = static_cast<XEvent*>(aGdkXEvent);
 
-  // See comments in nsScreenGtk::Init below.
   switch (xevent->type) {
     case PropertyNotify:
       {
         XPropertyEvent *propertyEvent = &xevent->xproperty;
-        if (propertyEvent->atom == manager->NetWorkareaAtom()) {
-          manager->Init();
+        if (propertyEvent->atom == self->NetWorkareaAtom()) {
+          MOZ_LOG(sScreenLog, LogLevel::Debug, ("Work area size changed"));
+          self->RefreshScreens();
         }
       }
       break;
     default:
       break;
   }
 #endif
 
   return GDK_FILTER_CONTINUE;
 }
 
-nsScreenManagerGtk :: nsScreenManagerGtk ( )
+ScreenHelperGTK::ScreenHelperGTK()
   : mXineramalib(nullptr)
   , mRootWindow(nullptr)
   , mNetWorkareaAtom(0)
 {
-  // nothing else to do. I guess we could cache a bunch of information
-  // here, but we want to ask the device at runtime in case anything
-  // has changed.
+  MOZ_LOG(sScreenLog, LogLevel::Debug, ("ScreenHelperGTK created"));
+  mRootWindow = gdk_get_default_root_window();
+  if (!mRootWindow) {
+    // Sometimes we don't initial X (e.g., xpcshell)
+    MOZ_LOG(sScreenLog, LogLevel::Debug, ("mRootWindow is nullptr, running headless"));
+    return;
+  }
+
+  g_object_ref(mRootWindow);
+
+  // GDK_PROPERTY_CHANGE_MASK ==> PropertyChangeMask, for PropertyNotify
+  gdk_window_set_events(mRootWindow,
+                        GdkEventMask(gdk_window_get_events(mRootWindow) |
+                                     GDK_PROPERTY_CHANGE_MASK));
+
+  g_signal_connect(gdk_screen_get_default(), "monitors-changed",
+                   G_CALLBACK(monitors_changed), this);
+#ifdef MOZ_X11
+  gdk_window_add_filter(mRootWindow, root_window_event_filter, this);
+  if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
+    mNetWorkareaAtom =
+      XInternAtom(GDK_WINDOW_XDISPLAY(mRootWindow), "_NET_WORKAREA", False);
+  }
+#endif
+  RefreshScreens();
 }
 
-
-nsScreenManagerGtk :: ~nsScreenManagerGtk()
+ScreenHelperGTK::~ScreenHelperGTK()
 {
   g_signal_handlers_disconnect_by_func(gdk_screen_get_default(),
                                        FuncToGpointer(monitors_changed),
                                        this);
 
   if (mRootWindow) {
     gdk_window_remove_filter(mRootWindow, root_window_event_filter, this);
     g_object_unref(mRootWindow);
@@ -82,56 +118,172 @@ nsScreenManagerGtk :: ~nsScreenManagerGt
    * in X, which is to be called in XCloseDisplay(). This is the case
    * if Xinerama is active, even if only with one screen.
    *
    * We can't unload libXinerama.so.1 here because this will make
    * the address of close_display() registered in X to be invalid and
    * it will crash when XCloseDisplay() is called later. */
 }
 
+gint
+ScreenHelperGTK::GetGTKMonitorScaleFactor()
+{
+#if (MOZ_WIDGET_GTK >= 3)
+  // Since GDK 3.10
+  static auto sGdkScreenGetMonitorScaleFactorPtr = (gint (*)(GdkScreen*, gint))
+    dlsym(RTLD_DEFAULT, "gdk_screen_get_monitor_scale_factor");
+  if (sGdkScreenGetMonitorScaleFactorPtr) {
+    // FIXME: In the future, we'll want to fix this for GTK on Wayland which
+    // supports a variable scale factor per display.
+    GdkScreen *screen = gdk_screen_get_default();
+    return sGdkScreenGetMonitorScaleFactorPtr(screen, 0);
+  }
+#endif
+  return 1;
+}
 
-// addref, release, QI
-NS_IMPL_ISUPPORTS(nsScreenManagerGtk, nsIScreenManager)
+static float
+GetDefaultCssScale()
+{
+  double scale = nsIWidget::DefaultScaleOverride();
+  if (scale <= 0.0) {
+    scale = ScreenHelperGTK::GetGTKMonitorScaleFactor() * gfxPlatformGtk::GetDPIScale();
+  }
+  return scale;
+}
 
+float
+ScreenHelperGTK::GetSystemDefaultScale()
+{
+  return GetDefaultCssScale();
+}
+
+static uint32_t
+GetGTKPixelDepth()
+{
+  GdkVisual * visual = gdk_screen_get_system_visual(gdk_screen_get_default());
+  return gdk_visual_get_depth(visual);
+}
+
+static already_AddRefed<Screen>
+MakeScreen(GdkWindow* aRootWindow)
+{
+  RefPtr<Screen> screen;
 
-// this function will make sure that everything has been initialized.
-nsresult
-nsScreenManagerGtk :: EnsureInit()
-{
-  if (mCachedScreenArray.Count() > 0)
-    return NS_OK;
+  gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor();
+  gint width = gdk_screen_width() * scale;
+  gint height = gdk_screen_height() * scale;
+  uint32_t pixelDepth = GetGTKPixelDepth();
+  DesktopToLayoutDeviceScale contentsScale(1.0);
+  CSSToLayoutDeviceScale defaultCssScale(GetDefaultCssScale());
+
+  LayoutDeviceIntRect rect;
+  LayoutDeviceIntRect availRect;
+  rect = availRect = LayoutDeviceIntRect(0, 0, width, height);
+
+#ifdef MOZ_X11
+  // We need to account for the taskbar, etc in the available rect.
+  // See http://freedesktop.org/Standards/wm-spec/index.html#id2767771
+
+  // XXX do we care about _NET_WM_STRUT_PARTIAL?  That will
+  // add much more complexity to the code here (our screen
+  // could have a non-rectangular shape), but should
+  // lead to greater accuracy.
 
-  mRootWindow = gdk_get_default_root_window();
-  if (!mRootWindow) {
-    // Sometimes we don't initial X (e.g., xpcshell)
-    return NS_OK;
+  long *workareas;
+  GdkAtom type_returned;
+  int format_returned;
+  int length_returned;
+
+  GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
+
+  gdk_error_trap_push();
+
+  // gdk_property_get uses (length + 3) / 4, hence G_MAXLONG - 3 here.
+  if (!gdk_property_get(aRootWindow,
+                        gdk_atom_intern ("_NET_WORKAREA", FALSE),
+                        cardinal_atom,
+                        0, G_MAXLONG - 3, FALSE,
+                        &type_returned,
+                        &format_returned,
+                        &length_returned,
+                        (guchar **) &workareas)) {
+    // This window manager doesn't support the freedesktop standard.
+    // Nothing we can do about it, so assume full screen size.
+    MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f]",
+                                          rect.x, rect.y, rect.width, rect.height,
+                                          pixelDepth, defaultCssScale.scale));
+    screen = new Screen(rect, availRect,
+                        pixelDepth, pixelDepth,
+                        contentsScale, defaultCssScale);
+    return screen.forget();
   }
 
-  g_object_ref(mRootWindow);
+  // Flush the X queue to catch errors now.
+  gdk_flush();
 
-  // GDK_PROPERTY_CHANGE_MASK ==> PropertyChangeMask, for PropertyNotify
-  gdk_window_set_events(mRootWindow,
-                        GdkEventMask(gdk_window_get_events(mRootWindow) |
-                                     GDK_PROPERTY_CHANGE_MASK));
+  if (!gdk_error_trap_pop() &&
+      type_returned == cardinal_atom &&
+      length_returned && (length_returned % 4) == 0 &&
+      format_returned == 32) {
+    int num_items = length_returned / sizeof(long);
 
-  g_signal_connect(gdk_screen_get_default(), "monitors-changed",
-                   G_CALLBACK(monitors_changed), this);
-#ifdef MOZ_X11
-  gdk_window_add_filter(mRootWindow, root_window_event_filter, this);
-  if (GDK_IS_X11_DISPLAY(gdk_display_get_default()))
-      mNetWorkareaAtom =
-        XInternAtom(GDK_WINDOW_XDISPLAY(mRootWindow), "_NET_WORKAREA", False);
+    for (int i = 0; i < num_items; i += 4) {
+      LayoutDeviceIntRect workarea(workareas[i],     workareas[i + 1],
+                                   workareas[i + 2], workareas[i + 3]);
+      if (!rect.Contains(workarea)) {
+        // Note that we hit this when processing screen size changes,
+        // since we'll get the configure event before the toolbars have
+        // been moved.  We'll end up cleaning this up when we get the
+        // change notification to the _NET_WORKAREA property.  However,
+        // we still want to listen to both, so we'll handle changes
+        // properly for desktop environments that don't set the
+        // _NET_WORKAREA property.
+        NS_WARNING("Invalid bounds");
+        continue;
+      }
+
+      availRect.IntersectRect(availRect, workarea);
+    }
+  }
+  g_free(workareas);
 #endif
-
-  return Init();
+  MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f]",
+                                        rect.x, rect.y, rect.width, rect.height,
+                                        pixelDepth, defaultCssScale.scale));
+  screen = new Screen(rect, availRect,
+                      pixelDepth, pixelDepth,
+                      contentsScale, defaultCssScale);
+  return screen.forget();
 }
 
-nsresult
-nsScreenManagerGtk :: Init()
+static already_AddRefed<Screen>
+MakeScreen(const XineramaScreenInfo& aScreenInfo)
 {
+  LayoutDeviceIntRect xineRect(aScreenInfo.x_org, aScreenInfo.y_org,
+                               aScreenInfo.width, aScreenInfo.height);
+  uint32_t pixelDepth = GetGTKPixelDepth();
+  DesktopToLayoutDeviceScale contentsScale(1.0);
+  CSSToLayoutDeviceScale defaultCssScale(GetDefaultCssScale());
+
+  MOZ_LOG(sScreenLog, LogLevel::Debug, ("New screen [%d %d %d %d %d %f]",
+                                        xineRect.x, xineRect.y,
+                                        xineRect.width, xineRect.height,
+                                        pixelDepth, defaultCssScale.scale));
+  RefPtr<Screen> screen = new Screen(xineRect, xineRect,
+                                     pixelDepth, pixelDepth,
+                                     contentsScale, defaultCssScale);
+  return screen.forget();
+}
+
+void
+ScreenHelperGTK::RefreshScreens()
+{
+  MOZ_LOG(sScreenLog, LogLevel::Debug, ("Refreshing screens"));
+  AutoTArray<RefPtr<Screen>, 4> screenList;
 #ifdef MOZ_X11
   XineramaScreenInfo *screenInfo = nullptr;
   int numScreens;
 
   bool useXinerama = GDK_IS_X11_DISPLAY(gdk_display_get_default());
 
   if (useXinerama && !mXineramalib) {
     mXineramalib = PR_LoadLibrary("libXinerama.so.1");
@@ -153,194 +305,34 @@ nsScreenManagerGtk :: Init()
     }
   }
 
   // screenInfo == nullptr if either Xinerama couldn't be loaded or
   // isn't running on the current display
   if (!screenInfo || numScreens == 1) {
     numScreens = 1;
 #endif
-    RefPtr<nsScreenGtk> screen;
-
-    if (mCachedScreenArray.Count() > 0) {
-      screen = static_cast<nsScreenGtk*>(mCachedScreenArray[0]);
-    } else {
-      screen = new nsScreenGtk();
-      if (!screen || !mCachedScreenArray.AppendObject(screen)) {
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-    }
-
-    screen->Init(mRootWindow);
+    MOZ_LOG(sScreenLog, LogLevel::Debug, ("Find only one screen available"));
+    // Get primary screen
+    screenList.AppendElement(MakeScreen(mRootWindow));
 #ifdef MOZ_X11
   }
   // If Xinerama is enabled and there's more than one screen, fill
   // in the info for all of the screens.  If that's not the case
-  // then nsScreenGTK() defaults to the screen width + height
+  // then defaults to the screen width + height
   else {
-#ifdef DEBUG
-    printf("Xinerama superpowers activated for %d screens!\n", numScreens);
-#endif
+    MOZ_LOG(sScreenLog, LogLevel::Debug,
+            ("Xinerama enabled for %d screens", numScreens));
     for (int i = 0; i < numScreens; ++i) {
-      RefPtr<nsScreenGtk> screen;
-      if (mCachedScreenArray.Count() > i) {
-        screen = static_cast<nsScreenGtk*>(mCachedScreenArray[i]);
-      } else {
-        screen = new nsScreenGtk();
-        if (!screen || !mCachedScreenArray.AppendObject(screen)) {
-          return NS_ERROR_OUT_OF_MEMORY;
-        }
-      }
-
-      // initialize this screen object
-      screen->Init(&screenInfo[i]);
+      screenList.AppendElement(MakeScreen(screenInfo[i]));
     }
   }
-  // Remove any screens that are no longer present.
-  while (mCachedScreenArray.Count() > numScreens) {
-    mCachedScreenArray.RemoveObjectAt(mCachedScreenArray.Count() - 1);
-  }
 
   if (screenInfo) {
     XFree(screenInfo);
   }
 #endif
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsScreenManagerGtk :: ScreenForId ( uint32_t aId, nsIScreen **outScreen )
-{
-  *outScreen = nullptr;
-
-  nsresult rv;
-  rv = EnsureInit();
-  if (NS_FAILED(rv)) {
-    NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from ScreenForId");
-    return rv;
-  }
-
-  for (int32_t i = 0, i_end = mCachedScreenArray.Count(); i < i_end; ++i) {
-    uint32_t id;
-    rv = mCachedScreenArray[i]->GetId(&id);
-    if (NS_SUCCEEDED(rv) && id == aId) {
-      NS_IF_ADDREF(*outScreen = mCachedScreenArray[i]);
-      return NS_OK;
-    }
-  }
-
-  return NS_ERROR_FAILURE;
+  ScreenManager& screenManager = ScreenManager::GetSingleton();
+  screenManager.Refresh(Move(screenList));
 }
 
-
-//
-// ScreenForRect
-//
-// Returns the screen that contains the rectangle. If the rect overlaps
-// multiple screens, it picks the screen with the greatest area of intersection.
-//
-// The coordinates are in desktop pixels.
-//
-NS_IMETHODIMP
-nsScreenManagerGtk::ScreenForRect(int32_t aX, int32_t aY,
-                                  int32_t aWidth, int32_t aHeight,
-                                  nsIScreen **aOutScreen)
-{
-  nsresult rv;
-  rv = EnsureInit();
-  if (NS_FAILED(rv)) {
-    NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from ScreenForRect");
-    return rv;
-  }
-
-  // which screen ( index from zero ) should we return?
-  uint32_t which = 0;
-  // Optimize for the common case.  If the number of screens is only
-  // one then this will fall through with which == 0 and will get the
-  // primary screen.
-  if (mCachedScreenArray.Count() > 1) {
-    // walk the list of screens and find the one that has the most
-    // surface area.
-    uint32_t area = 0;
-    nsIntRect windowRect(aX, aY, aWidth, aHeight);
-    for (int32_t i = 0, i_end = mCachedScreenArray.Count(); i < i_end; ++i) {
-      int32_t  x, y, width, height;
-      x = y = width = height = 0;
-      mCachedScreenArray[i]->GetRect(&x, &y, &width, &height);
-      // calculate the surface area
-      nsIntRect screenRect(x, y, width, height);
-      screenRect.IntersectRect(screenRect, windowRect);
-      uint32_t tempArea = screenRect.width * screenRect.height;
-      if (tempArea >= area) {
-        which = i;
-        area = tempArea;
-      }
-    }
-  }
-  *aOutScreen = mCachedScreenArray.SafeObjectAt(which);
-  NS_IF_ADDREF(*aOutScreen);
-  return NS_OK;
-
-} // ScreenForRect
-
-
-//
-// GetPrimaryScreen
-//
-// The screen with the menubar/taskbar. This shouldn't be needed very
-// often.
-//
-NS_IMETHODIMP
-nsScreenManagerGtk :: GetPrimaryScreen(nsIScreen * *aPrimaryScreen)
-{
-  nsresult rv;
-  rv =  EnsureInit();
-  if (NS_FAILED(rv)) {
-    NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from GetPrimaryScreen");
-    return rv;
-  }
-  *aPrimaryScreen = mCachedScreenArray.SafeObjectAt(0);
-  NS_IF_ADDREF(*aPrimaryScreen);
-  return NS_OK;
-
-} // GetPrimaryScreen
-
-NS_IMETHODIMP
-nsScreenManagerGtk::GetSystemDefaultScale(float *aDefaultScale)
-{
-  *aDefaultScale = nsScreenGtk::GetDPIScale();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsScreenManagerGtk :: ScreenForNativeWidget (void *aWidget, nsIScreen **outScreen)
-{
-  nsresult rv;
-  rv = EnsureInit();
-  if (NS_FAILED(rv)) {
-    NS_ERROR("nsScreenManagerGtk::EnsureInit() failed from ScreenForNativeWidget");
-    return rv;
-  }
-
-  if (mCachedScreenArray.Count() > 1) {
-    // I don't know how to go from GtkWindow to nsIScreen, especially
-    // given xinerama and stuff, so let's just do this
-    gint x, y, width, height;
-#if (MOZ_WIDGET_GTK == 2)
-    gint depth;
-#endif
-    x = y = width = height = 0;
-
-#if (MOZ_WIDGET_GTK == 2)
-    gdk_window_get_geometry(GDK_WINDOW(aWidget), &x, &y, &width, &height,
-                            &depth);
-#else
-    gdk_window_get_geometry(GDK_WINDOW(aWidget), &x, &y, &width, &height);
-#endif
-    gdk_window_get_origin(GDK_WINDOW(aWidget), &x, &y);
-    rv = ScreenForRect(x, y, width, height, outScreen);
-  } else {
-    rv = GetPrimaryScreen(outScreen);
-  }
-
-  return rv;
-}
+} // namespace widget
+} // namespace mozilla
rename from widget/gtk/nsScreenManagerGtk.h
rename to widget/gtk/ScreenHelperGTK.h
--- a/widget/gtk/nsScreenManagerGtk.h
+++ b/widget/gtk/ScreenHelperGTK.h
@@ -1,52 +1,49 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef nsScreenManagerGtk_h___
-#define nsScreenManagerGtk_h___
+#ifndef mozilla_widget_gtk_ScreenHelperGTK_h
+#define mozilla_widget_gtk_ScreenHelperGTK_h
 
-#include "nsIScreenManager.h"
-#include "nsIScreen.h"
-#include "nsCOMPtr.h"
-#include "nsCOMArray.h"
+#include "mozilla/widget/ScreenManager.h"
+
 #include "prlink.h"
 #include "gdk/gdk.h"
 #ifdef MOZ_X11
 #include <X11/Xlib.h>
 #endif
 
-//------------------------------------------------------------------------
+namespace mozilla {
+namespace widget {
 
-class nsScreenManagerGtk : public nsIScreenManager
+class ScreenHelperGTK final : public ScreenManager::Helper
 {
 public:
-  nsScreenManagerGtk ( );
+  ScreenHelperGTK();
+  ~ScreenHelperGTK() override;
 
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSISCREENMANAGER
+  float GetSystemDefaultScale() override;
+
+  static gint GetGTKMonitorScaleFactor();
 
 #ifdef MOZ_X11
   Atom NetWorkareaAtom() { return mNetWorkareaAtom; }
 #endif
-  
-  // For internal use, or reinitialization from change notification.
-  nsresult Init();
+
+  // For internal use from signal callback functions
+  void RefreshScreens();
 
 private:
-  virtual ~nsScreenManagerGtk();
-
-  nsresult EnsureInit();
-
-  // Cached screen array.  Its length is the number of screens we have.
-  nsCOMArray<nsIScreen> mCachedScreenArray;
-
-  PRLibrary *mXineramalib;
-
-  GdkWindow *mRootWindow;
+  PRLibrary* mXineramalib;
+  GdkWindow* mRootWindow;
 #ifdef MOZ_X11
   Atom mNetWorkareaAtom;
 #endif
 };
 
-#endif  // nsScreenManagerGtk_h___
+} // namespace widget
+} // namespace mozilla
+
+#endif // mozilla_widget_gtk_ScreenHelperGTK_h
--- a/widget/gtk/moz.build
+++ b/widget/gtk/moz.build
@@ -24,21 +24,20 @@ UNIFIED_SOURCES += [
     'nsAppShell.cpp',
     'nsBidiKeyboard.cpp',
     'nsColorPicker.cpp',
     'nsFilePicker.cpp',
     'nsGtkKeyUtils.cpp',
     'nsImageToPixbuf.cpp',
     'nsLookAndFeel.cpp',
     'nsNativeThemeGTK.cpp',
-    'nsScreenGtk.cpp',
-    'nsScreenManagerGtk.cpp',
     'nsSound.cpp',
     'nsToolkit.cpp',
     'nsWidgetFactory.cpp',
+    'ScreenHelperGTK.cpp',
     'WakeLockListener.cpp',
     'WidgetTraceEvent.cpp',
     'WidgetUtilsGtk.cpp',
 ]
 
 SOURCES += [
     'nsWindow.cpp', # conflicts with X11 headers
 ]
--- a/widget/gtk/nsAppShell.cpp
+++ b/widget/gtk/nsAppShell.cpp
@@ -16,18 +16,22 @@
 #include "prenv.h"
 #include "mozilla/HangMonitor.h"
 #include "mozilla/Unused.h"
 #include "GeckoProfiler.h"
 #include "nsIPowerManagerService.h"
 #ifdef MOZ_ENABLE_DBUS
 #include "WakeLockListener.h"
 #endif
+#include "ScreenHelperGTK.h"
+#include "mozilla/widget/ScreenManager.h"
 
 using mozilla::Unused;
+using mozilla::widget::ScreenHelperGTK;
+using mozilla::widget::ScreenManager;
 
 #define NOTIFY_TOKEN 0xFA
 
 PRLogModuleInfo *gWidgetLog = nullptr;
 PRLogModuleInfo *gWidgetFocusLog = nullptr;
 PRLogModuleInfo *gWidgetDragLog = nullptr;
 PRLogModuleInfo *gWidgetDrawLog = nullptr;
 
@@ -159,16 +163,21 @@ nsAppShell::Init()
     }
 #endif
 
     if (!sPollFunc) {
         sPollFunc = g_main_context_get_poll_func(nullptr);
         g_main_context_set_poll_func(nullptr, &PollWrapper);
     }
 
+    if (XRE_IsParentProcess()) {
+        ScreenManager& screenManager = ScreenManager::GetSingleton();
+        screenManager.SetHelper(mozilla::MakeUnique<ScreenHelperGTK>());
+    }
+
 #if MOZ_WIDGET_GTK == 3
     if (!sReal_gtk_window_check_resize &&
         gtk_check_version(3,8,0) != nullptr) { // GTK 3.0 to GTK 3.6.
         // GtkWindow is a static class and so will leak anyway but this ref
         // makes sure it isn't recreated.
         gpointer gtk_plug_class = g_type_class_ref(GTK_TYPE_WINDOW);
         auto check_resize = &GTK_CONTAINER_CLASS(gtk_plug_class)->check_resize;
         sReal_gtk_window_check_resize = *check_resize;
--- a/widget/gtk/nsDragService.cpp
+++ b/widget/gtk/nsDragService.cpp
@@ -35,17 +35,17 @@
 #include "nsIDocument.h"
 #include "nsISelection.h"
 #include "nsViewManager.h"
 #include "nsIFrame.h"
 #include "nsGtkUtils.h"
 #include "nsGtkKeyUtils.h"
 #include "mozilla/gfx/2D.h"
 #include "gfxPlatform.h"
-#include "nsScreenGtk.h"
+#include "ScreenHelperGTK.h"
 #include "nsArrayUtils.h"
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 
 // This sets how opaque the drag image is
 #define DRAG_IMAGE_ALPHA_LEVEL 0.5
 
@@ -234,17 +234,17 @@ OnSourceGrabEventAfter(GtkWidget *widget
         if (sMotionEvent) {
             gdk_event_free(sMotionEvent);
         }
         sMotionEvent = gdk_event_copy(event);
 
         // Update the cursor position.  The last of these recorded gets used for
         // the eDragEnd event.
         nsDragService *dragService = static_cast<nsDragService*>(user_data);
-        gint scale = nsScreenGtk::GetGtkMonitorScaleFactor();
+        gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor();
         auto p = LayoutDeviceIntPoint::Round(event->motion.x_root * scale,
                                              event->motion.y_root * scale);
         dragService->SetDragEndPoint(p);
     } else if (sMotionEvent && (event->type == GDK_KEY_PRESS ||
                                 event->type == GDK_KEY_RELEASE)) {
         // Update modifier state from key events.
         sMotionEvent->motion.state = event->key.state;
     } else {
@@ -500,17 +500,17 @@ nsDragService::SetAlphaPixmap(SourceSurf
     cairo_surface_mark_dirty(surf);
     cairo_surface_set_device_offset(surf, -aXOffset, -aYOffset);
 
     // Ensure that the surface is drawn at the correct scale on HiDPI displays.
     static auto sCairoSurfaceSetDeviceScalePtr =
         (void (*)(cairo_surface_t*,double,double))
         dlsym(RTLD_DEFAULT, "cairo_surface_set_device_scale");
     if (sCairoSurfaceSetDeviceScalePtr) {
-        gint scale = nsScreenGtk::GetGtkMonitorScaleFactor();
+        gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor();
         sCairoSurfaceSetDeviceScalePtr(surf, scale, scale);
     }
 
     gtk_drag_set_icon_surface(aContext, surf);
     cairo_surface_destroy(surf);
     return true;
 #endif
 }
@@ -1412,17 +1412,17 @@ nsDragService::SourceEndDragSession(GdkD
         // or SourceEndDragSession on drag-failed
         return;
 
     if (mEndDragPoint.x < 0) {
         // We don't have a drag end point, so guess
         gint x, y;
         GdkDisplay* display = gdk_display_get_default();
         if (display) {
-            gint scale = nsScreenGtk::GetGtkMonitorScaleFactor();
+            gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor();
             gdk_display_get_pointer(display, nullptr, &x, &y, nullptr);
             SetDragEndPoint(LayoutDeviceIntPoint(x * scale, y * scale));
         }
     }
 
     // Either the drag was aborted or the drop occurred outside the app.
     // The dropEffect of mDataTransfer is not updated for motion outside the
     // app, but is needed for the dragend event, so set it now.
--- a/widget/gtk/nsLookAndFeel.cpp
+++ b/widget/gtk/nsLookAndFeel.cpp
@@ -13,17 +13,17 @@
 #include <gtk/gtk.h>
 #include <gdk/gdk.h>
 
 #include <pango/pango.h>
 #include <pango/pango-fontmap.h>
 
 #include <fontconfig/fontconfig.h>
 #include "gfxPlatformGtk.h"
-#include "nsScreenGtk.h"
+#include "ScreenHelperGTK.h"
 
 #include "gtkdrawing.h"
 #include "nsStyleConsts.h"
 #include "gfxFontConstants.h"
 #include "WidgetUtils.h"
 
 #include <dlfcn.h>
 
@@ -920,17 +920,17 @@ GetSystemFontInfo(GtkWidget *aWidget,
     if (!pango_font_description_get_size_is_absolute(desc)) {
         // |size| is in pango-points, so convert to pixels.
         size *= float(gfxPlatformGtk::GetDPI()) / POINTS_PER_INCH_FLOAT;
     }
 
     // Scale fonts up on HiDPI displays.
     // This would be done automatically with cairo, but we manually manage
     // the display scale for platform consistency.
-    size *= nsScreenGtk::GetGtkMonitorScaleFactor();
+    size *= ScreenHelperGTK::GetGTKMonitorScaleFactor();
 
     // |size| is now pixels
 
     aFontStyle->size = size;
 
     pango_font_description_free(desc);
 }
 
--- a/widget/gtk/nsNativeThemeGTK.cpp
+++ b/widget/gtk/nsNativeThemeGTK.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsNativeThemeGTK.h"
 #include "nsThemeConstants.h"
 #include "gtkdrawing.h"
-#include "nsScreenGtk.h"
+#include "ScreenHelperGTK.h"
 
 #include "gfx2DGlue.h"
 #include "nsIObserverService.h"
 #include "nsIServiceManager.h"
 #include "nsIFrame.h"
 #include "nsIPresShell.h"
 #include "nsIContent.h"
 #include "nsViewManager.h"
@@ -1085,17 +1085,17 @@ nsNativeThemeGTK::GetExtraSizeForWidget(
       } else {
         aExtra->bottom = extra;
       }
       return false;
     }
   default:
     return false;
   }
-  gint scale = nsScreenGtk::GetGtkMonitorScaleFactor();
+  gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor();
   aExtra->top *= scale;
   aExtra->right *= scale;
   aExtra->bottom *= scale;
   aExtra->left *= scale;
   return true;
 }
 
 NS_IMETHODIMP
@@ -1113,17 +1113,17 @@ nsNativeThemeGTK::DrawWidgetBackground(n
                             &flags))
     return NS_OK;
 
   gfxContext* ctx = aContext->ThebesContext();
   nsPresContext *presContext = aFrame->PresContext();
 
   gfxRect rect = presContext->AppUnitsToGfxUnits(aRect);
   gfxRect dirtyRect = presContext->AppUnitsToGfxUnits(aDirtyRect);
-  gint scaleFactor = nsScreenGtk::GetGtkMonitorScaleFactor();
+  gint scaleFactor = ScreenHelperGTK::GetGTKMonitorScaleFactor();
 
   // Align to device pixels where sensible
   // to provide crisper and faster drawing.
   // Don't snap if it's a non-unit scale factor. We're going to have to take
   // slow paths then in any case.
   bool snapped = ctx->UserToDevicePixelSnapped(rect);
   if (snapped) {
     // Leave rect in device coords but make dirtyRect consistent.
@@ -1339,17 +1339,17 @@ nsNativeThemeGTK::GetWidgetBorder(nsDevi
                                &unusedFlags)) {
         moz_gtk_get_widget_border(gtkWidgetType, &aResult->left, &aResult->top,
                                   &aResult->right, &aResult->bottom, direction,
                                   IsFrameContentNodeInNamespace(aFrame, kNameSpaceID_XHTML));
       }
     }
   }
 
-  gint scale = nsScreenGtk::GetGtkMonitorScaleFactor();
+  gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor();
   aResult->top *= scale;
   aResult->right *= scale;
   aResult->bottom *= scale;
   aResult->left *= scale;
   return NS_OK;
 }
 
 bool
@@ -1399,17 +1399,17 @@ nsNativeThemeGTK::GetWidgetPadding(nsDev
         if (aWidgetType == NS_THEME_MENUITEM)
           moz_gtk_menuitem_get_horizontal_padding(&horizontal_padding);
         else
           moz_gtk_checkmenuitem_get_horizontal_padding(&horizontal_padding);
 
         aResult->left += horizontal_padding;
         aResult->right += horizontal_padding;
 
-        gint scale = nsScreenGtk::GetGtkMonitorScaleFactor();
+        gint scale = ScreenHelperGTK::GetGTKMonitorScaleFactor();
         aResult->top *= scale;
         aResult->right *= scale;
         aResult->bottom *= scale;
         aResult->left *= scale;
 
         return true;
       }
   }
@@ -1676,17 +1676,17 @@ nsNativeThemeGTK::GetMinimumWidgetSize(n
 
       moz_gtk_get_treeview_expander_size(&expander_size);
       aResult->width = aResult->height = expander_size;
       *aIsOverridable = false;
     }
     break;
   }
 
-  *aResult = *aResult * nsScreenGtk::GetGtkMonitorScaleFactor();
+  *aResult = *aResult * ScreenHelperGTK::GetGTKMonitorScaleFactor();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNativeThemeGTK::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType, 
                                      nsIAtom* aAttribute, bool* aShouldRepaint,
                                      const nsAttrValue* aOldValue)
deleted file mode 100644
--- a/widget/gtk/nsScreenGtk.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsScreenGtk.h"
-
-#include "nsIWidget.h"
-
-#include <gdk/gdk.h>
-#ifdef MOZ_X11
-#include <gdk/gdkx.h>
-#include <X11/Xatom.h>
-#endif
-#include <gtk/gtk.h>
-#include <dlfcn.h>
-#include "gfxPlatformGtk.h"
-
-static uint32_t sScreenId = 0;
-
-
-nsScreenGtk :: nsScreenGtk (  )
-  : mScreenNum(0),
-    mRect(0, 0, 0, 0),
-    mAvailRect(0, 0, 0, 0),
-    mId(++sScreenId)
-{
-}
-
-
-nsScreenGtk :: ~nsScreenGtk()
-{
-}
-
-
-NS_IMETHODIMP
-nsScreenGtk :: GetId(uint32_t *aId)
-{
-  *aId = mId;
-  return NS_OK;
-} // GetId
-
-
-NS_IMETHODIMP
-nsScreenGtk :: GetRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
-{
-  *outLeft = mRect.x;
-  *outTop = mRect.y;
-  *outWidth = mRect.width;
-  *outHeight = mRect.height;
-
-  return NS_OK;
-  
-} // GetRect
-
-
-NS_IMETHODIMP
-nsScreenGtk :: GetAvailRect(int32_t *outLeft, int32_t *outTop, int32_t *outWidth, int32_t *outHeight)
-{
-  *outLeft = mAvailRect.x;
-  *outTop = mAvailRect.y;
-  *outWidth = mAvailRect.width;
-  *outHeight = mAvailRect.height;
-
-  return NS_OK;
-  
-} // GetAvailRect
-
-gint
-nsScreenGtk :: GetGtkMonitorScaleFactor()
-{
-#if (MOZ_WIDGET_GTK >= 3)
-  // Since GDK 3.10
-  static auto sGdkScreenGetMonitorScaleFactorPtr = (gint (*)(GdkScreen*, gint))
-      dlsym(RTLD_DEFAULT, "gdk_screen_get_monitor_scale_factor");
-  if (sGdkScreenGetMonitorScaleFactorPtr) {
-      // FIXME: In the future, we'll want to fix this for GTK on Wayland which
-      // supports a variable scale factor per display.
-      GdkScreen *screen = gdk_screen_get_default();
-      return sGdkScreenGetMonitorScaleFactorPtr(screen, 0);
-  }
-#endif
-    return 1;
-}
-
-double
-nsScreenGtk :: GetDPIScale()
-{
-  double dpiScale = nsIWidget::DefaultScaleOverride();
-  if (dpiScale <= 0.0) {
-    dpiScale = GetGtkMonitorScaleFactor() * gfxPlatformGtk::GetDPIScale();
-  }
-  return dpiScale;
-}
-
-NS_IMETHODIMP 
-nsScreenGtk :: GetPixelDepth(int32_t *aPixelDepth)
-{
-  GdkVisual * visual = gdk_screen_get_system_visual(gdk_screen_get_default());
-  *aPixelDepth = gdk_visual_get_depth(visual);
-
-  return NS_OK;
-
-} // GetPixelDepth
-
-NS_IMETHODIMP 
-nsScreenGtk :: GetColorDepth(int32_t *aColorDepth)
-{
-  return GetPixelDepth ( aColorDepth );
-
-} // GetColorDepth
-
-NS_IMETHODIMP
-nsScreenGtk::GetDefaultCSSScaleFactor(double* aScaleFactor)
-{
-  *aScaleFactor = GetDPIScale();
-  return NS_OK;
-}
-
-void
-nsScreenGtk :: Init (GdkWindow *aRootWindow)
-{
-  gint scale = nsScreenGtk::GetGtkMonitorScaleFactor();
-  gint width = gdk_screen_width()*scale;
-  gint height = gdk_screen_height()*scale;
-
-  // We listen for configure events on the root window to pick up
-  // changes to this rect.  We could listen for "size_changed" signals
-  // on the default screen to do this, except that doesn't work with
-  // versions of GDK predating the GdkScreen object.  See bug 256646.
-  mAvailRect = mRect = nsIntRect(0, 0, width, height);
-
-#ifdef MOZ_X11
-  // We need to account for the taskbar, etc in the available rect.
-  // See http://freedesktop.org/Standards/wm-spec/index.html#id2767771
-
-  // XXX do we care about _NET_WM_STRUT_PARTIAL?  That will
-  // add much more complexity to the code here (our screen
-  // could have a non-rectangular shape), but should
-  // lead to greater accuracy.
-
-  long *workareas;
-  GdkAtom type_returned;
-  int format_returned;
-  int length_returned;
-
-  GdkAtom cardinal_atom = gdk_x11_xatom_to_atom(XA_CARDINAL);
-
-  gdk_error_trap_push();
-
-  // gdk_property_get uses (length + 3) / 4, hence G_MAXLONG - 3 here.
-  if (!gdk_property_get(aRootWindow,
-                        gdk_atom_intern ("_NET_WORKAREA", FALSE),
-                        cardinal_atom,
-                        0, G_MAXLONG - 3, FALSE,
-                        &type_returned,
-                        &format_returned,
-                        &length_returned,
-                        (guchar **) &workareas)) {
-    // This window manager doesn't support the freedesktop standard.
-    // Nothing we can do about it, so assume full screen size.
-    return;
-  }
-
-  // Flush the X queue to catch errors now.
-  gdk_flush();
-
-  if (!gdk_error_trap_pop() &&
-      type_returned == cardinal_atom &&
-      length_returned && (length_returned % 4) == 0 &&
-      format_returned == 32) {
-    int num_items = length_returned / sizeof(long);
-
-    for (int i = 0; i < num_items; i += 4) {
-      nsIntRect workarea(workareas[i],     workareas[i + 1],
-                         workareas[i + 2], workareas[i + 3]);
-      if (!mRect.Contains(workarea)) {
-        // Note that we hit this when processing screen size changes,
-        // since we'll get the configure event before the toolbars have
-        // been moved.  We'll end up cleaning this up when we get the
-        // change notification to the _NET_WORKAREA property.  However,
-        // we still want to listen to both, so we'll handle changes
-        // properly for desktop environments that don't set the
-        // _NET_WORKAREA property.
-        NS_WARNING("Invalid bounds");
-        continue;
-      }
-
-      mAvailRect.IntersectRect(mAvailRect, workarea);
-    }
-  }
-  g_free (workareas);
-#endif
-}
-
-#ifdef MOZ_X11
-void
-nsScreenGtk :: Init (XineramaScreenInfo *aScreenInfo)
-{
-  nsIntRect xineRect(aScreenInfo->x_org, aScreenInfo->y_org,
-                     aScreenInfo->width, aScreenInfo->height);
-
-  mScreenNum = aScreenInfo->screen_number;
-
-  mAvailRect = mRect = xineRect;
-}
-#endif
deleted file mode 100644
--- a/widget/gtk/nsScreenGtk.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef nsScreenGtk_h___
-#define nsScreenGtk_h___
-
-#include "nsBaseScreen.h"
-#include "nsRect.h"
-#include "gdk/gdk.h"
-#ifdef MOZ_X11
-#include <X11/Xlib.h>
-
-// from Xinerama.h
-typedef struct {
-   int   screen_number;
-   short x_org;
-   short y_org;
-   short width;
-   short height;
-} XineramaScreenInfo;
-#endif /* MOZ_X11 */
-
-//------------------------------------------------------------------------
-
-class nsScreenGtk : public nsBaseScreen
-{
-public:
-  nsScreenGtk();
-  ~nsScreenGtk();
-
-  NS_IMETHOD GetId(uint32_t* aId) override;
-  NS_IMETHOD GetRect(int32_t* aLeft, int32_t* aTop,
-                     int32_t* aWidth, int32_t* aHeight) override;
-  NS_IMETHOD GetAvailRect(int32_t* aLeft, int32_t* aTop,
-                          int32_t* aWidth, int32_t* aHeight) override;
-  NS_IMETHOD GetPixelDepth(int32_t* aPixelDepth) override;
-  NS_IMETHOD GetColorDepth(int32_t* aColorDepth) override;
-  NS_IMETHOD GetDefaultCSSScaleFactor(double* aScaleFactor) override;
-
-  void Init(GdkWindow *aRootWindow);
-#ifdef MOZ_X11
-  void Init(XineramaScreenInfo *aScreenInfo);
-#endif /* MOZ_X11 */
-
-  static gint    GetGtkMonitorScaleFactor();
-  static double  GetDPIScale();
-
-private:
-  uint32_t mScreenNum;
-  nsIntRect mRect;
-  nsIntRect mAvailRect;
-  uint32_t mId;
-};
-
-#endif  // nsScreenGtk_h___
--- a/widget/gtk/nsWidgetFactory.cpp
+++ b/widget/gtk/nsWidgetFactory.cpp
@@ -24,17 +24,16 @@
 #endif
 #if (MOZ_WIDGET_GTK == 3)
 #include "nsApplicationChooser.h"
 #endif
 #include "nsColorPicker.h"
 #include "nsFilePicker.h"
 #include "nsSound.h"
 #include "nsBidiKeyboard.h"
-#include "nsScreenManagerGtk.h"
 #include "nsGTKToolkit.h"
 #include "WakeLockListener.h"
 
 #ifdef NS_PRINTING
 #include "nsPrintOptionsGTK.h"
 #include "nsPrintSession.h"
 #include "nsDeviceContextSpecG.h"
 #endif
@@ -49,16 +48,17 @@
 #include "GfxInfoX11.h"
 #endif
 
 #include "nsNativeThemeGTK.h"
 
 #include "nsIComponentRegistrar.h"
 #include "nsComponentManagerUtils.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/widget/ScreenManager.h"
 #include <gtk/gtk.h>
 
 using namespace mozilla;
 using namespace mozilla::widget;
 
 /* from nsFilePicker.js */
 #define XULFILEPICKER_CID \
   { 0x54ae32f8, 0x1dd2, 0x11b2, \
@@ -72,17 +72,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKey
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
 #ifdef MOZ_X11
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceGTK, nsIdleServiceGTK::GetInstance)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsClipboard, Init)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
 #endif
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsScreenManagerGtk)
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageToPixbuf)
 
 
 // from nsWindow.cpp
 extern bool gDisableNativeTheme;
 
 static nsresult
 nsNativeThemeGTKConstructor(nsISupports *aOuter, REFNSIID aIID,
@@ -238,17 +238,17 @@ static const mozilla::Module::CIDEntry k
     { &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor },
 #ifdef MOZ_X11
     { &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardConstructor, Module::MAIN_PROCESS_ONLY },
     { &kNS_CLIPBOARDHELPER_CID, false, nullptr, nsClipboardHelperConstructor },
     { &kNS_DRAGSERVICE_CID, false, nullptr, nsDragServiceConstructor, Module::MAIN_PROCESS_ONLY },
 #endif
     { &kNS_HTMLFORMATCONVERTER_CID, false, nullptr, nsHTMLFormatConverterConstructor },
     { &kNS_BIDIKEYBOARD_CID, false, nullptr, nsBidiKeyboardConstructor },
-    { &kNS_SCREENMANAGER_CID, false, nullptr, nsScreenManagerGtkConstructor,
+    { &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor,
       Module::MAIN_PROCESS_ONLY },
     { &kNS_THEMERENDERER_CID, false, nullptr, nsNativeThemeGTKConstructor },
 #ifdef NS_PRINTING
     { &kNS_PRINTSETTINGSSERVICE_CID, false, nullptr, nsPrintOptionsGTKConstructor },
     { &kNS_PRINTER_ENUMERATOR_CID, false, nullptr, nsPrinterEnumeratorGTKConstructor },
     { &kNS_PRINTSESSION_CID, false, nullptr, nsPrintSessionConstructor },
     { &kNS_DEVICE_CONTEXT_SPEC_CID, false, nullptr, nsDeviceContextSpecGTKConstructor },
     { &kNS_PRINTDIALOGSERVICE_CID, false, nullptr, nsPrintDialogServiceGTKConstructor },
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -29,17 +29,17 @@
 #include "nsWidgetsCID.h"
 #include "nsDragService.h"
 #include "nsIWidgetListener.h"
 #include "nsIScreenManager.h"
 #include "SystemTimeConverter.h"
 
 #include "nsGtkKeyUtils.h"
 #include "nsGtkCursors.h"
-#include "nsScreenGtk.h"
+#include "ScreenHelperGTK.h"
 
 #include <gtk/gtk.h>
 #if (MOZ_WIDGET_GTK == 3)
 #include <gtk/gtkx.h>
 #endif
 #ifdef MOZ_X11
 #include <gdk/gdkx.h>
 #include <X11/Xatom.h>
@@ -6434,17 +6434,17 @@ 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)
         return (*sGdkWindowGetScaleFactorPtr)(mGdkWindow);
 #endif
-    return nsScreenGtk::GetGtkMonitorScaleFactor();
+    return ScreenHelperGTK::GetGTKMonitorScaleFactor();
 }
 
 
 gint
 nsWindow::DevicePixelsToGdkCoordRoundUp(int pixels) {
     gint scale = GdkScaleFactor();
     return (pixels + scale - 1) / scale;
 }