diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2011-03-22 11:53:42 +0100 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2011-03-22 11:53:42 +0100 |
commit | 02b6087c2d99d13bf16116673ec85324276ee49b (patch) | |
tree | 4d5d5ed9912eddbc5765c1741f44f120ff7e739d /gtk | |
parent | 279ef8bc87bf736b5600eba00947624d8139a189 (diff) |
gtk/display: split x11/windows backend
For better or worse..
Diffstat (limited to 'gtk')
-rw-r--r-- | gtk/display/gnome-rr-config.c | 2 | ||||
-rw-r--r-- | gtk/display/gnome-rr-private.h | 92 | ||||
-rw-r--r-- | gtk/display/gnome-rr-windows.c | 111 | ||||
-rw-r--r-- | gtk/display/gnome-rr-windows.h | 55 | ||||
-rw-r--r-- | gtk/display/gnome-rr-x11.c | 943 | ||||
-rw-r--r-- | gtk/display/gnome-rr-x11.h | 58 | ||||
-rw-r--r-- | gtk/display/gnome-rr.c | 1042 | ||||
-rw-r--r-- | gtk/spicy.c | 4 |
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); |