summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorMarc-André Lureau <marcandre.lureau@redhat.com>2011-03-22 11:53:42 +0100
committerMarc-André Lureau <marcandre.lureau@redhat.com>2011-03-22 11:53:42 +0100
commit02b6087c2d99d13bf16116673ec85324276ee49b (patch)
tree4d5d5ed9912eddbc5765c1741f44f120ff7e739d /gtk
parent279ef8bc87bf736b5600eba00947624d8139a189 (diff)
gtk/display: split x11/windows backend
For better or worse..
Diffstat (limited to 'gtk')
-rw-r--r--gtk/display/gnome-rr-config.c2
-rw-r--r--gtk/display/gnome-rr-private.h92
-rw-r--r--gtk/display/gnome-rr-windows.c111
-rw-r--r--gtk/display/gnome-rr-windows.h55
-rw-r--r--gtk/display/gnome-rr-x11.c943
-rw-r--r--gtk/display/gnome-rr-x11.h58
-rw-r--r--gtk/display/gnome-rr.c1042
-rw-r--r--gtk/spicy.c4
8 files changed, 1303 insertions, 1004 deletions
diff --git a/gtk/display/gnome-rr-config.c b/gtk/display/gnome-rr-config.c
index 5e22596..642345a 100644
--- a/gtk/display/gnome-rr-config.c
+++ b/gtk/display/gnome-rr-config.c
@@ -726,7 +726,7 @@ gnome_rr_config_class_init (GnomeRRConfigClass *klass)
g_object_class_install_property (gobject_class, PROP_SCREEN,
g_param_spec_object ("screen", "Screen", "The GnomeRRScreen this config applies to", GNOME_TYPE_RR_SCREEN,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB));
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
}
GnomeRRConfig *
diff --git a/gtk/display/gnome-rr-private.h b/gtk/display/gnome-rr-private.h
index 23aa3d4..5830de6 100644
--- a/gtk/display/gnome-rr-private.h
+++ b/gtk/display/gnome-rr-private.h
@@ -26,11 +26,26 @@
#define GNOME_RR_PRIVATE_H
#include <config.h>
+#include <gtk/gtk.h>
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif
+#ifndef HAVE_RANDR
+/* This is to avoid a ton of ifdefs wherever we use a type from libXrandr */
+typedef int RROutput;
+typedef int RRCrtc;
+typedef int RRMode;
+typedef int Rotation;
+#define RR_Rotate_0 1
+#define RR_Rotate_90 2
+#define RR_Rotate_180 4
+#define RR_Rotate_270 8
+#define RR_Reflect_X 16
+#define RR_Reflect_Y 32
+#endif
+
typedef struct ScreenInfo ScreenInfo;
struct ScreenInfo
@@ -40,10 +55,6 @@ struct ScreenInfo
int min_height;
int max_height;
-#ifdef HAVE_RANDR
- XRRScreenResources *resources;
-#endif
-
GnomeRROutput ** outputs;
GnomeRRCrtc ** crtcs;
GnomeRRMode ** modes;
@@ -53,6 +64,7 @@ struct ScreenInfo
GnomeRRMode ** clone_modes;
#ifdef HAVE_RANDR
+ XRRScreenResources *resources;
RROutput primary;
#endif
};
@@ -60,19 +72,7 @@ struct ScreenInfo
struct GnomeRRScreenPrivate
{
GdkScreen * gdk_screen;
- GdkWindow * gdk_root;
ScreenInfo * info;
-
-#ifdef HAVE_X11
- Display * xdisplay;
- Screen * xscreen;
- Window xroot;
-
- int randr_event_base;
- int rr_major_version;
- int rr_minor_version;
- Atom connector_type_atom;
-#endif
};
struct GnomeRROutputInfoPrivate
@@ -100,25 +100,11 @@ struct GnomeRROutputInfoPrivate
struct GnomeRRConfigPrivate
{
- gboolean clone;
- GnomeRRScreen *screen;
- GnomeRROutputInfo **outputs;
+ gboolean clone;
+ GnomeRRScreen * screen;
+ GnomeRROutputInfo ** outputs;
};
-#ifndef HAVE_RANDR
-/* This is to avoid a ton of ifdefs wherever we use a type from libXrandr */
-typedef int RROutput;
-typedef int RRCrtc;
-typedef int RRMode;
-typedef int Rotation;
-#define RR_Rotate_0 1
-#define RR_Rotate_90 2
-#define RR_Rotate_180 4
-#define RR_Rotate_270 8
-#define RR_Reflect_X 16
-#define RR_Reflect_Y 32
-#endif
-
struct GnomeRROutput
{
ScreenInfo * info;
@@ -134,7 +120,7 @@ struct GnomeRROutput
GnomeRRMode ** modes;
int n_preferred;
guint8 * edid_data;
- int edid_size;
+ int edid_size;
char * connector_type;
};
@@ -169,4 +155,42 @@ struct GnomeRRMode
int freq; /* in mHz */
};
+#if !GTK_CHECK_VERSION (2, 91, 0)
+#define gdk_x11_window_get_xid gdk_x11_drawable_get_xid
+#define gdk_error_trap_pop_ignored gdk_error_trap_pop
+#endif
+
+G_GNUC_INTERNAL
+GdkScreen * gnome_rr_screen_get_gdk_screen (GnomeRRScreen *self);
+G_GNUC_INTERNAL
+GnomeRROutput * gnome_rr_output_by_id (ScreenInfo *info, RROutput id);
+G_GNUC_INTERNAL
+GnomeRRCrtc * crtc_by_id (ScreenInfo *info, RRCrtc id);
+G_GNUC_INTERNAL
+GnomeRRMode * mode_by_id (ScreenInfo *info, RRMode id);
+
+G_GNUC_INTERNAL
+ScreenInfo * screen_info_new (GnomeRRScreen *screen, gboolean needs_reprobe,
+ GError **error);
+G_GNUC_INTERNAL
+gboolean screen_update (GnomeRRScreen *screen, gboolean force_callback,
+ gboolean needs_reprobe, GError **error);
+G_GNUC_INTERNAL
+gboolean fill_out_screen_info (GnomeRRScreen *screen, ScreenInfo *info,
+ gboolean needs_reprobe, GError **error);
+G_GNUC_INTERNAL
+GnomeRRCrtc * crtc_new (ScreenInfo *info, RRCrtc id);
+
+/* GnomeRROutput */
+G_GNUC_INTERNAL
+GnomeRROutput * output_new (ScreenInfo *info, RROutput id);
+G_GNUC_INTERNAL
+GnomeRRMode * mode_new (ScreenInfo *info, RRMode id);
+G_GNUC_INTERNAL
+void screen_info_free (ScreenInfo *info);
+G_GNUC_INTERNAL
+void gather_clone_modes (ScreenInfo *info);
+
+
+
#endif
diff --git a/gtk/display/gnome-rr-windows.c b/gtk/display/gnome-rr-windows.c
index 7e39b39..218d437 100644
--- a/gtk/display/gnome-rr-windows.c
+++ b/gtk/display/gnome-rr-windows.c
@@ -36,3 +36,114 @@
#undef GNOME_DISABLE_DEPRECATED
#include "gnome-rr.h"
#include "gnome-rr-config.h"
+#include "gnome-rr-private.h"
+#include "gnome-rr-windows.h"
+
+struct GnomeRRWindowsScreenPrivate
+{
+ DISPLAY_DEVICE device;
+};
+
+static void gnome_rr_windows_screen_initable_iface_init (GInitableIface *iface);
+G_DEFINE_TYPE_WITH_CODE (GnomeRRWindowsScreen, gnome_rr_windows_screen, GNOME_TYPE_RR_SCREEN,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gnome_rr_windows_screen_initable_iface_init))
+
+static gboolean
+gnome_rr_windows_screen_initable_init (GInitable *initable, GCancellable *canc, GError **error)
+{
+ GInitableIface *iface, *parent_iface;
+
+ iface = G_TYPE_INSTANCE_GET_INTERFACE(initable, G_TYPE_INITABLE, GInitableIface);
+ parent_iface = g_type_interface_peek_parent(iface);
+
+ if (!parent_iface->init (initable, canc, error))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+gnome_rr_windows_screen_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = gnome_rr_windows_screen_initable_init;
+}
+
+static void
+gnome_rr_windows_screen_finalize (GObject *gobject)
+{
+ G_OBJECT_CLASS (gnome_rr_windows_screen_parent_class)->finalize (gobject);
+}
+
+static void
+gnome_rr_windows_screen_class_init (GnomeRRWindowsScreenClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GnomeRRWindowsScreenPrivate));
+
+ gobject_class->finalize = gnome_rr_windows_screen_finalize;
+}
+
+static void
+gnome_rr_windows_screen_init (GnomeRRWindowsScreen *self)
+{
+ GnomeRRWindowsScreenPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GNOME_TYPE_RR_WINDOWS_SCREEN, GnomeRRWindowsScreenPrivate);
+
+ self->priv = priv;
+}
+
+gboolean
+fill_out_screen_info (GnomeRRScreen *screen, ScreenInfo *info,
+ gboolean needs_reprobe, GError **error)
+{
+ return FALSE;
+}
+
+gboolean
+gnome_rr_crtc_set_config_with_time (GnomeRRCrtc *crtc,
+ guint32 timestamp,
+ int x,
+ int y,
+ GnomeRRMode *mode,
+ GnomeRRRotation rotation,
+ GnomeRROutput **outputs,
+ int n_outputs,
+ GError **error)
+{
+ g_return_val_if_fail (crtc != NULL, FALSE);
+ g_return_val_if_fail (mode != NULL || outputs == NULL || n_outputs == 0, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ return FALSE;
+}
+
+void
+gnome_rr_screen_set_size (GnomeRRScreen *self,
+ int width,
+ int height,
+ int mm_width,
+ int mm_height)
+{
+ g_return_if_fail (GNOME_IS_RR_WINDOWS_SCREEN (self));
+}
+
+void
+gnome_rr_crtc_set_gamma (GnomeRRCrtc *crtc, int size,
+ unsigned short *red,
+ unsigned short *green,
+ unsigned short *blue)
+{
+ g_return_if_fail (crtc != NULL);
+ g_return_if_fail (red != NULL);
+ g_return_if_fail (green != NULL);
+ g_return_if_fail (blue != NULL);
+}
+
+gboolean
+gnome_rr_crtc_get_gamma (GnomeRRCrtc *crtc, int *size,
+ unsigned short **red, unsigned short **green,
+ unsigned short **blue)
+{
+ g_return_val_if_fail (crtc != NULL, FALSE);
+ return FALSE;
+}
diff --git a/gtk/display/gnome-rr-windows.h b/gtk/display/gnome-rr-windows.h
new file mode 100644
index 0000000..e5808a2
--- /dev/null
+++ b/gtk/display/gnome-rr-windows.h
@@ -0,0 +1,55 @@
+/* gnome-rr-windows.h
+ *
+ * Copyright 2011, Red Hat, Inc.
+ *
+ * This file is part of the Gnome Library.
+ *
+ * The Gnome 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.
+ *
+ * The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Soren Sandmann <sandmann@redhat.com>
+ * Marc-André Lureau <marcandre.lureau@redhat.com>
+ */
+
+#ifndef GNOME_RR_WINDOWS_H
+#define GNOME_RR_WINDOWS_H
+
+#include <glib.h>
+#include "gnome-rr.h"
+
+#define GNOME_TYPE_RR_WINDOWS_SCREEN (gnome_rr_windows_screen_get_type())
+#define GNOME_RR_WINDOWS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_RR_WINDOWS_SCREEN, GnomeRRWindowsScreen))
+#define GNOME_IS_RR_WINDOWS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_RR_WINDOWS_SCREEN))
+#define GNOME_RR_WINDOWS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_RR_WINDOWS_SCREEN, GnomeRRWindowsScreenClass))
+#define GNOME_IS_RR_WINDOWS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_RR_WINDOWS_SCREEN))
+#define GNOME_RR_WINDOWS_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_RR_WINDOWS_SCREEN, GnomeRRWindowsScreenClass))
+
+typedef struct GnomeRRWindowsScreenPrivate GnomeRRWindowsScreenPrivate;
+
+typedef struct {
+ GnomeRRScreen parent;
+
+ GnomeRRWindowsScreenPrivate* priv;
+} GnomeRRWindowsScreen;
+
+typedef struct {
+ GnomeRRScreenClass parent_class;
+
+ void (* changed) (void);
+} GnomeRRWindowsScreenClass;
+
+GType gnome_rr_windows_screen_get_type (void);
+
+#endif /* GNOME_RR_WINDOWS_H */
diff --git a/gtk/display/gnome-rr-x11.c b/gtk/display/gnome-rr-x11.c
index 67e8a5c..40cdb43 100644
--- a/gtk/display/gnome-rr-x11.c
+++ b/gtk/display/gnome-rr-x11.c
@@ -42,11 +42,24 @@
#undef GNOME_DISABLE_DEPRECATED
#include "gnome-rr.h"
+#include "gnome-rr-x11.h"
#include "gnome-rr-config.h"
#include "gnome-rr-private.h"
-#define DISPLAY(o) ((o)->info->screen->priv->xdisplay)
+struct GnomeRRX11ScreenPrivate
+{
+ Display * xdisplay;
+ Screen * xscreen;
+ Window xroot;
+
+ int randr_event_base;
+ int rr_major_version;
+ int rr_minor_version;
+ Atom connector_type_atom;
+};
+
+#define DISPLAY(o) (GNOME_RR_X11_SCREEN((o)->info->screen)->priv->xdisplay)
#ifdef HAVE_RANDR
#define RANDR_LIBRARY_IS_AT_LEAST_1_3 (RANDR_MAJOR > 1 || (RANDR_MAJOR == 1 && RANDR_MINOR >= 3))
@@ -55,3 +68,931 @@
#endif
#define SERVERS_RANDR_IS_AT_LEAST_1_3(priv) (priv->rr_major_version > 1 || (priv->rr_major_version == 1 && priv->rr_minor_version >= 3))
+
+static gboolean output_initialize (GnomeRROutput *output, XRRScreenResources *res, GError **error);
+static void gnome_rr_x11_screen_initable_iface_init (GInitableIface *iface);
+G_DEFINE_TYPE_WITH_CODE (GnomeRRX11Screen, gnome_rr_x11_screen, GNOME_TYPE_RR_SCREEN,
+ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gnome_rr_x11_screen_initable_iface_init))
+
+static GdkFilterReturn
+screen_on_event (GdkXEvent *xevent,
+ GdkEvent *event,
+ gpointer data)
+{
+#ifdef HAVE_RANDR
+ GnomeRRX11Screen *screen = data;
+ GnomeRRX11ScreenPrivate *priv = screen->priv;
+ XEvent *e = xevent;
+ int event_num;
+
+ if (!e)
+ return GDK_FILTER_CONTINUE;
+
+ event_num = e->type - priv->randr_event_base;
+
+ if (event_num == RRScreenChangeNotify) {
+ /* We don't reprobe the hardware; we just fetch the X server's latest
+ * state. The server already knows the new state of the outputs; that's
+ * why it sent us an event!
+ */
+ screen_update (GNOME_RR_SCREEN (screen), TRUE, FALSE, NULL); /* NULL-GError */
+#if 0
+ /* Enable this code to get a dialog showing the RANDR timestamps, for debugging purposes */
+ {
+ GtkWidget *dialog;
+ XRRScreenChangeNotifyEvent *rr_event;
+ static int dialog_num;
+
+ rr_event = (XRRScreenChangeNotifyEvent *) e;
+
+ dialog = gtk_message_dialog_new (NULL,
+ 0,
+ GTK_MESSAGE_INFO,
+ GTK_BUTTONS_CLOSE,
+ "RRScreenChangeNotify timestamps (%d):\n"
+ "event change: %u\n"
+ "event config: %u\n"
+ "event serial: %lu\n"
+ "----------------------"
+ "screen change: %u\n"
+ "screen config: %u\n",
+ dialog_num++,
+ (guint32) rr_event->timestamp,
+ (guint32) rr_event->config_timestamp,
+ rr_event->serial,
+ (guint32) priv->info->resources->timestamp,
+ (guint32) priv->info->resources->configTimestamp);
+ g_signal_connect (dialog, "response",
+ G_CALLBACK (gtk_widget_destroy), NULL);
+ gtk_widget_show (dialog);
+ }
+#endif
+ }
+#if 0
+ /* WHY THIS CODE IS DISABLED:
+ *
+ * Note that in gnome_rr_screen_new(), we only select for
+ * RRScreenChangeNotifyMask. We used to select for other values in
+ * RR*NotifyMask, but we weren't really doing anything useful with those
+ * events. We only care about "the screens changed in some way or another"
+ * for now.
+ *
+ * If we ever run into a situtation that could benefit from processing more
+ * detailed events, we can enable this code again.
+ *
+ * Note that the X server sends RRScreenChangeNotify in conjunction with the
+ * more detailed events from RANDR 1.2 - see xserver/randr/randr.c:TellChanged().
+ */
+ else if (event_num == RRNotify)
+ {
+ /* Other RandR events */
+
+ XRRNotifyEvent *event = (XRRNotifyEvent *)e;
+
+ /* Here we can distinguish between RRNotify events supported
+ * since RandR 1.2 such as RRNotify_OutputProperty. For now, we
+ * don't have anything special to do for particular subevent types, so
+ * we leave this as an empty switch().
+ */
+ switch (event->subtype)
+ {
+ default:
+ break;
+ }
+
+ /* No need to reprobe hardware here */
+ screen_update (GNOME_RR_SCREEN (screen), TRUE, FALSE, NULL); /* NULL-GError */
+ }
+#endif
+
+#endif /* HAVE_RANDR */
+
+ /* Pass the event on to GTK+ */
+ return GDK_FILTER_CONTINUE;
+}
+
+static gboolean
+gnome_rr_x11_screen_initable_init (GInitable *initable, GCancellable *canc, GError **error)
+{
+ GInitableIface *iface, *parent_iface;
+
+ iface = G_TYPE_INSTANCE_GET_INTERFACE(initable, G_TYPE_INITABLE, GInitableIface);
+ parent_iface = g_type_interface_peek_parent(iface);
+
+#ifdef HAVE_RANDR
+ GnomeRRX11Screen *self = GNOME_RR_X11_SCREEN (initable);
+ GnomeRRX11ScreenPrivate *priv = self->priv;
+ Display *dpy = GDK_SCREEN_XDISPLAY (gnome_rr_screen_get_gdk_screen (GNOME_RR_SCREEN (self)));
+ int event_base;
+ int ignore;
+ GdkWindow *root;
+
+ root = gdk_screen_get_root_window (gnome_rr_screen_get_gdk_screen (GNOME_RR_SCREEN (self)));
+ priv->connector_type_atom = XInternAtom (dpy, "ConnectorType", FALSE);
+
+ if (XRRQueryExtension (dpy, &event_base, &ignore))
+ {
+ priv->randr_event_base = event_base;
+
+ XRRQueryVersion (dpy, &priv->rr_major_version, &priv->rr_minor_version);
+ if (priv->rr_major_version < 1 || (priv->rr_major_version == 1 && priv->rr_minor_version < 2)) {
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_RANDR_EXTENSION,
+ "RANDR extension is too old (must be at least 1.2)");
+ return FALSE;
+ }
+
+ if (!parent_iface->init (initable, canc, error))
+ return FALSE;
+
+ XRRSelectInput (priv->xdisplay,
+ priv->xroot,
+ RRScreenChangeNotifyMask);
+ gdk_x11_register_standard_event_type (
+ gdk_screen_get_display (gnome_rr_screen_get_gdk_screen (GNOME_RR_SCREEN (self))),
+ event_base,
+ RRNotify + 1);
+ gdk_window_add_filter (root, screen_on_event, self);
+
+ return TRUE;
+ }
+ else
+ {
+#endif /* HAVE_RANDR */
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_RANDR_EXTENSION,
+ _("RANDR extension is not present"));
+
+ return FALSE;
+#ifdef HAVE_RANDR
+ }
+#endif
+}
+
+static void
+gnome_rr_x11_screen_initable_iface_init (GInitableIface *iface)
+{
+ iface->init = gnome_rr_x11_screen_initable_init;
+}
+
+static void
+gnome_rr_x11_screen_finalize (GObject *gobject)
+{
+ GnomeRRX11Screen *screen = GNOME_RR_X11_SCREEN (gobject);
+ GdkWindow *root;
+
+ root = gdk_screen_get_root_window (gnome_rr_screen_get_gdk_screen (GNOME_RR_SCREEN (screen)));
+ gdk_window_remove_filter (root, screen_on_event, screen);
+
+ G_OBJECT_CLASS (gnome_rr_x11_screen_parent_class)->finalize (gobject);
+}
+
+static void
+gnome_rr_x11_screen_class_init (GnomeRRX11ScreenClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (GnomeRRX11ScreenPrivate));
+
+ gobject_class->finalize = gnome_rr_x11_screen_finalize;
+}
+
+static void
+on_gdk_screen_changed (GnomeRRX11Screen *self, G_GNUC_UNUSED gpointer data)
+{
+ GnomeRRX11ScreenPrivate *priv = self->priv;
+ GdkScreen *gdk_screen;
+ GdkWindow *root;
+
+ gdk_screen = gnome_rr_screen_get_gdk_screen (GNOME_RR_SCREEN (self));
+ root = gdk_screen_get_root_window (gdk_screen);
+
+ priv->xroot = gdk_x11_window_get_xid (root);
+ priv->xdisplay = GDK_SCREEN_XDISPLAY (gdk_screen);
+ priv->xscreen = gdk_x11_screen_get_xscreen (gdk_screen);
+}
+
+static void
+gnome_rr_x11_screen_init (GnomeRRX11Screen *self)
+{
+ GnomeRRX11ScreenPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GNOME_TYPE_RR_X11_SCREEN, GnomeRRX11ScreenPrivate);
+
+ self->priv = priv;
+ priv->xdisplay = NULL;
+ priv->xroot = None;
+ priv->xscreen = NULL;
+ priv->rr_major_version = 0;
+ priv->rr_minor_version = 0;
+
+ /* no need to unregister this handler: it's self - instead of notify signal, we could override the prop */
+ g_signal_connect (self, "notify::gdk-screen", G_CALLBACK (on_gdk_screen_changed), NULL);
+}
+
+void
+gnome_rr_screen_set_size (GnomeRRScreen *self,
+ int width,
+ int height,
+ int mm_width,
+ int mm_height)
+{
+ g_return_if_fail (GNOME_IS_RR_X11_SCREEN (self));
+
+#ifdef HAVE_RANDR
+ GnomeRRX11ScreenPrivate *priv = GNOME_RR_X11_SCREEN (self)->priv;
+
+ gdk_error_trap_push ();
+ XRRSetScreenSize (priv->xdisplay, priv->xroot,
+ width, height, mm_width, mm_height);
+ gdk_error_trap_pop_ignored ();
+#endif
+}
+
+#ifdef HAVE_RANDR
+/* GnomeRRCrtc */
+typedef struct
+{
+ Rotation xrot;
+ GnomeRRRotation rot;
+} RotationMap;
+
+static const RotationMap rotation_map[] =
+{
+ { RR_Rotate_0, GNOME_RR_ROTATION_0 },
+ { RR_Rotate_90, GNOME_RR_ROTATION_90 },
+ { RR_Rotate_180, GNOME_RR_ROTATION_180 },
+ { RR_Rotate_270, GNOME_RR_ROTATION_270 },
+ { RR_Reflect_X, GNOME_RR_REFLECT_X },
+ { RR_Reflect_Y, GNOME_RR_REFLECT_Y },
+};
+
+static GnomeRRRotation
+gnome_rr_rotation_from_xrotation (Rotation r)
+{
+ int i;
+ GnomeRRRotation result = 0;
+
+ for (i = 0; i < G_N_ELEMENTS (rotation_map); ++i)
+ {
+ if (r & rotation_map[i].xrot)
+ result |= rotation_map[i].rot;
+ }
+
+ return result;
+}
+
+static Rotation
+xrotation_from_rotation (GnomeRRRotation r)
+{
+ int i;
+ Rotation result = 0;
+
+ for (i = 0; i < G_N_ELEMENTS (rotation_map); ++i)
+ {
+ if (r & rotation_map[i].rot)
+ result |= rotation_map[i].xrot;
+ }
+
+ return result;
+}
+
+static gboolean
+crtc_initialize (GnomeRRCrtc *crtc,
+ XRRScreenResources *res,
+ GError **error)
+{
+ XRRCrtcInfo *info = XRRGetCrtcInfo (DISPLAY (crtc), res, crtc->id);
+ GPtrArray *a;
+ int i;
+
+#if 0
+ g_print ("CRTC %lx Timestamp: %u\n", crtc->id, (guint32)info->timestamp);
+#endif
+
+ if (!info)
+ {
+ /* FIXME: We need to reaquire the screen resources */
+ /* FIXME: can we actually catch BadRRCrtc, and does it make sense to emit that? */
+
+ /* Translators: CRTC is a CRT Controller (this is X terminology).
+ * It is *very* unlikely that you'll ever get this error, so it is
+ * only listed for completeness. */
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
+ _("could not get information about CRTC %d"),
+ (int) crtc->id);
+ return FALSE;
+ }
+
+ /* GnomeRRMode */
+ crtc->current_mode = mode_by_id (crtc->info, info->mode);
+
+ crtc->x = info->x;
+ crtc->y = info->y;
+
+ /* Current outputs */
+ a = g_ptr_array_new ();
+ for (i = 0; i < info->noutput; ++i)
+ {
+ GnomeRROutput *output = gnome_rr_output_by_id (crtc->info, info->outputs[i]);
+
+ if (output)
+ g_ptr_array_add (a, output);
+ }
+ g_ptr_array_add (a, NULL);
+ crtc->current_outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
+
+ /* Possible outputs */
+ a = g_ptr_array_new ();
+ for (i = 0; i < info->npossible; ++i)
+ {
+ GnomeRROutput *output = gnome_rr_output_by_id (crtc->info, info->possible[i]);
+
+ if (output)
+ g_ptr_array_add (a, output);
+ }
+ g_ptr_array_add (a, NULL);
+ crtc->possible_outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
+
+ /* Rotations */
+ crtc->current_rotation = gnome_rr_rotation_from_xrotation (info->rotation);
+ crtc->rotations = gnome_rr_rotation_from_xrotation (info->rotations);
+
+ XRRFreeCrtcInfo (info);
+
+ /* get an store gamma size */
+ crtc->gamma_size = XRRGetCrtcGammaSize (DISPLAY (crtc), crtc->id);
+
+ return TRUE;
+}
+
+static void
+mode_initialize (GnomeRRMode *mode, XRRModeInfo *info)
+{
+ g_return_if_fail (mode != NULL);
+ g_return_if_fail (info != NULL);
+
+ mode->name = g_strdup (info->name);
+ mode->width = info->width;
+ mode->height = info->height;
+ mode->freq = ((info->dotClock / (double)info->hTotal) / info->vTotal + 0.5) * 1000;
+}
+
+static gboolean
+fill_screen_info_from_resources (ScreenInfo *info,
+ XRRScreenResources *resources,
+ GError **error)
+{
+ int i;
+ GPtrArray *a;
+ GnomeRRCrtc **crtc;
+ GnomeRROutput **output;
+
+ info->resources = resources;
+
+ /* We create all the structures before initializing them, so
+ * that they can refer to each other.
+ */
+ a = g_ptr_array_new ();
+ for (i = 0; i < resources->ncrtc; ++i)
+ {
+ GnomeRRCrtc *crtc = crtc_new (info, resources->crtcs[i]);
+
+ g_ptr_array_add (a, crtc);
+ }
+ g_ptr_array_add (a, NULL);
+ info->crtcs = (GnomeRRCrtc **)g_ptr_array_free (a, FALSE);
+
+ a = g_ptr_array_new ();
+ for (i = 0; i < resources->noutput; ++i)
+ {
+ GnomeRROutput *output = output_new (info, resources->outputs[i]);
+
+ g_ptr_array_add (a, output);
+ }
+ g_ptr_array_add (a, NULL);
+ info->outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
+
+ a = g_ptr_array_new ();
+ for (i = 0; i < resources->nmode; ++i)
+ {
+ GnomeRRMode *mode = mode_new (info, resources->modes[i].id);
+
+ g_ptr_array_add (a, mode);
+ }
+ g_ptr_array_add (a, NULL);
+ info->modes = (GnomeRRMode **)g_ptr_array_free (a, FALSE);
+
+ /* Initialize */
+ for (crtc = info->crtcs; *crtc; ++crtc)
+ {
+ if (!crtc_initialize (*crtc, resources, error))
+ return FALSE;
+ }
+
+ for (output = info->outputs; *output; ++output)
+ {
+ if (!output_initialize (*output, resources, error))
+ return FALSE;
+ }
+
+ for (i = 0; i < resources->nmode; ++i)
+ {
+ GnomeRRMode *mode = mode_by_id (info, resources->modes[i].id);
+
+ mode_initialize (mode, &(resources->modes[i]));
+ }
+
+ gather_clone_modes (info);
+
+ return TRUE;
+}
+#endif /* HAVE_RANDR */
+
+gboolean
+fill_out_screen_info (GnomeRRScreen *screen,
+ ScreenInfo *info,
+ gboolean needs_reprobe,
+ GError **error)
+{
+ GnomeRRX11ScreenPrivate *priv = GNOME_RR_X11_SCREEN (screen)->priv;
+ Display *xdisplay = priv->xdisplay;
+ Window xroot = priv->xroot;
+#ifdef HAVE_RANDR
+ XRRScreenResources *resources;
+
+ g_return_val_if_fail (xdisplay != NULL, FALSE);
+ g_return_val_if_fail (info != NULL, FALSE);
+
+ /* First update the screen resources */
+
+ if (needs_reprobe)
+ resources = XRRGetScreenResources (xdisplay, xroot);
+ else
+ {
+ /* XRRGetScreenResourcesCurrent is less expensive than
+ * XRRGetScreenResources, however it is available only
+ * in RandR 1.3 or higher
+ */
+#if RANDR_LIBRARY_IS_AT_LEAST_1_3
+ if (SERVERS_RANDR_IS_AT_LEAST_1_3 (priv))
+ resources = XRRGetScreenResourcesCurrent (xdisplay, xroot);
+ else
+ resources = XRRGetScreenResources (xdisplay, xroot);
+#else
+ resources = XRRGetScreenResources (xdisplay, xroot);
+#endif
+ }
+
+ if (resources)
+ {
+ if (!fill_screen_info_from_resources (info, resources, error))
+ return FALSE;
+ }
+ else
+ {
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
+ /* Translators: a CRTC is a CRT Controller (this is X terminology). */
+ _("could not get the screen resources (CRTCs, outputs, modes)"));
+ return FALSE;
+ }
+
+ /* Then update the screen size range. We do this after XRRGetScreenResources() so that
+ * the X server will already have an updated view of the outputs.
+ */
+
+ if (needs_reprobe) {
+ gboolean success;
+
+ gdk_error_trap_push ();
+ success = XRRGetScreenSizeRange (xdisplay, xroot,
+ &(info->min_width),
+ &(info->min_height),
+ &(info->max_width),
+ &(info->max_height));
+ gdk_flush ();
+ if (gdk_error_trap_pop ()) {
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_UNKNOWN,
+ _("unhandled X error while getting the range of screen sizes"));
+ return FALSE;
+ }
+
+ if (!success) {
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
+ _("could not get the range of screen sizes"));
+ return FALSE;
+ }
+ }
+ else
+ {
+ gnome_rr_screen_get_ranges (info->screen,
+ &(info->min_width),
+ &(info->max_width),
+ &(info->min_height),
+ &(info->max_height));
+ }
+
+ info->primary = None;
+#if RANDR_LIBRARY_IS_AT_LEAST_1_3
+ if (SERVERS_RANDR_IS_AT_LEAST_1_3 (priv)) {
+ gdk_error_trap_push ();
+ info->primary = XRRGetOutputPrimary (xdisplay, xroot);
+ gdk_error_trap_pop_ignored ();
+ }
+#endif
+
+ return TRUE;
+#else
+ return FALSE;
+#endif /* HAVE_RANDR */
+}
+
+static guint8 *
+get_property (Display *dpy,
+ RROutput output,
+ Atom atom,
+ int *len)
+{
+#ifdef HAVE_RANDR
+ unsigned char *prop;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ Atom actual_type;
+ guint8 *result;
+
+ XRRGetOutputProperty (dpy, output, atom,
+ 0, 100, False, False,
+ AnyPropertyType,
+ &actual_type, &actual_format,
+ &nitems, &bytes_after, &prop);
+
+ if (actual_type == XA_INTEGER && actual_format == 8)
+ {
+ result = g_memdup (prop, nitems);
+ if (len)
+ *len = nitems;
+ }
+ else
+ {
+ result = NULL;
+ }
+
+ XFree (prop);
+
+ return result;
+#else
+ return NULL;
+#endif /* HAVE_RANDR */
+}
+
+static guint8 *
+read_edid_data (GnomeRROutput *output, int *len)
+{
+ Atom edid_atom;
+ guint8 *result;
+
+ edid_atom = XInternAtom (DISPLAY (output), "EDID", FALSE);
+ result = get_property (DISPLAY (output),
+ output->id, edid_atom, len);
+
+ if (!result)
+ {
+ edid_atom = XInternAtom (DISPLAY (output), "EDID_DATA", FALSE);
+ result = get_property (DISPLAY (output),
+ output->id, edid_atom, len);
+ }
+
+ if (result)
+ {
+ if (*len % 128 == 0)
+ return result;
+ else
+ g_free (result);
+ }
+
+ return NULL;
+}
+
+static char *
+x11_get_connector_type_string (GnomeRROutput *output)
+{
+#ifdef HAVE_RANDR
+ char *result;
+ unsigned char *prop;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ Atom actual_type;
+ Atom connector_type;
+ char *connector_type_str;
+ GnomeRRX11ScreenPrivate *priv = GNOME_RR_X11_SCREEN (output->info->screen)->priv;
+
+ result = NULL;
+
+ if (XRRGetOutputProperty (DISPLAY (output), output->id, priv->connector_type_atom,
+ 0, 100, False, False,
+ AnyPropertyType,
+ &actual_type, &actual_format,
+ &nitems, &bytes_after, &prop) != Success)
+ return NULL;
+
+ if (!(actual_type == XA_ATOM && actual_format == 32 && nitems == 1))
+ goto out;
+
+ connector_type = *((Atom *) prop);
+
+ connector_type_str = XGetAtomName (DISPLAY (output), connector_type);
+ if (connector_type_str) {
+ result = g_strdup (connector_type_str); /* so the caller can g_free() it */
+ XFree (connector_type_str);
+ }
+
+out:
+
+ XFree (prop);
+
+ return result;
+#else
+ return NULL;
+#endif
+}
+
+static gboolean
+output_initialize (GnomeRROutput *output, XRRScreenResources *res, GError **error)
+{
+ XRROutputInfo *info = XRRGetOutputInfo (
+ DISPLAY (output), res, output->id);
+ GPtrArray *a;
+ int i;
+
+#if 0
+ g_print ("Output %lx Timestamp: %u\n", output->id, (guint32)info->timestamp);
+#endif
+
+ if (!info || !output->info)
+ {
+ /* FIXME: see the comment in crtc_initialize() */
+ /* Translators: here, an "output" is a video output */
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
+ _("could not get information about output %d"),
+ (int) output->id);
+ return FALSE;
+ }
+
+ output->name = g_strdup (info->name); /* FIXME: what is nameLen used for? */
+ output->current_crtc = crtc_by_id (output->info, info->crtc);
+ output->width_mm = info->mm_width;
+ output->height_mm = info->mm_height;
+ output->connected = (info->connection == RR_Connected);
+ output->connector_type = x11_get_connector_type_string (output);
+
+ /* Possible crtcs */
+ a = g_ptr_array_new ();
+
+ for (i = 0; i < info->ncrtc; ++i)
+ {
+ GnomeRRCrtc *crtc = crtc_by_id (output->info, info->crtcs[i]);
+
+ if (crtc)
+ g_ptr_array_add (a, crtc);
+ }
+ g_ptr_array_add (a, NULL);
+ output->possible_crtcs = (GnomeRRCrtc **)g_ptr_array_free (a, FALSE);
+
+ /* Clones */
+ a = g_ptr_array_new ();
+ for (i = 0; i < info->nclone; ++i)
+ {
+ GnomeRROutput *gnome_rr_output = gnome_rr_output_by_id (output->info, info->clones[i]);
+
+ if (gnome_rr_output)
+ g_ptr_array_add (a, gnome_rr_output);
+ }
+ g_ptr_array_add (a, NULL);
+ output->clones = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
+
+ /* Modes */
+ a = g_ptr_array_new ();
+ for (i = 0; i < info->nmode; ++i)
+ {
+ GnomeRRMode *mode = mode_by_id (output->info, info->modes[i]);
+
+ if (mode)
+ g_ptr_array_add (a, mode);
+ }
+ g_ptr_array_add (a, NULL);
+ output->modes = (GnomeRRMode **)g_ptr_array_free (a, FALSE);
+
+ output->n_preferred = info->npreferred;
+
+ /* Edid data */
+ output->edid_data = read_edid_data (output, &output->edid_size);
+
+ XRRFreeOutputInfo (info);
+
+ return TRUE;
+}
+
+gboolean
+gnome_rr_crtc_set_config_with_time (GnomeRRCrtc *crtc,
+ guint32 timestamp,
+ int x,
+ int y,
+ GnomeRRMode *mode,
+ GnomeRRRotation rotation,
+ GnomeRROutput **outputs,
+ int n_outputs,
+ GError **error)
+{
+#ifdef HAVE_RANDR
+ ScreenInfo *info;
+ GArray *output_ids;
+ Status status;
+ gboolean result;
+ int i;
+
+ g_return_val_if_fail (crtc != NULL, FALSE);
+ g_return_val_if_fail (mode != NULL || outputs == NULL || n_outputs == 0, FALSE);
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ info = crtc->info;
+
+ if (mode)
+ {
+ if (x + mode->width > info->max_width
+ || y + mode->height > info->max_height)
+ {
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_BOUNDS_ERROR,
+ /* Translators: the "position", "size", and "maximum"
+ * words here are not keywords; please translate them
+ * as usual. A CRTC is a CRT Controller (this is X terminology) */
+ _("requested position/size for CRTC %d is outside the allowed limit: "
+ "position=(%d, %d), size=(%d, %d), maximum=(%d, %d)"),
+ (int) crtc->id,
+ x, y,
+ mode->width, mode->height,
+ info->max_width, info->max_height);
+ return FALSE;
+ }
+ }
+
+ output_ids = g_array_new (FALSE, FALSE, sizeof (RROutput));
+
+ if (outputs)
+ {
+ for (i = 0; i < n_outputs; ++i)
+ g_array_append_val (output_ids, outputs[i]->id);
+ }
+
+ status = XRRSetCrtcConfig (DISPLAY (crtc), info->resources, crtc->id,
+ timestamp,
+ x, y,
+ mode ? mode->id : None,
+ xrotation_from_rotation (rotation),
+ (RROutput *)output_ids->data,
+ output_ids->len);
+
+ g_array_free (output_ids, TRUE);
+
+ if (status == RRSetConfigSuccess)
+ result = TRUE;
+ else {
+ result = FALSE;
+ /* Translators: CRTC is a CRT Controller (this is X terminology).
+ * It is *very* unlikely that you'll ever get this error, so it is
+ * only listed for completeness. */
+ g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
+ _("could not set the configuration for CRTC %d"),
+ (int) crtc->id);
+ }
+
+ return result;
+#else
+ return FALSE;
+#endif /* HAVE_RANDR */
+}
+
+void
+gnome_rr_crtc_set_gamma (GnomeRRCrtc *crtc, int size,
+ unsigned short *red,
+ unsigned short *green,
+ unsigned short *blue)
+{
+ g_return_if_fail (crtc != NULL);
+ g_return_if_fail (red != NULL);
+ g_return_if_fail (green != NULL);
+ g_return_if_fail (blue != NULL);
+
+#ifdef HAVE_RANDR
+ int copy_size;
+ XRRCrtcGamma *gamma;
+
+ if (size != crtc->gamma_size)
+ return;
+
+ gamma = XRRAllocGamma (crtc->gamma_size);
+
+ copy_size = crtc->gamma_size * sizeof (unsigned short);
+ memcpy (gamma->red, red, copy_size);
+ memcpy (gamma->green, green, copy_size);
+ memcpy (gamma->blue, blue, copy_size);
+
+ XRRSetCrtcGamma (DISPLAY (crtc), crtc->id, gamma);
+ XRRFreeGamma (gamma);
+#endif /* HAVE_RANDR */
+}
+
+gboolean
+gnome_rr_crtc_get_gamma (GnomeRRCrtc *crtc, int *size,
+ unsigned short **red, unsigned short **green,
+ unsigned short **blue)
+{
+ g_return_val_if_fail (crtc != NULL, FALSE);
+
+#ifdef HAVE_RANDR
+ int copy_size;
+ unsigned short *r, *g, *b;
+ XRRCrtcGamma *gamma;
+
+ gamma = XRRGetCrtcGamma (DISPLAY (crtc), crtc->id);
+ if (!gamma)
+ return FALSE;
+
+ copy_size = crtc->gamma_size * sizeof (unsigned short);
+
+ if (red) {
+ r = g_new0 (unsigned short, crtc->gamma_size);
+ memcpy (r, gamma->red, copy_size);
+ *red = r;
+ }
+
+ if (green) {
+ g = g_new0 (unsigned short, crtc->gamma_size);
+ memcpy (g, gamma->green, copy_size);
+ *green = g;
+ }
+
+ if (blue) {
+ b = g_new0 (unsigned short, crtc->gamma_size);
+ memcpy (b, gamma->blue, copy_size);
+ *blue = b;
+ }
+
+ XRRFreeGamma (gamma);
+
+ if (size)
+ *size = crtc->gamma_size;
+
+ return TRUE;
+#else
+ return FALSE;
+#endif /* HAVE_RANDR */
+}
+
+gboolean
+gnome_rr_x11_screen_force_timestamp_update (GnomeRRX11Screen *self)
+{
+#ifdef HAVE_RANDR
+ GnomeRRX11ScreenPrivate *priv = self->priv;
+ GnomeRRCrtc *crtc;
+ XRRCrtcInfo *current_info;
+ Status status;
+ gboolean timestamp_updated;
+ ScreenInfo *info;
+
+ timestamp_updated = FALSE;
+
+ info = GNOME_RR_SCREEN(self)->priv->info;
+ crtc = info->crtcs[0];
+
+ if (crtc == NULL)
+ goto out;
+
+ current_info = XRRGetCrtcInfo (priv->xdisplay,
+ info->resources,
+ crtc->id);
+
+ if (current_info == NULL)
+ goto out;
+
+ gdk_error_trap_push ();
+ status = XRRSetCrtcConfig (priv->xdisplay,
+ info->resources,
+ crtc->id,
+ current_info->timestamp,
+ current_info->x,
+ current_info->y,
+ current_info->mode,
+ current_info->rotation,
+ current_info->outputs,
+ current_info->noutput);
+
+ XRRFreeCrtcInfo (current_info);
+
+ gdk_flush ();
+ if (gdk_error_trap_pop ())
+ goto out;
+
+ if (status == RRSetConfigSuccess)
+ timestamp_updated = TRUE;
+out:
+ return timestamp_updated;
+#else
+ return FALSE;
+#endif
+}
diff --git a/gtk/display/gnome-rr-x11.h b/gtk/display/gnome-rr-x11.h
new file mode 100644
index 0000000..e8dabce
--- /dev/null
+++ b/gtk/display/gnome-rr-x11.h
@@ -0,0 +1,58 @@
+/* gnome-rr-x11.h
+ *
+ * Copyright 2011, Red Hat, Inc.
+ *
+ * This file is part of the Gnome Library.
+ *
+ * The Gnome 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.
+ *
+ * The Gnome 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 the Gnome Library; see the file COPYING.LIB. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Authors: Soren Sandmann <sandmann@redhat.com>
+ * Marc-André Lureau <marcandre.lureau@redhat.com>
+ */
+
+#ifndef GNOME_RR_X11_H
+#define GNOME_RR_X11_H
+
+#include <glib.h>
+#include "gnome-rr.h"
+
+#define GNOME_TYPE_RR_X11_SCREEN (gnome_rr_x11_screen_get_type())
+#define GNOME_RR_X11_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GNOME_TYPE_RR_X11_SCREEN, GnomeRRX11Screen))
+#define GNOME_IS_RR_X11_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GNOME_TYPE_RR_X11_SCREEN))
+#define GNOME_RR_X11_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GNOME_TYPE_RR_X11_SCREEN, GnomeRRX11ScreenClass))
+#define GNOME_IS_RR_X11_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GNOME_TYPE_RR_X11_SCREEN))
+#define GNOME_RR_X11_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GNOME_TYPE_RR_X11_SCREEN, GnomeRRX11ScreenClass))
+
+typedef struct GnomeRRX11ScreenPrivate GnomeRRX11ScreenPrivate;
+
+typedef struct {
+ GnomeRRScreen parent;
+
+ GnomeRRX11ScreenPrivate* priv;
+} GnomeRRX11Screen;
+
+typedef struct {
+ GnomeRRScreenClass parent_class;
+
+ void (* changed) (void);
+} GnomeRRX11ScreenClass;
+
+GType gnome_rr_x11_screen_get_type (void);
+
+G_GNUC_INTERNAL
+gboolean gnome_rr_x11_screen_force_timestamp_update (GnomeRRX11Screen *screen);
+
+#endif /* GNOME_RR_X11_H */
diff --git a/gtk/display/gnome-rr.c b/gtk/display/gnome-rr.c
index 0ddd215..f141e8e 100644
--- a/gtk/display/gnome-rr.c
+++ b/gtk/display/gnome-rr.c
@@ -30,6 +30,15 @@
#include <gtk/gtk.h>
+#ifdef HAVE_X11
+#include <X11/Xlib.h>
+#include <gdk/gdkx.h>
+#include <X11/Xatom.h>
+#include "gnome-rr-x11.h"
+#else
+#include "gnome-rr-windows.h"
+#endif
+
#undef GNOME_DISABLE_DEPRECATED
#include "gnome-rr.h"
#include "gnome-rr-config.h"
@@ -47,49 +56,21 @@ enum {
SCREEN_SIGNAL_LAST,
};
-gint screen_signals[SCREEN_SIGNAL_LAST];
+static gint screen_signals[SCREEN_SIGNAL_LAST];
+static GParamSpec *screen_properties[SCREEN_PROP_LAST];
/* GnomeRRCrtc */
-#ifdef HAVE_RANDR
-static GnomeRRCrtc * crtc_new (ScreenInfo *info,
- RRCrtc id);
-#endif
-
static GnomeRRCrtc * crtc_copy (const GnomeRRCrtc *from);
static void crtc_free (GnomeRRCrtc *crtc);
-#ifdef HAVE_RANDR
-static gboolean crtc_initialize (GnomeRRCrtc *crtc,
- XRRScreenResources *res,
- GError **error);
-/* GnomeRROutput */
-static GnomeRROutput *output_new (ScreenInfo *info,
- RROutput id);
-
-static gboolean output_initialize (GnomeRROutput *output,
- XRRScreenResources *res,
- GError **error);
-#endif
-
static GnomeRROutput *output_copy (const GnomeRROutput *from);
static void output_free (GnomeRROutput *output);
-#ifdef HAVE_RANDR
-/* GnomeRRMode */
-static GnomeRRMode * mode_new (ScreenInfo *info,
- RRMode id);
-
-static void mode_initialize (GnomeRRMode *mode,
- XRRModeInfo *info);
-#endif
-
static GnomeRRMode * mode_copy (const GnomeRRMode *from);
static void mode_free (GnomeRRMode *mode);
-static void gnome_rr_screen_finalize (GObject*);
static void gnome_rr_screen_set_property (GObject*, guint, const GValue*, GParamSpec*);
static void gnome_rr_screen_get_property (GObject*, guint, GValue*, GParamSpec*);
-static gboolean gnome_rr_screen_initable_init (GInitable*, GCancellable*, GError**);
static void gnome_rr_screen_initable_iface_init (GInitableIface *iface);
G_DEFINE_TYPE_WITH_CODE (GnomeRRScreen, gnome_rr_screen, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gnome_rr_screen_initable_iface_init))
@@ -114,14 +95,13 @@ gnome_rr_error_quark (void)
return g_quark_from_static_string ("gnome-rr-error-quark");
}
-#ifdef HAVE_RANDR
/* Screen */
-static GnomeRROutput *
+GnomeRROutput *
gnome_rr_output_by_id (ScreenInfo *info, RROutput id)
{
GnomeRROutput **output;
- g_assert (info != NULL);
+ g_return_val_if_fail (info != NULL, NULL);
for (output = info->outputs; *output; ++output)
{
@@ -132,7 +112,7 @@ gnome_rr_output_by_id (ScreenInfo *info, RROutput id)
return NULL;
}
-static GnomeRRCrtc *
+GnomeRRCrtc *
crtc_by_id (ScreenInfo *info, RRCrtc id)
{
GnomeRRCrtc **crtc;
@@ -149,12 +129,12 @@ crtc_by_id (ScreenInfo *info, RRCrtc id)
return NULL;
}
-static GnomeRRMode *
+GnomeRRMode *
mode_by_id (ScreenInfo *info, RRMode id)
{
GnomeRRMode **mode;
- g_assert (info != NULL);
+ g_return_val_if_fail (info != NULL, NULL);
for (mode = info->modes; *mode; ++mode)
{
@@ -164,16 +144,15 @@ mode_by_id (ScreenInfo *info, RRMode id)
return NULL;
}
-#endif
-static void
+void
screen_info_free (ScreenInfo *info)
{
GnomeRROutput **output;
GnomeRRCrtc **crtc;
GnomeRRMode **mode;
- g_assert (info != NULL);
+ g_return_if_fail (info != NULL);
#ifdef HAVE_RANDR
if (info->resources)
@@ -214,8 +193,7 @@ screen_info_free (ScreenInfo *info)
g_free (info);
}
-#ifdef HAVE_RANDR
-static gboolean
+gboolean
has_similar_mode (GnomeRROutput *output, GnomeRRMode *mode)
{
int i;
@@ -237,7 +215,7 @@ has_similar_mode (GnomeRROutput *output, GnomeRRMode *mode)
return FALSE;
}
-static void
+void
gather_clone_modes (ScreenInfo *info)
{
int i;
@@ -284,190 +262,13 @@ gather_clone_modes (ScreenInfo *info)
info->clone_modes = (GnomeRRMode **)g_ptr_array_free (result, FALSE);
}
-static gboolean
-fill_screen_info_from_resources (ScreenInfo *info,
- XRRScreenResources *resources,
- GError **error)
-{
- int i;
- GPtrArray *a;
- GnomeRRCrtc **crtc;
- GnomeRROutput **output;
-
- info->resources = resources;
-
- /* We create all the structures before initializing them, so
- * that they can refer to each other.
- */
- a = g_ptr_array_new ();
- for (i = 0; i < resources->ncrtc; ++i)
- {
- GnomeRRCrtc *crtc = crtc_new (info, resources->crtcs[i]);
-
- g_ptr_array_add (a, crtc);
- }
- g_ptr_array_add (a, NULL);
- info->crtcs = (GnomeRRCrtc **)g_ptr_array_free (a, FALSE);
-
- a = g_ptr_array_new ();
- for (i = 0; i < resources->noutput; ++i)
- {
- GnomeRROutput *output = output_new (info, resources->outputs[i]);
-
- g_ptr_array_add (a, output);
- }
- g_ptr_array_add (a, NULL);
- info->outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
-
- a = g_ptr_array_new ();
- for (i = 0; i < resources->nmode; ++i)
- {
- GnomeRRMode *mode = mode_new (info, resources->modes[i].id);
-
- g_ptr_array_add (a, mode);
- }
- g_ptr_array_add (a, NULL);
- info->modes = (GnomeRRMode **)g_ptr_array_free (a, FALSE);
-
- /* Initialize */
- for (crtc = info->crtcs; *crtc; ++crtc)
- {
- if (!crtc_initialize (*crtc, resources, error))
- return FALSE;
- }
-
- for (output = info->outputs; *output; ++output)
- {
- if (!output_initialize (*output, resources, error))
- return FALSE;
- }
-
- for (i = 0; i < resources->nmode; ++i)
- {
- GnomeRRMode *mode = mode_by_id (info, resources->modes[i].id);
-
- mode_initialize (mode, &(resources->modes[i]));
- }
-
- gather_clone_modes (info);
-
- return TRUE;
-}
-#endif /* HAVE_RANDR */
-
-#if !GTK_CHECK_VERSION (2, 91, 0)
-#define gdk_x11_window_get_xid gdk_x11_drawable_get_xid
-#define gdk_error_trap_pop_ignored gdk_error_trap_pop
-#endif
-
-#ifdef HAVE_X11
-static gboolean
-fill_out_screen_info (Display *xdisplay,
- Window xroot,
- ScreenInfo *info,
- gboolean needs_reprobe,
- GError **error)
-{
-#ifdef HAVE_RANDR
- XRRScreenResources *resources;
- GnomeRRScreenPrivate *priv;
-
- g_assert (xdisplay != NULL);
- g_assert (info != NULL);
-
- priv = info->screen->priv;
-
- /* First update the screen resources */
-
- if (needs_reprobe)
- resources = XRRGetScreenResources (xdisplay, xroot);
- else
- {
- /* XRRGetScreenResourcesCurrent is less expensive than
- * XRRGetScreenResources, however it is available only
- * in RandR 1.3 or higher
- */
-#if RANDR_LIBRARY_IS_AT_LEAST_1_3
- if (SERVERS_RANDR_IS_AT_LEAST_1_3 (priv))
- resources = XRRGetScreenResourcesCurrent (xdisplay, xroot);
- else
- resources = XRRGetScreenResources (xdisplay, xroot);
-#else
- resources = XRRGetScreenResources (xdisplay, xroot);
-#endif
- }
-
- if (resources)
- {
- if (!fill_screen_info_from_resources (info, resources, error))
- return FALSE;
- }
- else
- {
- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
- /* Translators: a CRTC is a CRT Controller (this is X terminology). */
- _("could not get the screen resources (CRTCs, outputs, modes)"));
- return FALSE;
- }
-
- /* Then update the screen size range. We do this after XRRGetScreenResources() so that
- * the X server will already have an updated view of the outputs.
- */
-
- if (needs_reprobe) {
- gboolean success;
-
- gdk_error_trap_push ();
- success = XRRGetScreenSizeRange (xdisplay, xroot,
- &(info->min_width),
- &(info->min_height),
- &(info->max_width),
- &(info->max_height));
- gdk_flush ();
- if (gdk_error_trap_pop ()) {
- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_UNKNOWN,
- _("unhandled X error while getting the range of screen sizes"));
- return FALSE;
- }
-
- if (!success) {
- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
- _("could not get the range of screen sizes"));
- return FALSE;
- }
- }
- else
- {
- gnome_rr_screen_get_ranges (info->screen,
- &(info->min_width),
- &(info->max_width),
- &(info->min_height),
- &(info->max_height));
- }
-
- info->primary = None;
-#if RANDR_LIBRARY_IS_AT_LEAST_1_3
- if (SERVERS_RANDR_IS_AT_LEAST_1_3 (priv)) {
- gdk_error_trap_push ();
- info->primary = XRRGetOutputPrimary (xdisplay, xroot);
- gdk_error_trap_pop_ignored ();
- }
-#endif
-
- return TRUE;
-#else
- return FALSE;
-#endif /* HAVE_RANDR */
-}
-#endif
-
-static ScreenInfo *
+ScreenInfo *
screen_info_new (GnomeRRScreen *screen, gboolean needs_reprobe, GError **error)
{
ScreenInfo *info = g_new0 (ScreenInfo, 1);
GnomeRRScreenPrivate *priv;
- g_assert (screen != NULL);
+ g_return_val_if_fail (screen != NULL, NULL);
priv = screen->priv;
@@ -476,26 +277,24 @@ screen_info_new (GnomeRRScreen *screen, gboolean needs_reprobe, GError **error)
info->modes = NULL;
info->screen = screen;
-#if HAVE_X11
- if (fill_out_screen_info (priv->xdisplay, priv->xroot, info, needs_reprobe, error))
+ if (fill_out_screen_info (screen, info, needs_reprobe, error))
{
return info;
}
else
-#endif
{
screen_info_free (info);
return NULL;
}
}
-static gboolean
+gboolean
screen_update (GnomeRRScreen *screen, gboolean force_callback, gboolean needs_reprobe, GError **error)
{
ScreenInfo *info;
gboolean changed = FALSE;
- g_assert (screen != NULL);
+ g_return_val_if_fail (screen != NULL, FALSE);
info = screen_info_new (screen, needs_reprobe, error);
if (!info)
@@ -516,173 +315,25 @@ screen_update (GnomeRRScreen *screen, gboolean force_callback, gboolean needs_re
return changed;
}
-static GdkFilterReturn
-screen_on_event (GdkXEvent *xevent,
- GdkEvent *event,
- gpointer data)
-{
-#ifdef HAVE_RANDR
- GnomeRRScreen *screen = data;
- GnomeRRScreenPrivate *priv = screen->priv;
- XEvent *e = xevent;
- int event_num;
-
- if (!e)
- return GDK_FILTER_CONTINUE;
-
- event_num = e->type - priv->randr_event_base;
-
- if (event_num == RRScreenChangeNotify) {
- /* We don't reprobe the hardware; we just fetch the X server's latest
- * state. The server already knows the new state of the outputs; that's
- * why it sent us an event!
- */
- screen_update (screen, TRUE, FALSE, NULL); /* NULL-GError */
-#if 0
- /* Enable this code to get a dialog showing the RANDR timestamps, for debugging purposes */
- {
- GtkWidget *dialog;
- XRRScreenChangeNotifyEvent *rr_event;
- static int dialog_num;
-
- rr_event = (XRRScreenChangeNotifyEvent *) e;
-
- dialog = gtk_message_dialog_new (NULL,
- 0,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_CLOSE,
- "RRScreenChangeNotify timestamps (%d):\n"
- "event change: %u\n"
- "event config: %u\n"
- "event serial: %lu\n"
- "----------------------"
- "screen change: %u\n"
- "screen config: %u\n",
- dialog_num++,
- (guint32) rr_event->timestamp,
- (guint32) rr_event->config_timestamp,
- rr_event->serial,
- (guint32) priv->info->resources->timestamp,
- (guint32) priv->info->resources->configTimestamp);
- g_signal_connect (dialog, "response",
- G_CALLBACK (gtk_widget_destroy), NULL);
- gtk_widget_show (dialog);
- }
-#endif
- }
-#if 0
- /* WHY THIS CODE IS DISABLED:
- *
- * Note that in gnome_rr_screen_new(), we only select for
- * RRScreenChangeNotifyMask. We used to select for other values in
- * RR*NotifyMask, but we weren't really doing anything useful with those
- * events. We only care about "the screens changed in some way or another"
- * for now.
- *
- * If we ever run into a situtation that could benefit from processing more
- * detailed events, we can enable this code again.
- *
- * Note that the X server sends RRScreenChangeNotify in conjunction with the
- * more detailed events from RANDR 1.2 - see xserver/randr/randr.c:TellChanged().
- */
- else if (event_num == RRNotify)
- {
- /* Other RandR events */
-
- XRRNotifyEvent *event = (XRRNotifyEvent *)e;
-
- /* Here we can distinguish between RRNotify events supported
- * since RandR 1.2 such as RRNotify_OutputProperty. For now, we
- * don't have anything special to do for particular subevent types, so
- * we leave this as an empty switch().
- */
- switch (event->subtype)
- {
- default:
- break;
- }
-
- /* No need to reprobe hardware here */
- screen_update (screen, TRUE, FALSE, NULL); /* NULL-GError */
- }
-#endif
-
-#endif /* HAVE_RANDR */
-
- /* Pass the event on to GTK+ */
- return GDK_FILTER_CONTINUE;
-}
-
static gboolean
gnome_rr_screen_initable_init (GInitable *initable, GCancellable *canc, GError **error)
{
-#ifdef HAVE_RANDR
GnomeRRScreen *self = GNOME_RR_SCREEN (initable);
GnomeRRScreenPrivate *priv = self->priv;
- Display *dpy = GDK_SCREEN_XDISPLAY (self->priv->gdk_screen);
- int event_base;
- int ignore;
-
- priv->connector_type_atom = XInternAtom (dpy, "ConnectorType", FALSE);
- if (XRRQueryExtension (dpy, &event_base, &ignore))
- {
- priv->randr_event_base = event_base;
-
- XRRQueryVersion (dpy, &priv->rr_major_version, &priv->rr_minor_version);
- if (priv->rr_major_version < 1 || (priv->rr_major_version == 1 && priv->rr_minor_version < 2)) {
- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_RANDR_EXTENSION,
- "RANDR extension is too old (must be at least 1.2)");
- return FALSE;
- }
-
- priv->info = screen_info_new (self, TRUE, error);
-
- if (!priv->info) {
- return FALSE;
- }
-
- XRRSelectInput (priv->xdisplay,
- priv->xroot,
- RRScreenChangeNotifyMask);
- gdk_x11_register_standard_event_type (gdk_screen_get_display (priv->gdk_screen),
- event_base,
- RRNotify + 1);
- gdk_window_add_filter (priv->gdk_root, screen_on_event, self);
-
- return TRUE;
- }
- else
- {
-#endif /* HAVE_RANDR */
- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_NO_RANDR_EXTENSION,
- _("RANDR extension is not present"));
+ priv->info = screen_info_new (self, TRUE, error);
+ g_return_val_if_fail (priv->info != NULL, FALSE);
- return FALSE;
-#ifdef HAVE_RANDR
- }
-#endif
+ return TRUE;
}
-void
+static void
gnome_rr_screen_initable_iface_init (GInitableIface *iface)
{
iface->init = gnome_rr_screen_initable_init;
}
-void
-gnome_rr_screen_finalize (GObject *gobject)
-{
- GnomeRRScreen *screen = GNOME_RR_SCREEN (gobject);
-
- gdk_window_remove_filter (screen->priv->gdk_root, screen_on_event, screen);
-
- screen_info_free (screen->priv->info);
-
- G_OBJECT_CLASS (gnome_rr_screen_parent_class)->finalize (gobject);
-}
-
-void
+static void
gnome_rr_screen_set_property (GObject *gobject, guint property_id, const GValue *value, GParamSpec *property)
{
GnomeRRScreen *self = GNOME_RR_SCREEN (gobject);
@@ -692,12 +343,7 @@ gnome_rr_screen_set_property (GObject *gobject, guint property_id, const GValue
{
case SCREEN_PROP_GDK_SCREEN:
priv->gdk_screen = g_value_get_object (value);
- priv->gdk_root = gdk_screen_get_root_window (priv->gdk_screen);
-#ifdef HAVE_X11
- priv->xroot = gdk_x11_window_get_xid (priv->gdk_root);
- priv->xdisplay = GDK_SCREEN_XDISPLAY (priv->gdk_screen);
- priv->xscreen = gdk_x11_screen_get_xscreen (priv->gdk_screen);
-#endif
+ g_object_notify_by_pspec (gobject, screen_properties[SCREEN_PROP_GDK_SCREEN]);
return;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, property);
@@ -705,16 +351,15 @@ gnome_rr_screen_set_property (GObject *gobject, guint property_id, const GValue
}
}
-void
+static void
gnome_rr_screen_get_property (GObject *gobject, guint property_id, GValue *value, GParamSpec *property)
{
GnomeRRScreen *self = GNOME_RR_SCREEN (gobject);
- GnomeRRScreenPrivate *priv = self->priv;
switch (property_id)
{
case SCREEN_PROP_GDK_SCREEN:
- g_value_set_object (value, priv->gdk_screen);
+ g_value_set_object (value, gnome_rr_screen_get_gdk_screen (self));
return;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, property);
@@ -722,6 +367,17 @@ gnome_rr_screen_get_property (GObject *gobject, guint property_id, GValue *value
}
}
+static void
+gnome_rr_screen_finalize (GObject *gobject)
+{
+ GnomeRRScreen *screen = GNOME_RR_SCREEN (gobject);
+
+ if (screen->priv->info)
+ screen_info_free (screen->priv->info);
+
+ G_OBJECT_CLASS (gnome_rr_screen_parent_class)->finalize (gobject);
+}
+
void
gnome_rr_screen_class_init (GnomeRRScreenClass *klass)
{
@@ -732,18 +388,19 @@ gnome_rr_screen_class_init (GnomeRRScreenClass *klass)
gobject_class->get_property = gnome_rr_screen_get_property;
gobject_class->finalize = gnome_rr_screen_finalize;
+ screen_properties[SCREEN_PROP_GDK_SCREEN] = g_param_spec_object (
+ "gdk-screen",
+ "GDK Screen",
+ "The GDK Screen represented by this GnomeRRScreen",
+ GDK_TYPE_SCREEN,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS);
+
g_object_class_install_property(
gobject_class,
SCREEN_PROP_GDK_SCREEN,
- g_param_spec_object (
- "gdk-screen",
- "GDK Screen",
- "The GDK Screen represented by this GnomeRRScreen",
- GDK_TYPE_SCREEN,
- G_PARAM_READWRITE |
- G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS)
- );
+ screen_properties[SCREEN_PROP_GDK_SCREEN]);
screen_signals[SCREEN_CHANGED] = g_signal_new("changed",
G_TYPE_FROM_CLASS (gobject_class),
@@ -763,14 +420,6 @@ gnome_rr_screen_init (GnomeRRScreen *self)
self->priv = priv;
priv->gdk_screen = NULL;
- priv->gdk_root = NULL;
-#ifdef HAVE_X11
- priv->xdisplay = NULL;
- priv->xroot = None;
- priv->xscreen = NULL;
- priv->rr_major_version = 0;
- priv->rr_minor_version = 0;
-#endif
priv->info = NULL;
}
@@ -779,7 +428,7 @@ gnome_rr_screen_init (GnomeRRScreen *self)
* Creates a new #GnomeRRScreen instance
*
* @screen: the #GdkScreen on which to operate
- * @error: will be set if XRandR is not supported
+ * @error: will be set if screen could not be created
*
* Returns: a new #GnomeRRScreen instance or NULL if screen could not be created,
* for instance if the driver does not support Xrandr 1.2
@@ -788,25 +437,14 @@ GnomeRRScreen *
gnome_rr_screen_new (GdkScreen *screen,
GError **error)
{
- /* _gnome_desktop_init_i18n (); */
- return g_initable_new (GNOME_TYPE_RR_SCREEN, NULL, error, "gdk-screen", screen, NULL);
-}
-
-void
-gnome_rr_screen_set_size (GnomeRRScreen *screen,
- int width,
- int height,
- int mm_width,
- int mm_height)
-{
- g_return_if_fail (GNOME_IS_RR_SCREEN (screen));
-
-#ifdef HAVE_RANDR
- gdk_error_trap_push ();
- XRRSetScreenSize (screen->priv->xdisplay, screen->priv->xroot,
- width, height, mm_width, mm_height);
- gdk_error_trap_pop_ignored ();
+ /* FIXME: _gnome_desktop_init_i18n (); */
+ return g_initable_new (
+#ifdef HAVE_X11
+ GNOME_TYPE_RR_X11_SCREEN,
+#else
+ GNOME_TYPE_RR_WINDOWS_SCREEN,
#endif
+ NULL, error, "gdk-screen", screen, NULL);
}
/**
@@ -877,57 +515,6 @@ gnome_rr_screen_get_timestamps (GnomeRRScreen *screen,
#endif
}
-static gboolean
-force_timestamp_update (GnomeRRScreen *screen)
-{
-#ifdef HAVE_RANDR
- GnomeRRScreenPrivate *priv = screen->priv;
- GnomeRRCrtc *crtc;
- XRRCrtcInfo *current_info;
- Status status;
- gboolean timestamp_updated;
-
- timestamp_updated = FALSE;
-
- crtc = priv->info->crtcs[0];
-
- if (crtc == NULL)
- goto out;
-
- current_info = XRRGetCrtcInfo (priv->xdisplay,
- priv->info->resources,
- crtc->id);
-
- if (current_info == NULL)
- goto out;
-
- gdk_error_trap_push ();
- status = XRRSetCrtcConfig (priv->xdisplay,
- priv->info->resources,
- crtc->id,
- current_info->timestamp,
- current_info->x,
- current_info->y,
- current_info->mode,
- current_info->rotation,
- current_info->outputs,
- current_info->noutput);
-
- XRRFreeCrtcInfo (current_info);
-
- gdk_flush ();
- if (gdk_error_trap_pop ())
- goto out;
-
- if (status == RRSetConfigSuccess)
- timestamp_updated = TRUE;
-out:
- return timestamp_updated;
-#else
- return FALSE;
-#endif
-}
-
/**
* gnome_rr_screen_refresh:
* @screen: a #GnomeRRScreen
@@ -954,9 +541,9 @@ gnome_rr_screen_refresh (GnomeRRScreen *screen,
#endif
refreshed = screen_update (screen, FALSE, TRUE, error);
- force_timestamp_update (screen); /* this is to keep other clients from thinking that the X server re-detected things by itself - bgo#621046 */
#ifdef HAVE_X11
+ gnome_rr_x11_screen_force_timestamp_update (GNOME_RR_X11_SCREEN (screen)); /* this is to keep other clients from thinking that the X server re-detected things by itself - bgo#621046 */
gdk_x11_display_ungrab (gdk_screen_get_display (screen->priv->gdk_screen));
#endif
@@ -1079,9 +666,8 @@ gnome_rr_screen_get_output_by_id (GnomeRRScreen *screen,
return NULL;
}
-#ifdef HAVE_RANDR
/* GnomeRROutput */
-static GnomeRROutput *
+GnomeRROutput *
output_new (ScreenInfo *info, RROutput id)
{
GnomeRROutput *output = g_slice_new0 (GnomeRROutput);
@@ -1091,195 +677,6 @@ output_new (ScreenInfo *info, RROutput id)
return output;
}
-#endif
-
-#ifdef HAVE_X11
-static guint8 *
-get_property (Display *dpy,
- RROutput output,
- Atom atom,
- int *len)
-{
-#ifdef HAVE_RANDR
- unsigned char *prop;
- int actual_format;
- unsigned long nitems, bytes_after;
- Atom actual_type;
- guint8 *result;
-
- XRRGetOutputProperty (dpy, output, atom,
- 0, 100, False, False,
- AnyPropertyType,
- &actual_type, &actual_format,
- &nitems, &bytes_after, &prop);
-
- if (actual_type == XA_INTEGER && actual_format == 8)
- {
- result = g_memdup (prop, nitems);
- if (len)
- *len = nitems;
- }
- else
- {
- result = NULL;
- }
-
- XFree (prop);
-
- return result;
-#else
- return NULL;
-#endif /* HAVE_RANDR */
-}
-
-static guint8 *
-read_edid_data (GnomeRROutput *output, int *len)
-{
- Atom edid_atom;
- guint8 *result;
-
- edid_atom = XInternAtom (DISPLAY (output), "EDID", FALSE);
- result = get_property (DISPLAY (output),
- output->id, edid_atom, len);
-
- if (!result)
- {
- edid_atom = XInternAtom (DISPLAY (output), "EDID_DATA", FALSE);
- result = get_property (DISPLAY (output),
- output->id, edid_atom, len);
- }
-
- if (result)
- {
- if (*len % 128 == 0)
- return result;
- else
- g_free (result);
- }
-
- return NULL;
-}
-#endif /* !HAVE_X11 - get_property */
-
-#ifdef HAVE_RANDR
-static char *
-get_connector_type_string (GnomeRROutput *output)
-{
-#ifdef HAVE_RANDR
- char *result;
- unsigned char *prop;
- int actual_format;
- unsigned long nitems, bytes_after;
- Atom actual_type;
- Atom connector_type;
- char *connector_type_str;
-
- result = NULL;
-
- if (XRRGetOutputProperty (DISPLAY (output), output->id, output->info->screen->priv->connector_type_atom,
- 0, 100, False, False,
- AnyPropertyType,
- &actual_type, &actual_format,
- &nitems, &bytes_after, &prop) != Success)
- return NULL;
-
- if (!(actual_type == XA_ATOM && actual_format == 32 && nitems == 1))
- goto out;
-
- connector_type = *((Atom *) prop);
-
- connector_type_str = XGetAtomName (DISPLAY (output), connector_type);
- if (connector_type_str) {
- result = g_strdup (connector_type_str); /* so the caller can g_free() it */
- XFree (connector_type_str);
- }
-
-out:
-
- XFree (prop);
-
- return result;
-#else
- return NULL;
-#endif
-}
-
-static gboolean
-output_initialize (GnomeRROutput *output, XRRScreenResources *res, GError **error)
-{
- XRROutputInfo *info = XRRGetOutputInfo (
- DISPLAY (output), res, output->id);
- GPtrArray *a;
- int i;
-
-#if 0
- g_print ("Output %lx Timestamp: %u\n", output->id, (guint32)info->timestamp);
-#endif
-
- if (!info || !output->info)
- {
- /* FIXME: see the comment in crtc_initialize() */
- /* Translators: here, an "output" is a video output */
- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
- _("could not get information about output %d"),
- (int) output->id);
- return FALSE;
- }
-
- output->name = g_strdup (info->name); /* FIXME: what is nameLen used for? */
- output->current_crtc = crtc_by_id (output->info, info->crtc);
- output->width_mm = info->mm_width;
- output->height_mm = info->mm_height;
- output->connected = (info->connection == RR_Connected);
- output->connector_type = get_connector_type_string (output);
-
- /* Possible crtcs */
- a = g_ptr_array_new ();
-
- for (i = 0; i < info->ncrtc; ++i)
- {
- GnomeRRCrtc *crtc = crtc_by_id (output->info, info->crtcs[i]);
-
- if (crtc)
- g_ptr_array_add (a, crtc);
- }
- g_ptr_array_add (a, NULL);
- output->possible_crtcs = (GnomeRRCrtc **)g_ptr_array_free (a, FALSE);
-
- /* Clones */
- a = g_ptr_array_new ();
- for (i = 0; i < info->nclone; ++i)
- {
- GnomeRROutput *gnome_rr_output = gnome_rr_output_by_id (output->info, info->clones[i]);
-
- if (gnome_rr_output)
- g_ptr_array_add (a, gnome_rr_output);
- }
- g_ptr_array_add (a, NULL);
- output->clones = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
-
- /* Modes */
- a = g_ptr_array_new ();
- for (i = 0; i < info->nmode; ++i)
- {
- GnomeRRMode *mode = mode_by_id (output->info, info->modes[i]);
-
- if (mode)
- g_ptr_array_add (a, mode);
- }
- g_ptr_array_add (a, NULL);
- output->modes = (GnomeRRMode **)g_ptr_array_free (a, FALSE);
-
- output->n_preferred = info->npreferred;
-
- /* Edid data */
- output->edid_data = read_edid_data (output, &output->edid_size);
-
- XRRFreeOutputInfo (info);
-
- return TRUE;
-}
-#endif /* HAVE_RANDR */
static GnomeRROutput*
output_copy (const GnomeRROutput *from)
@@ -1342,7 +739,7 @@ output_free (GnomeRROutput *output)
guint32
gnome_rr_output_get_id (GnomeRROutput *output)
{
- g_assert(output != NULL);
+ g_return_val_if_fail (output != NULL, 0);
return output->id;
}
@@ -1456,21 +853,21 @@ gnome_rr_output_get_position (GnomeRROutput *output,
const char *
gnome_rr_output_get_name (GnomeRROutput *output)
{
- g_assert (output != NULL);
+ g_return_val_if_fail (output != NULL, "");
return output->name;
}
int
gnome_rr_output_get_width_mm (GnomeRROutput *output)
{
- g_assert (output != NULL);
+ g_return_val_if_fail (output != NULL, -1);
return output->width_mm;
}
int
gnome_rr_output_get_height_mm (GnomeRROutput *output)
{
- g_assert (output != NULL);
+ g_return_val_if_fail (output != NULL, -1);
return output->height_mm;
}
@@ -1567,55 +964,6 @@ gnome_rr_screen_set_primary_output (GnomeRRScreen *screen,
#endif
}
-#ifdef HAVE_RANDR
-/* GnomeRRCrtc */
-typedef struct
-{
- Rotation xrot;
- GnomeRRRotation rot;
-} RotationMap;
-
-static const RotationMap rotation_map[] =
-{
- { RR_Rotate_0, GNOME_RR_ROTATION_0 },
- { RR_Rotate_90, GNOME_RR_ROTATION_90 },
- { RR_Rotate_180, GNOME_RR_ROTATION_180 },
- { RR_Rotate_270, GNOME_RR_ROTATION_270 },
- { RR_Reflect_X, GNOME_RR_REFLECT_X },
- { RR_Reflect_Y, GNOME_RR_REFLECT_Y },
-};
-
-static GnomeRRRotation
-gnome_rr_rotation_from_xrotation (Rotation r)
-{
- int i;
- GnomeRRRotation result = 0;
-
- for (i = 0; i < G_N_ELEMENTS (rotation_map); ++i)
- {
- if (r & rotation_map[i].xrot)
- result |= rotation_map[i].rot;
- }
-
- return result;
-}
-
-static Rotation
-xrotation_from_rotation (GnomeRRRotation r)
-{
- int i;
- Rotation result = 0;
-
- for (i = 0; i < G_N_ELEMENTS (rotation_map); ++i)
- {
- if (r & rotation_map[i].rot)
- result |= rotation_map[i].xrot;
- }
-
- return result;
-}
-#endif
-
#ifndef GNOME_DISABLE_DEPRECATED_SOURCE
gboolean
gnome_rr_crtc_set_config (GnomeRRCrtc *crtc,
@@ -1631,85 +979,6 @@ gnome_rr_crtc_set_config (GnomeRRCrtc *crtc,
}
#endif
-gboolean
-gnome_rr_crtc_set_config_with_time (GnomeRRCrtc *crtc,
- guint32 timestamp,
- int x,
- int y,
- GnomeRRMode *mode,
- GnomeRRRotation rotation,
- GnomeRROutput **outputs,
- int n_outputs,
- GError **error)
-{
-#ifdef HAVE_RANDR
- ScreenInfo *info;
- GArray *output_ids;
- Status status;
- gboolean result;
- int i;
-
- g_return_val_if_fail (crtc != NULL, FALSE);
- g_return_val_if_fail (mode != NULL || outputs == NULL || n_outputs == 0, FALSE);
- g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
- info = crtc->info;
-
- if (mode)
- {
- if (x + mode->width > info->max_width
- || y + mode->height > info->max_height)
- {
- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_BOUNDS_ERROR,
- /* Translators: the "position", "size", and "maximum"
- * words here are not keywords; please translate them
- * as usual. A CRTC is a CRT Controller (this is X terminology) */
- _("requested position/size for CRTC %d is outside the allowed limit: "
- "position=(%d, %d), size=(%d, %d), maximum=(%d, %d)"),
- (int) crtc->id,
- x, y,
- mode->width, mode->height,
- info->max_width, info->max_height);
- return FALSE;
- }
- }
-
- output_ids = g_array_new (FALSE, FALSE, sizeof (RROutput));
-
- if (outputs)
- {
- for (i = 0; i < n_outputs; ++i)
- g_array_append_val (output_ids, outputs[i]->id);
- }
-
- status = XRRSetCrtcConfig (DISPLAY (crtc), info->resources, crtc->id,
- timestamp,
- x, y,
- mode ? mode->id : None,
- xrotation_from_rotation (rotation),
- (RROutput *)output_ids->data,
- output_ids->len);
-
- g_array_free (output_ids, TRUE);
-
- if (status == RRSetConfigSuccess)
- result = TRUE;
- else {
- result = FALSE;
- /* Translators: CRTC is a CRT Controller (this is X terminology).
- * It is *very* unlikely that you'll ever get this error, so it is
- * only listed for completeness. */
- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
- _("could not set the configuration for CRTC %d"),
- (int) crtc->id);
- }
-
- return result;
-#else
- return FALSE;
-#endif /* HAVE_RANDR */
-}
-
GnomeRRMode *
gnome_rr_crtc_get_current_mode (GnomeRRCrtc *crtc)
{
@@ -1763,14 +1032,14 @@ gnome_rr_crtc_get_position (GnomeRRCrtc *crtc,
GnomeRRRotation
gnome_rr_crtc_get_current_rotation (GnomeRRCrtc *crtc)
{
- g_assert(crtc != NULL);
+ g_return_val_if_fail (crtc != NULL, GNOME_RR_ROTATION_0);
return crtc->current_rotation;
}
GnomeRRRotation
gnome_rr_crtc_get_rotations (GnomeRRCrtc *crtc)
{
- g_assert(crtc != NULL);
+ g_return_val_if_fail (crtc != NULL, GNOME_RR_ROTATION_0);
return crtc->rotations;
}
@@ -1782,8 +1051,7 @@ gnome_rr_crtc_supports_rotation (GnomeRRCrtc * crtc,
return (crtc->rotations & rotation);
}
-#ifdef HAVE_RANDR
-static GnomeRRCrtc *
+GnomeRRCrtc *
crtc_new (ScreenInfo *info, RROutput id)
{
GnomeRRCrtc *crtc = g_slice_new0 (GnomeRRCrtc);
@@ -1793,7 +1061,6 @@ crtc_new (ScreenInfo *info, RROutput id)
return crtc;
}
-#endif
static GnomeRRCrtc *
crtc_copy (const GnomeRRCrtc *from)
@@ -1828,77 +1095,6 @@ crtc_copy (const GnomeRRCrtc *from)
return to;
}
-#ifdef HAVE_RANDR
-static gboolean
-crtc_initialize (GnomeRRCrtc *crtc,
- XRRScreenResources *res,
- GError **error)
-{
- XRRCrtcInfo *info = XRRGetCrtcInfo (DISPLAY (crtc), res, crtc->id);
- GPtrArray *a;
- int i;
-
-#if 0
- g_print ("CRTC %lx Timestamp: %u\n", crtc->id, (guint32)info->timestamp);
-#endif
-
- if (!info)
- {
- /* FIXME: We need to reaquire the screen resources */
- /* FIXME: can we actually catch BadRRCrtc, and does it make sense to emit that? */
-
- /* Translators: CRTC is a CRT Controller (this is X terminology).
- * It is *very* unlikely that you'll ever get this error, so it is
- * only listed for completeness. */
- g_set_error (error, GNOME_RR_ERROR, GNOME_RR_ERROR_RANDR_ERROR,
- _("could not get information about CRTC %d"),
- (int) crtc->id);
- return FALSE;
- }
-
- /* GnomeRRMode */
- crtc->current_mode = mode_by_id (crtc->info, info->mode);
-
- crtc->x = info->x;
- crtc->y = info->y;
-
- /* Current outputs */
- a = g_ptr_array_new ();
- for (i = 0; i < info->noutput; ++i)
- {
- GnomeRROutput *output = gnome_rr_output_by_id (crtc->info, info->outputs[i]);
-
- if (output)
- g_ptr_array_add (a, output);
- }
- g_ptr_array_add (a, NULL);
- crtc->current_outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
-
- /* Possible outputs */
- a = g_ptr_array_new ();
- for (i = 0; i < info->npossible; ++i)
- {
- GnomeRROutput *output = gnome_rr_output_by_id (crtc->info, info->possible[i]);
-
- if (output)
- g_ptr_array_add (a, output);
- }
- g_ptr_array_add (a, NULL);
- crtc->possible_outputs = (GnomeRROutput **)g_ptr_array_free (a, FALSE);
-
- /* Rotations */
- crtc->current_rotation = gnome_rr_rotation_from_xrotation (info->rotation);
- crtc->rotations = gnome_rr_rotation_from_xrotation (info->rotations);
-
- XRRFreeCrtcInfo (info);
-
- /* get an store gamma size */
- crtc->gamma_size = XRRGetCrtcGammaSize (DISPLAY (crtc), crtc->id);
-
- return TRUE;
-}
-#endif
-
static void
crtc_free (GnomeRRCrtc *crtc)
{
@@ -1907,9 +1103,8 @@ crtc_free (GnomeRRCrtc *crtc)
g_slice_free (GnomeRRCrtc, crtc);
}
-#ifdef HAVE_RANDR
/* GnomeRRMode */
-static GnomeRRMode *
+GnomeRRMode *
mode_new (ScreenInfo *info, RRMode id)
{
GnomeRRMode *mode = g_slice_new0 (GnomeRRMode);
@@ -1919,7 +1114,6 @@ mode_new (ScreenInfo *info, RRMode id)
return mode;
}
-#endif
guint32
gnome_rr_mode_get_id (GnomeRRMode *mode)
@@ -1949,20 +1143,6 @@ gnome_rr_mode_get_height (GnomeRRMode *mode)
return mode->height;
}
-#ifdef HAVE_RANDR
-static void
-mode_initialize (GnomeRRMode *mode, XRRModeInfo *info)
-{
- g_assert (mode != NULL);
- g_assert (info != NULL);
-
- mode->name = g_strdup (info->name);
- mode->width = info->width;
- mode->height = info->height;
- mode->freq = ((info->dotClock / (double)info->hTotal) / info->vTotal + 0.5) * 1000;
-}
-#endif /* HAVE_RANDR */
-
static GnomeRRMode *
mode_copy (const GnomeRRMode *from)
{
@@ -1985,80 +1165,10 @@ mode_free (GnomeRRMode *mode)
g_slice_free (GnomeRRMode, mode);
}
-void
-gnome_rr_crtc_set_gamma (GnomeRRCrtc *crtc, int size,
- unsigned short *red,
- unsigned short *green,
- unsigned short *blue)
+GdkScreen *
+gnome_rr_screen_get_gdk_screen (GnomeRRScreen *self)
{
-#ifdef HAVE_RANDR
- int copy_size;
- XRRCrtcGamma *gamma;
-
- g_return_if_fail (crtc != NULL);
- g_return_if_fail (red != NULL);
- g_return_if_fail (green != NULL);
- g_return_if_fail (blue != NULL);
-
- if (size != crtc->gamma_size)
- return;
-
- gamma = XRRAllocGamma (crtc->gamma_size);
+ g_return_val_if_fail (self != NULL, NULL);
- copy_size = crtc->gamma_size * sizeof (unsigned short);
- memcpy (gamma->red, red, copy_size);
- memcpy (gamma->green, green, copy_size);
- memcpy (gamma->blue, blue, copy_size);
-
- XRRSetCrtcGamma (DISPLAY (crtc), crtc->id, gamma);
- XRRFreeGamma (gamma);
-#endif /* HAVE_RANDR */
-}
-
-gboolean
-gnome_rr_crtc_get_gamma (GnomeRRCrtc *crtc, int *size,
- unsigned short **red, unsigned short **green,
- unsigned short **blue)
-{
-#ifdef HAVE_RANDR
- int copy_size;
- unsigned short *r, *g, *b;
- XRRCrtcGamma *gamma;
-
- g_return_val_if_fail (crtc != NULL, FALSE);
-
- gamma = XRRGetCrtcGamma (DISPLAY (crtc), crtc->id);
- if (!gamma)
- return FALSE;
-
- copy_size = crtc->gamma_size * sizeof (unsigned short);
-
- if (red) {
- r = g_new0 (unsigned short, crtc->gamma_size);
- memcpy (r, gamma->red, copy_size);
- *red = r;
- }
-
- if (green) {
- g = g_new0 (unsigned short, crtc->gamma_size);
- memcpy (g, gamma->green, copy_size);
- *green = g;
- }
-
- if (blue) {
- b = g_new0 (unsigned short, crtc->gamma_size);
- memcpy (b, gamma->blue, copy_size);
- *blue = b;
- }
-
- XRRFreeGamma (gamma);
-
- if (size)
- *size = crtc->gamma_size;
-
- return TRUE;
-#else
- return FALSE;
-#endif /* HAVE_RANDR */
+ return self->priv->gdk_screen;
}
-
diff --git a/gtk/spicy.c b/gtk/spicy.c
index 7a16855..e23a1dd 100644
--- a/gtk/spicy.c
+++ b/gtk/spicy.c
@@ -1340,9 +1340,9 @@ int main(int argc, char *argv[])
mainloop = g_main_loop_new(NULL, false);
rrscreen = gnome_rr_screen_new(gdk_screen_get_default (), &error);
g_warn_if_fail(rrscreen != NULL);
- g_signal_connect(rrscreen, "changed", G_CALLBACK(on_screen_changed), NULL);
+ if (rrscreen)
+ g_signal_connect(rrscreen, "changed", G_CALLBACK(on_screen_changed), NULL);
on_screen_changed(rrscreen, NULL);
-
conn = connection_new();
spice_cmdline_session_setup(conn->session);
connection_connect(conn);