[gtk+] x11: Port to new monitor api



commit d92fda2103bc79043465b5218323a14edd05183e
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Apr 3 00:12:39 2016 -0400

    x11: Port to new monitor api

 gdk/x11/Makefile.am      |    3 +
 gdk/x11/gdkdisplay-x11.c |   39 +++
 gdk/x11/gdkdisplay-x11.h |    3 +
 gdk/x11/gdkmonitor-x11.c |  102 ++++++
 gdk/x11/gdkmonitor-x11.h |   43 +++
 gdk/x11/gdkscreen-x11.c  |  774 ++++++++++++++++++++++------------------------
 gdk/x11/gdkscreen-x11.h  |    8 +-
 gdk/x11/gdkwindow-x11.c  |    5 +-
 gdk/x11/gdkx.h           |    1 +
 gdk/x11/gdkx11monitor.h  |   48 +++
 10 files changed, 620 insertions(+), 406 deletions(-)
---
diff --git a/gdk/x11/Makefile.am b/gdk/x11/Makefile.am
index c488a31..6223e7e 100644
--- a/gdk/x11/Makefile.am
+++ b/gdk/x11/Makefile.am
@@ -43,6 +43,8 @@ libgdk_x11_la_SOURCES =       \
        gdkglcontext-x11.h      \
        gdkkeys-x11.c           \
        gdkmain-x11.c           \
+       gdkmonitor-x11.c        \
+       gdkmonitor-x11.h        \
        gdkproperty-x11.c       \
        gdkscreen-x11.c         \
        gdkscreen-x11.h         \
@@ -76,6 +78,7 @@ libgdkx11include_HEADERS =    \
        gdkx11dnd.h             \
        gdkx11glcontext.h       \
        gdkx11keys.h            \
+       gdkx11monitor.h         \
        gdkx11property.h        \
        gdkx11screen.h          \
        gdkx11selection.h       \
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index 6804ed2..f7c79c4 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -180,6 +180,7 @@ G_DEFINE_TYPE_WITH_CODE (GdkX11Display, gdk_x11_display, GDK_TYPE_DISPLAY,
 static void
 gdk_x11_display_init (GdkX11Display *display)
 {
+  display->monitors = g_ptr_array_new_with_free_func (g_object_unref);
 }
 
 static void
@@ -1903,6 +1904,8 @@ gdk_x11_display_finalize (GObject *object)
   g_object_unref (display_x11->screen);
   g_list_free_full (display_x11->screens, g_object_unref);
 
+  g_ptr_array_free (display_x11->monitors, TRUE);
+
   g_free (display_x11->startup_notification_id);
 
   /* X ID hashtable */
@@ -2903,6 +2906,38 @@ gdk_x11_display_get_default_seat (GdkDisplay *display)
   return NULL;
 }
 
+static int
+gdk_x11_display_get_n_monitors (GdkDisplay *display)
+{
+  GdkX11Display *x11_display = GDK_X11_DISPLAY (display);
+
+  return x11_display->monitors->len;
+}
+
+
+static GdkMonitor *
+gdk_x11_display_get_monitor (GdkDisplay *display,
+                             int         monitor_num)
+{
+  GdkX11Display *x11_display = GDK_X11_DISPLAY (display);
+
+  if (0 <= monitor_num || monitor_num < x11_display->monitors->len)
+    return (GdkMonitor *)x11_display->monitors->pdata[monitor_num];
+
+  return NULL;
+}
+
+static GdkMonitor *
+gdk_x11_display_get_primary_monitor (GdkDisplay *display)
+{
+  GdkX11Display *x11_display = GDK_X11_DISPLAY (display);
+
+  if (0 <= x11_display->primary_monitor && x11_display->primary_monitor < x11_display->monitors->len)
+    return x11_display->monitors->pdata[x11_display->primary_monitor];
+
+  return NULL;
+}
+
 static void
 gdk_x11_display_class_init (GdkX11DisplayClass * class)
 {
@@ -2959,5 +2994,9 @@ gdk_x11_display_class_init (GdkX11DisplayClass * class)
 
   display_class->get_default_seat = gdk_x11_display_get_default_seat;
 
+  display_class->get_n_monitors = gdk_x11_display_get_n_monitors;
+  display_class->get_monitor = gdk_x11_display_get_monitor;
+  display_class->get_primary_monitor = gdk_x11_display_get_primary_monitor;
+
   _gdk_x11_windowing_init ();
 }
diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h
index eb43feb..48100dc 100644
--- a/gdk/x11/gdkdisplay-x11.h
+++ b/gdk/x11/gdkdisplay-x11.h
@@ -100,6 +100,9 @@ struct _GdkX11Display
   /* input GdkWindow list */
   GList *input_windows;
 
+  GPtrArray *monitors;
+  int primary_monitor;
+
   /* Startup notification */
   gchar *startup_notification_id;
 
diff --git a/gdk/x11/gdkmonitor-x11.c b/gdk/x11/gdkmonitor-x11.c
new file mode 100644
index 0000000..899511a
--- /dev/null
+++ b/gdk/x11/gdkmonitor-x11.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright © 2016 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#include "gdkmonitor-x11.h"
+#include "gdkscreen-x11.h"
+
+
+G_DEFINE_TYPE (GdkX11Monitor, gdk_x11_monitor, GDK_TYPE_MONITOR)
+
+static gboolean
+gdk_monitor_has_fullscreen_window (GdkMonitor *monitor)
+{
+  GdkScreen *screen = gdk_display_get_default_screen (monitor->display);
+  GList *toplevels, *l;
+  GdkWindow *window;
+  gboolean has_fullscreen;
+
+  toplevels = gdk_screen_get_toplevel_windows (screen);
+
+  has_fullscreen = FALSE;
+  for (l = toplevels; l; l = l->next)
+    {
+      window = l->data;
+
+      if ((gdk_window_get_state (window) & GDK_WINDOW_STATE_FULLSCREEN) == 0)
+        continue;
+
+      if (gdk_window_get_fullscreen_mode (window) == GDK_FULLSCREEN_ON_ALL_MONITORS ||
+          gdk_display_get_monitor_at_window (monitor->display, window) == monitor)
+        {
+          has_fullscreen = TRUE;
+          break;
+        }
+    }
+
+  g_list_free (toplevels);
+
+  return has_fullscreen;
+}
+
+static void
+gdk_x11_monitor_get_workarea (GdkMonitor   *monitor,
+                              GdkRectangle *dest)
+{
+  GdkScreen *screen = gdk_display_get_default_screen (monitor->display);
+  GdkRectangle workarea;
+
+  gdk_monitor_get_geometry (monitor, dest);
+
+  /* The EWMH constrains workarea to be a rectangle, so it
+   * can't adequately deal with L-shaped monitor arrangements.
+   * As a workaround, we ignore the workarea for anything
+   * but the primary monitor. Since that is where the 'desktop
+   * chrome' usually lives, this works ok in practice.
+   */
+  if (gdk_monitor_is_primary (monitor) &&
+      !gdk_monitor_has_fullscreen_window (monitor))
+    {
+      gdk_x11_screen_get_work_area (screen, &workarea);
+      if (gdk_rectangle_intersect (dest, &workarea, &workarea))
+        *dest = workarea;
+    }
+}
+
+static void
+gdk_x11_monitor_init (GdkX11Monitor *monitor)
+{
+}
+
+static void
+gdk_x11_monitor_class_init (GdkX11MonitorClass *class)
+{
+  GDK_MONITOR_CLASS (class)->get_workarea = gdk_x11_monitor_get_workarea;
+}
+
+XID
+gdk_x11_monitor_get_output (GdkMonitor *monitor)
+{
+  g_return_val_if_fail (GDK_IS_X11_MONITOR (monitor), 0);
+
+  return GDK_X11_MONITOR (monitor)->output;
+}
+
diff --git a/gdk/x11/gdkmonitor-x11.h b/gdk/x11/gdkmonitor-x11.h
new file mode 100644
index 0000000..de8b1dc
--- /dev/null
+++ b/gdk/x11/gdkmonitor-x11.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright © 2016 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDK_X11_MONITOR_PRIVATE_H__
+#define __GDK_X11_MONITOR_PRIVATE_H__
+
+#include <glib.h>
+#include <gio/gio.h>
+#include <X11/Xlib.h>
+
+#include "gdkmonitorprivate.h"
+
+#include "gdkx11monitor.h"
+
+
+struct _GdkX11Monitor
+{
+  GdkMonitor parent;
+
+  XID output;
+  guint add     : 1;
+  guint remove  : 1;
+};
+
+struct _GdkX11MonitorClass {
+  GdkMonitorClass parent_class;
+};
+
+#endif
diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c
index 2cb62ff..7dfe373 100644
--- a/gdk/x11/gdkscreen-x11.c
+++ b/gdk/x11/gdkscreen-x11.c
@@ -25,6 +25,7 @@
 #include "gdkdisplay-x11.h"
 #include "gdkprivate-x11.h"
 #include "xsettings-client.h"
+#include "gdkmonitor-x11.h"
 
 #include <glib.h>
 
@@ -44,7 +45,6 @@
 static void         gdk_x11_screen_dispose     (GObject                  *object);
 static void         gdk_x11_screen_finalize    (GObject                  *object);
 static void        init_randr_support         (GdkScreen         *screen);
-static void        deinit_multihead           (GdkScreen         *screen);
 
 enum
 {
@@ -64,17 +64,6 @@ struct _NetWmSupportedAtoms
   gulong n_atoms;
 };
 
-struct _GdkX11Monitor
-{
-  GdkRectangle  geometry;
-  XID          output;
-  int          width_mm;
-  int          height_mm;
-  char *       output_name;
-  char *       manufacturer;
-};
-
-
 static void
 gdk_x11_screen_init (GdkX11Screen *screen)
 {
@@ -171,50 +160,9 @@ gdk_x11_screen_finalize (GObject *object)
 
   g_free (x11_screen->window_manager_name);
 
-  deinit_multihead (GDK_SCREEN (object));
-  
   G_OBJECT_CLASS (gdk_x11_screen_parent_class)->finalize (object);
 }
 
-static gint
-gdk_x11_screen_get_n_monitors (GdkScreen *screen)
-{
-  return GDK_X11_SCREEN (screen)->n_monitors;
-}
-
-static gint
-gdk_x11_screen_get_primary_monitor (GdkScreen *screen)
-{
-  return GDK_X11_SCREEN (screen)->primary_monitor;
-}
-
-static gint
-gdk_x11_screen_get_monitor_width_mm (GdkScreen *screen,
-                                     gint       monitor_num)
-{
-  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
-
-  return x11_screen->monitors[monitor_num].width_mm;
-}
-
-static gint
-gdk_x11_screen_get_monitor_height_mm (GdkScreen *screen,
-                                     gint       monitor_num)
-{
-  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
-
-  return x11_screen->monitors[monitor_num].height_mm;
-}
-
-static gchar *
-gdk_x11_screen_get_monitor_plug_name (GdkScreen *screen,
-                                     gint       monitor_num)
-{
-  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
-
-  return g_strdup (x11_screen->monitors[monitor_num].output_name);
-}
-
 /**
  * gdk_x11_screen_get_monitor_output:
  * @screen: (type GdkX11Screen): a #GdkScreen
@@ -233,29 +181,15 @@ gdk_x11_screen_get_monitor_output (GdkScreen *screen,
                                    gint       monitor_num)
 {
   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
+  GdkX11Display *x11_display = GDK_X11_DISPLAY (x11_screen->display);
+  GdkX11Monitor *monitor;
 
   g_return_val_if_fail (GDK_IS_SCREEN (screen), None);
   g_return_val_if_fail (monitor_num >= 0, None);
-  g_return_val_if_fail (monitor_num < x11_screen->n_monitors, None);
+  g_return_val_if_fail (monitor_num < x11_display->monitors->len, None);
 
-  return x11_screen->monitors[monitor_num].output;
-}
-
-static void
-gdk_x11_screen_get_monitor_geometry (GdkScreen    *screen,
-                                    gint          monitor_num,
-                                    GdkRectangle *dest)
-{
-  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
-
-  if (dest)
-    {
-      *dest = x11_screen->monitors[monitor_num].geometry;
-      dest->x /= x11_screen->window_scale;
-      dest->y /= x11_screen->window_scale;
-      dest->width /= x11_screen->window_scale;
-      dest->height /= x11_screen->window_scale;
-    }
+  monitor = x11_display->monitors->pdata[monitor_num];
+  return monitor->output;
 }
 
 static int
@@ -295,9 +229,9 @@ get_current_desktop (GdkScreen *screen)
   return workspace;
 }
 
-static void
-get_work_area (GdkScreen    *screen,
-               GdkRectangle *area)
+void
+gdk_x11_screen_get_work_area (GdkScreen    *screen,
+                              GdkRectangle *area)
 {
   GdkX11Screen   *x11_screen = GDK_X11_SCREEN (screen);
   Atom            workarea;
@@ -371,71 +305,6 @@ out:
     XFree (ret_workarea);
 }
 
-static gboolean
-gdk_x11_screen_monitor_has_fullscreen_window (GdkScreen *screen,
-                                              gint       monitor)
-{
-  GList *toplevels, *l;
-  GdkWindow *window;
-  gboolean has_fullscreen;
-
-  toplevels = gdk_screen_get_toplevel_windows (screen);
-
-  has_fullscreen = FALSE;
-
-  for (l = toplevels; l; l = l->next)
-    {
-      window = l->data;
-
-      if ((gdk_window_get_state (window) & GDK_WINDOW_STATE_FULLSCREEN) == 0)
-        continue;
-
-      if (gdk_window_get_fullscreen_mode (window) == GDK_FULLSCREEN_ON_ALL_MONITORS ||
-          gdk_screen_get_monitor_at_window (screen, window) == monitor)
-        {
-          has_fullscreen = TRUE;
-          break;
-        }
-    }
-
-  g_list_free (toplevels);
-
-  return has_fullscreen;
-}
-
-static void
-gdk_x11_screen_get_monitor_workarea (GdkScreen    *screen,
-                                     gint          monitor_num,
-                                     GdkRectangle *dest)
-{
-  GdkRectangle workarea;
-
-  gdk_x11_screen_get_monitor_geometry (screen, monitor_num, dest);
-
-  /* The EWMH constrains workarea to be a rectangle, so it
-   * can't adequately deal with L-shaped monitor arrangements.
-   * As a workaround, we ignore the workarea for anything
-   * but the primary monitor. Since that is where the 'desktop
-   * chrome' usually lives, this works ok in practice.
-   */
-  if (monitor_num == GDK_X11_SCREEN (screen)->primary_monitor &&
-      !gdk_x11_screen_monitor_has_fullscreen_window (screen, monitor_num))
-    {
-      get_work_area (screen, &workarea);
-      if (gdk_rectangle_intersect (dest, &workarea, &workarea))
-        *dest = workarea;
-    }
-}
-
-static gint
-gdk_x11_screen_get_monitor_scale_factor (GdkScreen *screen,
-                                        gint       monitor_num)
-{
-  GdkX11Screen *screen_x11 = GDK_X11_SCREEN (screen);
-
-  return screen_x11->window_scale;
-}
-
 static GdkVisual *
 gdk_x11_screen_get_rgba_visual (GdkScreen *screen)
 {
@@ -494,81 +363,52 @@ check_is_composited (GdkDisplay *display,
   return xwindow != None;
 }
 
-static void
-init_monitor_geometry (GdkX11Monitor *monitor,
-                       int x, int y, int width, int height)
-{
-  monitor->geometry.x = x;
-  monitor->geometry.y = y;
-  monitor->geometry.width = width;
-  monitor->geometry.height = height;
-
-  monitor->output = None;
-  monitor->width_mm = -1;
-  monitor->height_mm = -1;
-  monitor->output_name = NULL;
-  monitor->manufacturer = NULL;
-}
-
-static void
-free_monitors (GdkX11Monitor *monitors,
-               gint           n_monitors)
+static GdkX11Monitor *
+find_monitor_by_output (GdkX11Display *x11_display, RROutput output)
 {
   int i;
 
-  for (i = 0; i < n_monitors; ++i)
+  for (i = 0; i < x11_display->monitors->len; i++)
     {
-      g_free (monitors[i].output_name);
-      g_free (monitors[i].manufacturer);
+      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+      if (monitor->output == output)
+        return monitor;
     }
 
-  g_free (monitors);
+  return NULL;
 }
 
-#ifdef HAVE_RANDR
-static int
-monitor_compare_function (GdkX11Monitor *monitor1,
-                          GdkX11Monitor *monitor2)
+static GdkSubpixelLayout
+translate_subpixel_order (int subpixel)
 {
-  /* Sort the leftmost/topmost monitors first.
-   * For "cloned" monitors, sort the bigger ones first
-   * (giving preference to taller monitors over wider
-   * monitors)
-   */
-
-  if (monitor1->geometry.x != monitor2->geometry.x)
-    return monitor1->geometry.x - monitor2->geometry.x;
-
-  if (monitor1->geometry.y != monitor2->geometry.y)
-    return monitor1->geometry.y - monitor2->geometry.y;
-
-  if (monitor1->geometry.height != monitor2->geometry.height)
-    return - (monitor1->geometry.height - monitor2->geometry.height);
-
-  if (monitor1->geometry.width != monitor2->geometry.width)
-    return - (monitor1->geometry.width - monitor2->geometry.width);
-
-  return 0;
+  switch (subpixel)
+    {
+    case 1: return GDK_SUBPIXEL_LAYOUT_HORIZONTAL_RGB;
+    case 2: return GDK_SUBPIXEL_LAYOUT_HORIZONTAL_BGR;
+    case 3: return GDK_SUBPIXEL_LAYOUT_VERTICAL_RGB;
+    case 4: return GDK_SUBPIXEL_LAYOUT_VERTICAL_BGR;
+    case 5: return GDK_SUBPIXEL_LAYOUT_NONE;
+    default: return GDK_SUBPIXEL_LAYOUT_UNKNOWN;
+    }
 }
-#endif
 
 static gboolean
-init_randr15 (GdkScreen *screen)
+init_randr15 (GdkScreen *screen, gboolean *changed)
 {
 #ifdef HAVE_RANDR15
   GdkDisplay *display = gdk_screen_get_display (screen);
-  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
+  GdkX11Display *x11_display = GDK_X11_DISPLAY (display);
   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
   XRRScreenResources *resources;
   RROutput primary_output = None;
   RROutput first_output = None;
   int i;
-  GArray *monitors;
   gboolean randr12_compat = FALSE;
   XRRMonitorInfo *rr_monitors;
   int num_rr_monitors;
+  int old_primary;
 
-  if (!display_x11->have_randr15)
+  if (!x11_display->have_randr15)
     return FALSE;
 
   resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay,
@@ -583,13 +423,22 @@ init_randr15 (GdkScreen *screen)
   if (!rr_monitors)
     return FALSE;
 
-  monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor), num_rr_monitors);
+  for (i = 0; i < x11_display->monitors->len; i++)
+    {
+      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+      monitor->add = FALSE;
+      monitor->remove = TRUE;
+    }
 
   for (i = 0; i < num_rr_monitors; i++)
     {
       RROutput output = rr_monitors[i].outputs[0];
       XRROutputInfo *output_info;
-      GdkX11Monitor monitor;
+      GdkX11Monitor *monitor;
+      GdkRectangle geometry;
+      GdkRectangle newgeo;
+      char *name;
+      int refresh_rate = 0;
 
       gdk_x11_display_error_trap_push (display);
       output_info = XRRGetOutputInfo (x11_screen->xdisplay, resources, output);
@@ -611,21 +460,69 @@ init_randr15 (GdkScreen *screen)
       if (first_output == None)
         first_output = output;
 
-      init_monitor_geometry (&monitor,
-                             rr_monitors[i].x,
-                             rr_monitors[i].y,
-                             rr_monitors[i].width,
-                             rr_monitors[i].height);
+      if (output_info->crtc)
+        {
+          XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc);
+          int j;
+
+          for (j = 0; j < resources->nmode; j++)
+            {
+              XRRModeInfo *xmode = &resources->modes[j];
+              if (xmode->id == crtc->mode)
+                {
+                  refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal *xmode->vTotal);
+                  break;
+                }
+            }
+
+          XRRFreeCrtcInfo (crtc);
+        }
+
+      monitor = find_monitor_by_output (x11_display, output);
+      if (monitor)
+        monitor->remove = FALSE;
+      else
+        {
+          monitor = g_object_new (GDK_TYPE_X11_MONITOR,
+                                  "display", display,
+                                  NULL);
+          monitor->output = output;
+          monitor->add = TRUE;
+          g_ptr_array_add (x11_display->monitors, monitor);
+        }
 
-      monitor.width_mm = rr_monitors[i].mwidth;
-      monitor.height_mm = rr_monitors[i].mheight;
-      monitor.output = output;
-      monitor.output_name = g_strndup (output_info->name, output_info->nameLen);
+      gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry);
+      name = g_strndup (output_info->name, output_info->nameLen);
+
+      newgeo.x = rr_monitors[i].x / x11_screen->window_scale;
+      newgeo.y = rr_monitors[i].y / x11_screen->window_scale;
+      newgeo.width = rr_monitors[i].width / x11_screen->window_scale;
+      newgeo.height = rr_monitors[i].height / x11_screen->window_scale;
+      if (newgeo.x != geometry.x ||
+          newgeo.y != geometry.y ||
+          newgeo.width != geometry.width ||
+          newgeo.height != geometry.height ||
+          rr_monitors[i].mwidth != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) ||
+          rr_monitors[i].mheight != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) ||
+          g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor))))
+        *changed = TRUE;
+
+      gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y);
+      gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height);
+      g_object_notify (G_OBJECT (monitor), "workarea");
+      gdk_monitor_set_physical_size (GDK_MONITOR (monitor),
+                                     rr_monitors[i].mwidth,
+                                     rr_monitors[i].mheight);
+      gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor),
+                                       translate_subpixel_order (output_info->subpixel_order));
+      gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate);
+      gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale);
+      gdk_monitor_set_model (GDK_MONITOR (monitor), name);
+      g_free (name);
 
       if (rr_monitors[i].primary)
-        primary_output = monitor.output;
+        primary_output = monitor->output;
 
-      g_array_append_val (monitors, monitor);
       XRRFreeOutputInfo (output_info);
     }
 
@@ -635,61 +532,82 @@ init_randr15 (GdkScreen *screen)
   /* non RandR 1.2+ X driver doesn't return any usable multihead data */
   if (randr12_compat)
     {
-      guint n_monitors = monitors->len;
-
-      free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE), n_monitors);
+      for (i = 0; i < x11_display->monitors->len; i++)
+        {
+          GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+          if (monitor->remove)
+            gdk_display_monitor_removed (display, GDK_MONITOR (monitor));
+        }
+      g_ptr_array_remove_range (x11_display->monitors, 0, x11_display->monitors->len);
       return FALSE;
     }
 
-  g_array_sort (monitors, (GCompareFunc) monitor_compare_function);
-
-  x11_screen->n_monitors = monitors->len;
-  x11_screen->monitors = (GdkX11Monitor *) g_array_free (monitors, FALSE);
-
-  x11_screen->primary_monitor = 0;
+  for (i = x11_display->monitors->len - 1; i >= 0; i--)
+    {
+      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+      if (monitor->add)
+        {
+          gdk_display_monitor_added (display, GDK_MONITOR (monitor));
+          *changed = TRUE;
+        }
+      else if (monitor->remove)
+        {
+          g_object_ref (monitor);
+          g_ptr_array_remove (x11_display->monitors, monitor);
+          gdk_display_monitor_removed (display, GDK_MONITOR (monitor));
+          g_object_unref (monitor);
+          *changed = TRUE;
+        }
+    }
 
-  for (i = 0; i < x11_screen->n_monitors; ++i)
+  old_primary = x11_display->primary_monitor;
+  x11_display->primary_monitor = 0;
+  for (i = 0; i < x11_display->monitors->len; ++i)
     {
-      if (x11_screen->monitors[i].output == primary_output)
+      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+      if (monitor->output == primary_output)
         {
-          x11_screen->primary_monitor = i;
+          x11_display->primary_monitor = i;
           break;
         }
 
       /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */
       if (primary_output == None &&
-          g_ascii_strncasecmp (x11_screen->monitors[i].output_name, "LVDS", 4) == 0)
+          g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0)
         {
-          x11_screen->primary_monitor = i;
+          x11_display->primary_monitor = i;
           break;
         }
 
       /* No primary specified and no LVDS found */
-      if (x11_screen->monitors[i].output == first_output)
-        x11_screen->primary_monitor = i;
+      if (monitor->output == first_output)
+        x11_display->primary_monitor = i;
     }
 
-  return x11_screen->n_monitors > 0;
+  if (x11_display->primary_monitor != old_primary)
+    *changed = TRUE;
+
+  return x11_display->monitors->len > 0;
 #endif
 
   return FALSE;
 }
 
 static gboolean
-init_randr13 (GdkScreen *screen)
+init_randr13 (GdkScreen *screen, gboolean *changed)
 {
 #ifdef HAVE_RANDR
   GdkDisplay *display = gdk_screen_get_display (screen);
-  GdkX11Display *display_x11 = GDK_X11_DISPLAY (display);
+  GdkX11Display *x11_display = GDK_X11_DISPLAY (display);
   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
   XRRScreenResources *resources;
   RROutput primary_output = None;
   RROutput first_output = None;
   int i;
-  GArray *monitors;
   gboolean randr12_compat = FALSE;
+  int old_primary;
 
-  if (!display_x11->have_randr13)
+  if (!x11_display->have_randr13)
       return FALSE;
 
   resources = XRRGetScreenResourcesCurrent (x11_screen->xdisplay,
@@ -697,7 +615,12 @@ init_randr13 (GdkScreen *screen)
   if (!resources)
     return FALSE;
 
-  monitors = g_array_sized_new (FALSE, TRUE, sizeof (GdkX11Monitor), resources->noutput);
+  for (i = 0; i < x11_display->monitors->len; i++)
+    {
+      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+      monitor->add = FALSE;
+      monitor->remove = TRUE;
+    }
 
   for (i = 0; i < resources->noutput; ++i)
     {
@@ -716,16 +639,66 @@ init_randr13 (GdkScreen *screen)
 
       if (output_info->crtc)
        {
-         GdkX11Monitor monitor;
+         GdkX11Monitor *monitor;
          XRRCrtcInfo *crtc = XRRGetCrtcInfo (x11_screen->xdisplay, resources, output_info->crtc);
+          char *name;
+          GdkRectangle geometry;
+          GdkRectangle newgeo;
+          int j;
+          int refresh_rate = 0;
 
-          init_monitor_geometry (&monitor, crtc->x, crtc->y, crtc->width, crtc->height);
-         monitor.output = output;
-         monitor.width_mm = output_info->mm_width;
-         monitor.height_mm = output_info->mm_height;
-         monitor.output_name = g_strndup (output_info->name, output_info->nameLen);
+          for (j = 0; j < resources->nmode; j++)
+            {
+              XRRModeInfo *xmode = &resources->modes[j];
+              if (xmode->id == crtc->mode)
+                {
+                  refresh_rate = (1000 * xmode->dotClock) / (xmode->hTotal *xmode->vTotal);
+                  break;
+                }
+            }
 
-         g_array_append_val (monitors, monitor);
+          monitor = find_monitor_by_output (x11_display, output);
+          if (monitor)
+            monitor->remove = FALSE;
+          else
+            {
+              monitor = g_object_new (gdk_x11_monitor_get_type (),
+                                      "display", display,
+                                      NULL);
+              monitor->output = output;
+              monitor->add = TRUE;
+              g_ptr_array_add (x11_display->monitors, monitor);
+            }
+
+          gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry);
+          name = g_strndup (output_info->name, output_info->nameLen);
+
+          newgeo.x = crtc->x / x11_screen->window_scale;
+          newgeo.y = crtc->y / x11_screen->window_scale;
+          newgeo.width = crtc->width / x11_screen->window_scale;
+          newgeo.height = crtc->height / x11_screen->window_scale;
+          if (newgeo.x != geometry.x ||
+              newgeo.y != geometry.y ||
+              newgeo.width != geometry.width ||
+              newgeo.height != geometry.height ||
+              output_info->mm_width != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) ||
+              output_info->mm_height != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)) ||
+              g_strcmp0 (name, gdk_monitor_get_model (GDK_MONITOR (monitor))) != 0)
+            *changed = TRUE;
+
+          gdk_monitor_set_position (GDK_MONITOR (monitor), newgeo.x, newgeo.y);
+          gdk_monitor_set_size (GDK_MONITOR (monitor), newgeo.width, newgeo.height);
+          g_object_notify (G_OBJECT (monitor), "workarea");
+          gdk_monitor_set_physical_size (GDK_MONITOR (monitor),
+                                         output_info->mm_width,
+                                         output_info->mm_height);
+          gdk_monitor_set_subpixel_layout (GDK_MONITOR (monitor),
+                                           translate_subpixel_order (output_info->subpixel_order));
+          gdk_monitor_set_refresh_rate (GDK_MONITOR (monitor), refresh_rate);
+          gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale);
+          gdk_monitor_set_model (GDK_MONITOR (monitor), name);
+
+          g_free (name);
 
           XRRFreeCrtcInfo (crtc);
        }
@@ -738,193 +711,175 @@ init_randr13 (GdkScreen *screen)
 
   XRRFreeScreenResources (resources);
 
-  /* non RandR 1.2+ X driver doesn't return any usable multihead data */
   if (randr12_compat)
     {
-      guint n_monitors = monitors->len;
-
-      free_monitors ((GdkX11Monitor *)g_array_free (monitors, FALSE), n_monitors);
-
+      for (i = 0; i < x11_display->monitors->len; i++)
+        {
+          GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+          if (monitor->remove)
+            gdk_display_monitor_removed (display, GDK_MONITOR (monitor));
+        }
+      g_ptr_array_remove_range (x11_display->monitors, 0, x11_display->monitors->len);
       return FALSE;
     }
 
-  g_array_sort (monitors, (GCompareFunc) monitor_compare_function);
-
-  x11_screen->n_monitors = monitors->len;
-  x11_screen->monitors = (GdkX11Monitor *)g_array_free (monitors, FALSE);
-
-  x11_screen->primary_monitor = 0;
+  for (i = x11_display->monitors->len - 1; i >= 0; i--)
+    {
+      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+      if (monitor->add)
+        {
+          gdk_display_monitor_added (display, GDK_MONITOR (monitor));
+          *changed = TRUE;
+        }
+      else if (monitor->remove)
+        {
+          g_object_ref (monitor);
+          g_ptr_array_remove (x11_display->monitors, monitor);
+          gdk_display_monitor_removed (display, GDK_MONITOR (monitor));
+          g_object_unref (monitor);
+          *changed = TRUE;
+        }
+    }
 
+  old_primary = x11_display->primary_monitor;
+  x11_display->primary_monitor = 0;
   primary_output = XRRGetOutputPrimary (x11_screen->xdisplay,
                                         x11_screen->xroot_window);
 
-  for (i = 0; i < x11_screen->n_monitors; ++i)
+  for (i = 0; i < x11_display->monitors->len; ++i)
     {
-      if (x11_screen->monitors[i].output == primary_output)
+      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+      if (monitor->output == primary_output)
         {
-          x11_screen->primary_monitor = i;
+          x11_display->primary_monitor = i;
           break;
         }
 
       /* No RandR1.3+ available or no primary set, fall back to prefer LVDS as primary if present */
       if (primary_output == None &&
-          g_ascii_strncasecmp (x11_screen->monitors[i].output_name, "LVDS", 4) == 0)
+          g_ascii_strncasecmp (gdk_monitor_get_model (GDK_MONITOR (monitor)), "LVDS", 4) == 0)
         {
-          x11_screen->primary_monitor = i;
+          x11_display->primary_monitor = i;
           break;
         }
 
       /* No primary specified and no LVDS found */
-      if (x11_screen->monitors[i].output == first_output)
-        x11_screen->primary_monitor = i;
+      if (monitor->output == first_output)
+        x11_display->primary_monitor = i;
     }
 
-  return x11_screen->n_monitors > 0;
+  if (x11_display->primary_monitor != old_primary)
+    *changed = TRUE;
+
+  return x11_display->monitors->len > 0;
 #endif
 
   return FALSE;
 }
 
-void
-_gdk_x11_screen_get_edge_monitors (GdkScreen *screen,
-                                   gint      *top,
-                                   gint      *bottom,
-                                   gint      *left,
-                                   gint      *right)
+static void
+init_no_multihead (GdkScreen *screen, gboolean *changed)
 {
   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
-  gint          top_most_pos = x11_screen->height;
-  gint          left_most_pos = x11_screen->width;
-  gint          bottom_most_pos = 0;
-  gint          right_most_pos = 0;
-  gint          monitor_num;
+  GdkX11Display *x11_display = GDK_X11_DISPLAY (x11_screen->display);
+  GdkX11Monitor *monitor;
+  GdkRectangle geometry;
+  int i;
 
-  for (monitor_num = 0; monitor_num < x11_screen->n_monitors; monitor_num++)
+  for (i = 0; i < x11_display->monitors->len; i++)
     {
-      gint monitor_x = x11_screen->monitors[monitor_num].geometry.x;
-      gint monitor_y = x11_screen->monitors[monitor_num].geometry.y;
-      gint monitor_max_x = monitor_x + x11_screen->monitors[monitor_num].geometry.width;
-      gint monitor_max_y = monitor_y + x11_screen->monitors[monitor_num].geometry.height;
-
-      if (left && left_most_pos > monitor_x)
-       {
-         left_most_pos = monitor_x;
-         *left = monitor_num;
-       }
-      if (right && right_most_pos < monitor_max_x)
-       {
-         right_most_pos = monitor_max_x;
-         *right = monitor_num;
-       }
-      if (top && top_most_pos > monitor_y)
-       {
-         top_most_pos = monitor_y;
-         *top = monitor_num;
-       }
-      if (bottom && bottom_most_pos < monitor_max_y)
-       {
-         bottom_most_pos = monitor_max_y;
-         *bottom = monitor_num;
-       }
+      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+      monitor->add = FALSE;
+      monitor->remove = TRUE;
     }
-}
-
-static void
-deinit_multihead (GdkScreen *screen)
-{
-  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
-
-  free_monitors (x11_screen->monitors, x11_screen->n_monitors);
-
-  x11_screen->n_monitors = 0;
-  x11_screen->monitors = NULL;
-}
-
-static gboolean
-compare_monitor (GdkX11Monitor *m1,
-                 GdkX11Monitor *m2)
-{
-  if (m1->geometry.x != m2->geometry.x ||
-      m1->geometry.y != m2->geometry.y ||
-      m1->geometry.width != m2->geometry.width ||
-      m1->geometry.height != m2->geometry.height)
-    return FALSE;
-
-  if (m1->width_mm != m2->width_mm ||
-      m1->height_mm != m2->height_mm)
-    return FALSE;
-
-  if (g_strcmp0 (m1->output_name, m2->output_name) != 0)
-    return FALSE;
 
-  if (g_strcmp0 (m1->manufacturer, m2->manufacturer) != 0)
-    return FALSE;
-
-  return TRUE;
-}
-
-static gboolean
-compare_monitors (GdkX11Monitor *monitors1, gint n_monitors1,
-                  GdkX11Monitor *monitors2, gint n_monitors2)
-{
-  gint i;
-
-  if (n_monitors1 != n_monitors2)
-    return FALSE;
-
-  for (i = 0; i < n_monitors1; i++)
+  monitor = find_monitor_by_output (x11_display, 0);
+  if (monitor)
+    monitor->remove = FALSE;
+  else
     {
-      if (!compare_monitor (monitors1 + i, monitors2 + i))
-        return FALSE;
+      monitor = g_object_new (gdk_x11_monitor_get_type (),
+                              "display", x11_display,
+                              NULL);
+      monitor->output = 0;
+      monitor->add = TRUE;
+      g_ptr_array_add (x11_display->monitors, monitor);
     }
 
-  return TRUE;
-}
-
-static void
-init_no_multihead (GdkScreen *screen)
-{
-  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
-
-  x11_screen->n_monitors = 1;
-  x11_screen->monitors = g_new0 (GdkX11Monitor, 1);
-  x11_screen->primary_monitor = 0;
-
-  init_monitor_geometry (x11_screen->monitors, 0, 0,
-                        WidthOfScreen (x11_screen->xscreen),
-                        HeightOfScreen (x11_screen->xscreen));
+  gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry);
+  if (0 != geometry.x ||
+      0 != geometry.y ||
+      gdk_screen_get_width (screen) != geometry.width ||
+      gdk_screen_get_height (screen) != geometry.height ||
+      gdk_screen_get_width_mm (screen) != gdk_monitor_get_width_mm (GDK_MONITOR (monitor)) ||
+      gdk_screen_get_height_mm (screen) != gdk_monitor_get_height_mm (GDK_MONITOR (monitor)))
+    *changed = TRUE;
+
+  gdk_monitor_set_position (GDK_MONITOR (monitor), 0, 0);
+  gdk_monitor_set_size (GDK_MONITOR (monitor),
+                        gdk_screen_get_width (screen),
+                        gdk_screen_get_height (screen));
+  g_object_notify (G_OBJECT (monitor), "workarea");
+  gdk_monitor_set_physical_size (GDK_MONITOR (monitor),
+                                 gdk_screen_get_height_mm (screen),
+                                 gdk_screen_get_height_mm (screen));
+  gdk_monitor_set_scale_factor (GDK_MONITOR (monitor), x11_screen->window_scale);
+
+  if (x11_display->primary_monitor != 0)
+    *changed = TRUE;
+  x11_display->primary_monitor = 0;
+
+  for (i = x11_display->monitors->len - 1; i >= 0; i--)
+    {
+      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+      if (monitor->add)
+        {
+          gdk_display_monitor_added (GDK_DISPLAY (x11_display), GDK_MONITOR (monitor));
+          *changed = TRUE;
+        }
+      else if (monitor->remove)
+        {
+          g_object_ref (monitor);
+          g_ptr_array_remove (x11_display->monitors, monitor);
+          gdk_display_monitor_removed (GDK_DISPLAY (x11_display), GDK_MONITOR (monitor));
+          g_object_unref (monitor);
+          *changed = TRUE;
+        }
+    }
 }
 
-static void
+static gboolean
 init_multihead (GdkScreen *screen)
 {
-  if (init_randr15 (screen))
-    return;
+  gboolean any_changed = FALSE;
 
-  if (init_randr13 (screen))
-    return;
+  if (!init_randr15 (screen, &any_changed) &&
+      !init_randr13 (screen, &any_changed))
+    init_no_multihead (screen, &any_changed);
 
-  init_no_multihead (screen);
+  return any_changed;
 }
 
 static void
 update_bounding_box (GdkScreen *screen)
 {
   GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
+  GdkX11Display *x11_display = GDK_X11_DISPLAY (x11_screen->display);
   gint i, x1, y1, x2, y2;
 
   x1 = y1 = G_MAXINT;
   x2 = y2 = G_MININT;
 
-  for (i = 0; i < x11_screen->n_monitors; i++)
+  for (i = 0; i < x11_display->monitors->len; i++)
     {
-      GdkX11Monitor *monitor;
-
-      monitor = &x11_screen->monitors[i];
-      x1 = MIN (x1, monitor->geometry.x);
-      y1 = MIN (y1, monitor->geometry.y);
-      x2 = MAX (x2, monitor->geometry.x + monitor->geometry.width);
-      y2 = MAX (y2, monitor->geometry.y + monitor->geometry.height);
+      GdkX11Monitor *monitor = x11_display->monitors->pdata[i];
+      GdkRectangle geometry;
+
+      gdk_monitor_get_geometry (GDK_MONITOR (monitor), &geometry);
+      x1 = MIN (x1, geometry.x);
+      y1 = MIN (y1, geometry.y);
+      x2 = MAX (x2, geometry.x + geometry.width);
+      y2 = MAX (y2, geometry.y + geometry.height);
     }
 
   x11_screen->width = x2 - x1;
@@ -963,9 +918,9 @@ _gdk_x11_screen_new (GdkDisplay *display,
   else
     x11_screen->window_scale = 1;
 
-  init_multihead (screen);
   init_randr_support (screen);
-  
+  init_multihead (screen);
+
   _gdk_x11_screen_init_visuals (screen);
   _gdk_x11_screen_init_root_window (screen);
   update_bounding_box (screen);
@@ -977,8 +932,10 @@ void
 _gdk_x11_screen_set_window_scale (GdkX11Screen *x11_screen,
                                  gint          scale)
 {
+  GdkX11Display *x11_display = GDK_X11_DISPLAY (x11_screen->display);
   GList *toplevels, *l;
   GdkWindow *root;
+  int i;
 
   if (x11_screen->window_scale == scale)
     return;
@@ -997,6 +954,13 @@ _gdk_x11_screen_set_window_scale (GdkX11Screen *x11_screen,
       _gdk_x11_window_set_window_scale (window, scale);
     }
 
+  for (i = 0; i < x11_display->monitors->len; i++)
+    {
+      GdkMonitor *monitor = GDK_MONITOR (x11_display->monitors->pdata[i]);
+
+      gdk_monitor_set_scale_factor (monitor, scale);
+    }
+
   g_signal_emit_by_name (GDK_SCREEN (x11_screen), "monitors-changed");
 }
 
@@ -1048,29 +1012,7 @@ init_randr_support (GdkScreen *screen)
 static void
 process_monitors_change (GdkScreen *screen)
 {
-  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
-  gint          n_monitors;
-  gint          primary_monitor;
-  GdkX11Monitor        *monitors;
-  gboolean changed;
-
-  primary_monitor = x11_screen->primary_monitor;
-  n_monitors = x11_screen->n_monitors;
-  monitors = x11_screen->monitors;
-
-  x11_screen->n_monitors = 0;
-  x11_screen->monitors = NULL;
-
-  init_multihead (screen);
-
-  changed =
-    !compare_monitors (monitors, n_monitors,
-                      x11_screen->monitors, x11_screen->n_monitors) ||
-    x11_screen->primary_monitor != primary_monitor;
-
-  free_monitors (monitors, n_monitors);
-
-  if (changed)
+  if (init_multihead (screen))
     {
       update_bounding_box (screen);
       g_signal_emit_by_name (screen, "monitors-changed");
@@ -1117,6 +1059,50 @@ _gdk_x11_screen_size_changed (GdkScreen *screen,
 }
 
 void
+_gdk_x11_screen_get_edge_monitors (GdkScreen *screen,
+                                   gint      *top,
+                                   gint      *bottom,
+                                   gint      *left,
+                                   gint      *right)
+{
+  GdkX11Screen *x11_screen = GDK_X11_SCREEN (screen);
+  gint          top_most_pos = x11_screen->height;
+  gint          left_most_pos = x11_screen->width;
+  gint          bottom_most_pos = 0;
+  gint          right_most_pos = 0;
+  gint          i;
+
+  for (i = 0; i < x11_screen->monitors->len; i++)
+    {
+      GdkMonitor *monitor = x11_screen->monitors->pdata[i];
+      GdkRectangle geometry;
+
+      gdk_monitor_get_geometry (monitor, &geometry);
+
+      if (left && left_most_pos > geometry.x)
+       {
+         left_most_pos = geometry.x;
+         *left = i;
+       }
+      if (right && right_most_pos < geometry.x + geometry.width)
+       {
+         right_most_pos = geometry.x + geometry.width;
+         *right = i;
+       }
+      if (top && top_most_pos > geometry.y)
+       {
+         top_most_pos = geometry.y;
+         *top = i;
+       }
+      if (bottom && bottom_most_pos < geometry.y + geometry.height)
+       {
+         bottom_most_pos = geometry.y + geometry.height;
+         *bottom = i;
+       }
+    }
+}
+
+void
 _gdk_x11_screen_window_manager_changed (GdkScreen *screen)
 {
   g_signal_emit (screen, signals[WINDOW_MANAGER_CHANGED], 0);
@@ -1567,14 +1553,6 @@ gdk_x11_screen_class_init (GdkX11ScreenClass *klass)
   screen_class->get_height_mm = gdk_x11_screen_get_height_mm;
   screen_class->get_number = gdk_x11_screen_get_number;
   screen_class->get_root_window = gdk_x11_screen_get_root_window;
-  screen_class->get_n_monitors = gdk_x11_screen_get_n_monitors;
-  screen_class->get_primary_monitor = gdk_x11_screen_get_primary_monitor;
-  screen_class->get_monitor_width_mm = gdk_x11_screen_get_monitor_width_mm;
-  screen_class->get_monitor_height_mm = gdk_x11_screen_get_monitor_height_mm;
-  screen_class->get_monitor_plug_name = gdk_x11_screen_get_monitor_plug_name;
-  screen_class->get_monitor_geometry = gdk_x11_screen_get_monitor_geometry;
-  screen_class->get_monitor_workarea = gdk_x11_screen_get_monitor_workarea;
-  screen_class->get_monitor_scale_factor = gdk_x11_screen_get_monitor_scale_factor;
   screen_class->get_system_visual = _gdk_x11_screen_get_system_visual;
   screen_class->get_rgba_visual = gdk_x11_screen_get_rgba_visual;
   screen_class->is_composited = gdk_x11_screen_is_composited;
diff --git a/gdk/x11/gdkscreen-x11.h b/gdk/x11/gdkscreen-x11.h
index db82735..3b0fb35 100644
--- a/gdk/x11/gdkscreen-x11.h
+++ b/gdk/x11/gdkscreen-x11.h
@@ -42,10 +42,6 @@ struct _GdkX11Screen
   Window xroot_window;
   GdkWindow *root_window;
   gint screen_num;
-  /* Xinerama/RandR 1.2 */
-  gint  n_monitors;
-  GdkX11Monitor *monitors;
-  gint primary_monitor;
 
   gint width;
   gint height;
@@ -116,8 +112,6 @@ void _gdk_x11_screen_size_changed           (GdkScreen *screen,
                                             XEvent    *event);
 void _gdk_x11_screen_process_owner_change   (GdkScreen *screen,
                                             XEvent    *event);
-gint _gdk_x11_screen_get_xinerama_index     (GdkScreen *screen,
-                                            gint       monitor_num);
 void _gdk_x11_screen_get_edge_monitors      (GdkScreen *screen,
                                             gint      *top,
                                             gint      *bottom,
@@ -125,6 +119,8 @@ void _gdk_x11_screen_get_edge_monitors      (GdkScreen *screen,
                                             gint      *right);
 void _gdk_x11_screen_set_window_scale       (GdkX11Screen *x11_screen,
                                             int        scale);
+void gdk_x11_screen_get_work_area           (GdkScreen    *screen,
+                                             GdkRectangle *area);
 
 G_END_DECLS
 
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index 9ed087a..3aa4038 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -4215,8 +4215,9 @@ gdk_x11_window_apply_fullscreen_mode (GdkWindow *window)
          /* Translate all 4 monitors from the GDK set into XINERAMA indices */
          for (i = 0; i < 4; ++i)
            {
-             xclient.data.l[i] = _gdk_x11_screen_get_xinerama_index (GDK_WINDOW_SCREEN (window),
-                                                                     gdk_monitors[i]);
+              /* FIXME
+               xclient.data.l[i] = _gdk_x11_screen_ge_xinerama_index (GDK_WINDOW_SCREEN (window), 
gdk_monitors[i]); */
+             xclient.data.l[i] = 0;
              /* Sanity check, if XINERAMA is not available, we could have invalid
               * negative values for the XINERAMA indices.
               */
diff --git a/gdk/x11/gdkx.h b/gdk/x11/gdkx.h
index ae05fa6..1f64bcc 100644
--- a/gdk/x11/gdkx.h
+++ b/gdk/x11/gdkx.h
@@ -45,6 +45,7 @@
 #include <gdk/x11/gdkx11dnd.h>
 #include <gdk/x11/gdkx11glcontext.h>
 #include <gdk/x11/gdkx11keys.h>
+#include <gdk/x11/gdkx11monitor.h>
 #include <gdk/x11/gdkx11property.h>
 #include <gdk/x11/gdkx11screen.h>
 #include <gdk/x11/gdkx11selection.h>
diff --git a/gdk/x11/gdkx11monitor.h b/gdk/x11/gdkx11monitor.h
new file mode 100644
index 0000000..98717e8
--- /dev/null
+++ b/gdk/x11/gdkx11monitor.h
@@ -0,0 +1,48 @@
+/*
+ * gdkx11monitor.h
+ *
+ * Copyright 2016 Red Hat, Inc.
+ *
+ * Matthias Clasen <mclasen redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GDK_X11_MONITOR_H__
+#define __GDK_X11_MONITOR_H__
+
+#if !defined (__GDKX_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdkx.h> can be included directly."
+#endif
+
+#include <gdk/gdkmonitor.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_X11_MONITOR           (gdk_x11_monitor_get_type ())
+#define GDK_X11_MONITOR(object)        (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_X11_MONITOR, 
GdkX11Monitor))
+#define GDK_IS_X11_MONITOR(object)     (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_X11_MONITOR))
+
+typedef struct _GdkX11Monitor      GdkX11Monitor;
+typedef struct _GdkX11MonitorClass GdkX11MonitorClass;
+
+GDK_AVAILABLE_IN_3_22
+GType             gdk_x11_monitor_get_type            (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_3_22
+XID               gdk_x11_monitor_get_output          (GdkMonitor *monitor);
+
+G_END_DECLS
+
+#endif  /* __GDK_X11_MONITOR_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]