Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Evergreen:11.1:kernel-2.6.32
gnome-panel
gnome-panel-bnc479684-pick-primary-output.diff
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gnome-panel-bnc479684-pick-primary-output.diff of Package gnome-panel
diff --git a/configure.in b/configure.in index 4824f84..75ec51e 100644 --- a/configure.in +++ b/configure.in @@ -266,6 +266,12 @@ PKG_CHECK_MODULES(X, x11 xau, :, [ AC_SUBST(X_LIBS) +dnl X RANDR extension + +if $PKG_CONFIG --exists "xrandr >= 1.2.0" ; then + AC_DEFINE(HAVE_RANDR, 1, [Have the Xrandr extension library]) +fi + dnl IDL directories ORBIT_IDL="`$PKG_CONFIG --variable=orbit_idl ORBit-2.0`" diff --git a/gnome-panel/panel-multiscreen.c b/gnome-panel/panel-multiscreen.c index 06df009..0a542ce 100644 --- a/gnome-panel/panel-multiscreen.c +++ b/gnome-panel/panel-multiscreen.c @@ -25,6 +25,9 @@ #include <config.h> +#include <X11/Xlib.h> +#include <X11/extensions/Xrandr.h> +#include <gdk/gdkx.h> #include "panel-multiscreen.h" #include <string.h> @@ -40,6 +43,134 @@ static int screens = 0; static int *monitors = NULL; static GdkRectangle **geometries = NULL; static gboolean initialized = FALSE; +static gboolean have_randr; + +static gboolean +get_xrandr_monitor_geometries (GdkScreen *screen, int *monitors_ret, GdkRectangle **geometries_ret) +{ + if (!have_randr) + return FALSE; + +#ifdef HAVE_RANDR + /* GTK+ 2.14.x uses the Xinerama API, instead of RANDR, to get the + * monitor geometries. It does this to avoid calling + * XRRGetScreenResources(), which is slow as it re-detects all the + * monitors --- note that XRRGetScreenResourcesCurrent() had not been + * introduced yet. Using Xinerama in GTK+ has the bad side effect that + * gdk_screen_get_monitor_plug_name() will return NULL, as Xinerama does + * not provide that information, unlike RANDR. + * + * Here we need to identify the output names, so that we can put the + * built-in LCD in a laptop *before* all other outputs. This is so that + * gnome-panel will normally prefer to appear on the "native" display + * rather than on an external monitor. + * + * To get the output names and geometries, we will not use + * gdk_screen_get_n_monitors() and friends, but rather we will call + * XRR*() directly. + * + * See https://bugzilla.novell.com/show_bug.cgi?id=479684 for this + * particular bug, and and + * http://bugzilla.gnome.org/show_bug.cgi?id=562944 for a more long-term + * solution. + */ + + Display *xdisplay; + XRRScreenResources *resources; + GArray *geometries; + int i; + gboolean driver_is_pre_randr_1_2; + + xdisplay = GDK_SCREEN_XDISPLAY (screen); + + resources = XRRGetScreenResources (xdisplay, GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen))); + if (!resources) + return FALSE; + + geometries = g_array_sized_new (FALSE, FALSE, sizeof (GdkRectangle), resources->noutput); + + driver_is_pre_randr_1_2 = FALSE; + + for (i = 0; i < resources->noutput; i++) { + XRROutputInfo *output; + + output = XRRGetOutputInfo (xdisplay, resources, resources->outputs[i]); + + if (g_strcmp0 (output->name, "default") == 0) + driver_is_pre_randr_1_2 = TRUE; /* Drivers before RANDR 1.2 return "default" for the output name */ + + if (output->connection != RR_Disconnected && output->crtc != 0) { + XRRCrtcInfo *crtc; + GdkRectangle rect; + + crtc = XRRGetCrtcInfo (xdisplay, resources, output->crtc); + + rect.x = crtc->x; + rect.y = crtc->y; + rect.width = crtc->width; + rect.height = crtc->height; + + XRRFreeCrtcInfo (crtc); + + /* "LVDS" is the oh-so-intuitive name that X gives to laptop LCDs. + * + * Note that on RANDR 1.3, the right way to check for + * this is to get the ConnectorType property for the + * output, and see if it is "Panel". Yes, they changed + * the known output names for 1.3. Amateurs. + */ + + if (g_str_has_prefix (output->name, "LVDS")) /* can be "LVDS0", "LVDS-0", etc. */ + g_array_prepend_vals (geometries, &rect, 1); + else + g_array_append_vals (geometries, &rect, 1); + } + + XRRFreeOutputInfo (output); + } + + XRRFreeScreenResources (resources); + + if (driver_is_pre_randr_1_2) { + /* Drivers before RANDR 1.2 don't provide useful info about outputs */ + g_array_free (geometries, TRUE); + return FALSE; + } + + *monitors_ret = geometries->len; + *geometries_ret = (GdkRectangle *) g_array_free (geometries, FALSE); + + return TRUE; +#else + return FALSE; +#endif +} + +static void +get_gdk_monitor_geometries (GdkScreen *screen, int *monitors_ret, GdkRectangle **geometries_ret) +{ + int num_monitors; + GdkRectangle *geometries; + int i; + + num_monitors = gdk_screen_get_n_monitors (screen); + geometries = g_new (GdkRectangle, num_monitors); + + for (i = 0; i < num_monitors; i++) + gdk_screen_get_monitor_geometry (screen, i, &(geometries[i])); + + *monitors_ret = num_monitors; + *geometries_ret = geometries; +} + +static void +get_raw_monitor_geometries (GdkScreen *screen, int *monitors_ret, GdkRectangle **geometries_ret) +{ + if (get_xrandr_monitor_geometries (screen, monitors_ret, geometries_ret)) + return; + + get_gdk_monitor_geometries (screen, monitors_ret, geometries_ret); +} static gboolean overlaps (GdkRectangle *a, GdkRectangle *b) @@ -54,17 +185,14 @@ pixels_in_rectangle (GdkRectangle *r) } static void -get_monitors_for_screen (GdkScreen *screen, int *monitors_ret, GdkRectangle **geometries_ret) +compress_overlapping_monitors (int *num_monitors_inout, GdkRectangle **geometries_inout) { int num_monitors; GdkRectangle *geometries; int i; - num_monitors = gdk_screen_get_n_monitors (screen); - geometries = g_new (GdkRectangle, num_monitors); - - for (i = 0; i < num_monitors; i++) - gdk_screen_get_monitor_geometry (screen, i, &(geometries[i])); + num_monitors = *num_monitors_inout; + geometries = *geometries_inout; /* http://bugzilla.gnome.org/show_bug.cgi?id=530969 * https://bugzilla.novell.com/show_bug.cgi?id=310208 @@ -142,10 +270,50 @@ get_monitors_for_screen (GdkScreen *screen, int *monitors_ret, GdkRectangle **ge } } + *num_monitors_inout = num_monitors; + *geometries_inout = geometries; +} + +static void +get_monitors_for_screen (GdkScreen *screen, int *monitors_ret, GdkRectangle **geometries_ret) +{ + int num_monitors; + GdkRectangle *geometries; + + get_raw_monitor_geometries (screen, &num_monitors, &geometries); + compress_overlapping_monitors (&num_monitors, &geometries); + *monitors_ret = num_monitors; *geometries_ret = geometries; } +static void +init_randr (GdkDisplay *display) +{ +#ifdef HAVE_RANDR + Display *xdisplay; + int event_base, error_base; +#endif + + have_randr = FALSE; + +#ifdef HAVE_RANDR + xdisplay = GDK_DISPLAY_XDISPLAY (display); + + /* We don't remember the event/error bases, as we expect to get "screen + * changed" events from GdkScreen instead. + */ + + if (XRRQueryExtension (xdisplay, &event_base, &error_base)) { + int major, minor; + + XRRQueryVersion (xdisplay, &major, &minor); + if ((major == 1 && minor >= 2) || major > 1) + have_randr = TRUE; + } +#endif +} + void panel_multiscreen_init (void) { @@ -158,6 +326,8 @@ panel_multiscreen_init (void) display = gdk_display_get_default (); screens = gdk_display_get_n_screens (display); + init_randr (display); + monitors = g_new0 (int, screens); geometries = g_new0 (GdkRectangle *, screens);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor