gtk2/gtk2-bnc343858-buggy-intel-xinerama.patch

147 lines
4.8 KiB
Diff

2008-01-15 Federico Mena Quintero <federico@novell.com>
Start fixing https://bugzilla.novell.com/show_bug.cgi?id=343858 -
X servers with Intel 915GM graphics report a connected VGA output
incorrectly, so applications don't use the whole screen.
* gdk/x11/gdkscreen-x11.c (check_xfree_xinerama): Sanitize the
monitors that we get from XineramaQueryScreens().
(sanitize_monitors): Workaround for an Intel 915GM driver bug,
where it will return that a VGA output is connected to a laptop,
even though it isn't. In the case of just two overlapping
monitors ("laptop plus cloned external display"), simulate that we
have only *one* monitor.
diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c
index 624870f..7626ca8 100644
--- a/gdk/x11/gdkscreen-x11.c
+++ b/gdk/x11/gdkscreen-x11.c
@@ -596,6 +596,73 @@ check_solaris_xinerama (GdkScreen *screen)
return FALSE;
}
+static GdkRectangle
+pick_the_biggest_geometry (GdkRectangle *geometries, int num_geometries)
+{
+ long max_pixels;
+ int largest_index;
+ int i;
+
+ max_pixels = 0;
+ largest_index = 0;
+
+ for (i = 0; i < num_geometries; i++)
+ {
+ long pixels;
+
+ pixels = (long) geometries[i].width * geometries[i].height;
+
+ if (pixels > max_pixels)
+ {
+ max_pixels = pixels;
+ largest_index = i;
+ }
+ }
+
+ return geometries[largest_index];
+}
+
+static void
+sanitize_monitors (GdkRectangle *monitors, int n_monitors,
+ GdkRectangle **monitors_ret, int *n_monitors_ret)
+{
+ if (n_monitors == 2
+ && gdk_rectangle_intersect (monitors + 0, monitors + 1, NULL))
+ {
+ /* https://bugzilla.novell.com/show_bug.cgi?id=310208
+ *
+ * The X driver for Intel 915GM chipsets has/had a bug where it would
+ * report that laptops started with a VGA output connected, and most
+ * of the time it defaults to a resolution of 1024x768. This doesn't
+ * match the resolution of the laptop, which these days is big and fancy.
+ *
+ * Both monitors (the VGA output's and the laptop's) *overlap* in the Xinerama
+ * configuration, since that is how "clone the display" is implemented.
+ * So, we see if there are only two monitors *and* if they intersect --- in
+ * that case, we can be reasonably confident that we can just pick the bigger
+ * monitor, which will be the laptop's display.
+ *
+ * This shouldn't break real setups with "make a big screen out of two monitors",
+ * since those monitors don't overlap in the Xinerama configuration.
+ *
+ * To summarize: in the case of just two overlapping monitors ("laptop
+ * plus cloned external display"), we simulate that we have only *one* monitor.
+ */
+
+ *n_monitors_ret = 1;
+ *monitors_ret = g_new (GdkRectangle, 1);
+
+ **monitors_ret = pick_the_biggest_geometry (monitors, n_monitors);
+
+ g_free (monitors);
+ }
+ else
+ {
+ *monitors_ret = monitors;
+ *n_monitors_ret = n_monitors;
+ }
+}
+
static gboolean
check_xfree_xinerama (GdkScreen *screen)
{
@@ -603,9 +670,10 @@ check_xfree_xinerama (GdkScreen *screen)
if (XineramaIsActive (GDK_SCREEN_XDISPLAY (screen)))
{
GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen);
+ int num_monitors;
XineramaScreenInfo *monitors = XineramaQueryScreens (GDK_SCREEN_XDISPLAY (screen),
- &screen_x11->num_monitors);
- if (screen_x11->num_monitors <= 0 || monitors == NULL)
+ &num_monitors);
+ if (num_monitors <= 0 || monitors == NULL)
{
/* If Xinerama doesn't think we have any monitors, try acting as
* though we had no Xinerama. If the "no monitors" condition
@@ -614,23 +682,34 @@ check_xfree_xinerama (GdkScreen *screen)
* and can go back into Xinerama-ish mode at that point. */
if (monitors)
XFree (monitors);
+
+ screen_x11->num_monitors = 0;
return FALSE;
}
else
{
+ GdkRectangle *rects;
int i;
- screen_x11->monitors = g_new0 (GdkRectangle, screen_x11->num_monitors);
+ GdkRectangle *sane_rects;
+ int sane_num_monitors;
+
+ rects = g_new0 (GdkRectangle, num_monitors);
- for (i = 0; i < screen_x11->num_monitors; i++)
+ for (i = 0; i < num_monitors; i++)
{
- screen_x11->monitors[i].x = monitors[i].x_org;
- screen_x11->monitors[i].y = monitors[i].y_org;
- screen_x11->monitors[i].width = monitors[i].width;
- screen_x11->monitors[i].height = monitors[i].height;
+ rects[i].x = monitors[i].x_org;
+ rects[i].y = monitors[i].y_org;
+ rects[i].width = monitors[i].width;
+ rects[i].height = monitors[i].height;
}
XFree (monitors);
+ sanitize_monitors (rects, num_monitors, &sane_rects, &sane_num_monitors);
+
+ screen_x11->num_monitors = sane_num_monitors;
+ screen_x11->monitors = sane_rects;
+
return TRUE;
}
}