-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256

Am 21.07.2010 13:47, awesome wrote:
> THIS IS AN AUTOMATED MESSAGE, DO NOT REPLY.
> 
> The following task has a new comment added:
> 
> FS#784 - Nvidia's TwinView is not working on awesome 3.4.5+ (Git)
> User who did this - Uli Schlachter (psychon)
> 
> ----------
> I just had an idea.
> 
> The current situation is:
> - If Xrandr is available, use it
> - Else check if Xinerama is available and use it
> - Else assume a single screen
> 
> We could change this into something like this:
> - If Xrandr is available and reports more than one screen, use it
> - Else check if Xinerama is available and use it (No point in checking if 
> there is more than one screen here, doesnt make a difference anyway)
> - Else assume a single screen
> ----------

Hi list,

the attached patches should implement this. The first one doesn't actually
change anything, but splits the code up into functions. The second patch then
actually implements my idea. With it, we fall back to Xinerama if Xrandr only
finds one screen.

I only tested this on my dual-head laptop with working Xrandr (intel driver),
since I don't have anything as broken as nvidia. Testing welcome.

CC'ing JD since I want his ACK on this. I won't push this if he doesn't approve
it. Of course, everyone else is welcome to post comments as well.

Cheers,
Uli

- -- 
- - Buck, when, exactly, did you lose your mind?
- - Three months ago. I woke up one morning married to a pineapple.
  An ugly pineapple... But I loved her!
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)

iQEcBAEBCAAGBQJMRu10AAoJECLkKOvLj8sGfXkH/jhphhrCH+QVtugMdVuTKg0z
GBPWmfNAzSFL/OL5+a6Z1Ue+DPhruV+eCpXTH0MX/9uZCjnrhwJgFaBuKWS3LkCq
9Lqwbew29GbVjEzf3D3Nw9MDC2q/0V91uQt22xGdgqr+l0LJaUE8zEj5VTRQ4enp
ULBbu/aPcSb9ZOqUjKFX9e+JFDveZzUHYD/Bb8+T5+pGIHA/diYVk6M+CGfOBGWp
Cw3Bq1n1ywYZ/k/CvMRnTCvMGYl6kYKTuqWSZdWBSRJJW/9akuAQszgSzbTmcboO
5zb1R3JUUD8TpOT6Cu+khEYlyY00bjgIpePNURotseKy2uB9WhdGG4JblYK3+7M=
=wfG2
-----END PGP SIGNATURE-----
>From 7bf1370502de308a4b807238c6c30631e510423d Mon Sep 17 00:00:00 2001
From: Uli Schlachter <[email protected]>
Date: Wed, 21 Jul 2010 14:42:45 +0200
Subject: [PATCH 1/2] Split up screen_scan()

This splits up screen_scan() into screen_scan_randr(), screen_scan_xinerama()
and screen_scan_x11(). These function try to set up screens via RANDR, Xinerama
and the classic core protcol setup.

No code in these functions was actually changed, only some indentation was
changed (and a "return true/false" added to the first two functions).

Signed-off-by: Uli Schlachter <[email protected]>
---
 screen.c |  148 +++++++++++++++++++++++++++++++++++---------------------------
 1 files changed, 84 insertions(+), 64 deletions(-)

diff --git a/screen.c b/screen.c
index ab8a18c..fcc3898 100644
--- a/screen.c
+++ b/screen.c
@@ -72,10 +72,8 @@ screen_default_visual(xcb_screen_t *s)
     return NULL;
 }
 
-/** Get screens informations and fill global configuration.
- */
-void
-screen_scan(void)
+static bool
+screen_scan_randr(void)
 {
     /* Check for extension before checking for XRandR */
     if(xcb_get_extension_data(globalconf.connection, &xcb_randr_id)->present)
@@ -146,81 +144,103 @@ screen_scan(void)
                 globalconf.xinerama_is_active = true;
 
             globalconf.screens.tab[0].visual = screen_default_visual(xutil_screen_get(globalconf.connection, globalconf.default_screen));
+
+            return true;
         }
     }
-    else
-    {
-        /* Check for extension before checking for Xinerama */
-        if(xcb_get_extension_data(globalconf.connection, &xcb_xinerama_id)->present)
-        {
-            xcb_xinerama_is_active_reply_t *xia;
-            xia = xcb_xinerama_is_active_reply(globalconf.connection, xcb_xinerama_is_active(globalconf.connection), NULL);
-            globalconf.xinerama_is_active = xia->state;
-            p_delete(&xia);
-        }
 
-        if(globalconf.xinerama_is_active)
-        {
-            xcb_xinerama_query_screens_reply_t *xsq;
-            xcb_xinerama_screen_info_t *xsi;
-            int xinerama_screen_number;
+    return false;
+}
 
-            xsq = xcb_xinerama_query_screens_reply(globalconf.connection,
-                                                   xcb_xinerama_query_screens_unchecked(globalconf.connection),
-                                                   NULL);
+static bool
+screen_scan_xinerama(void)
+{
+    /* Check for extension before checking for Xinerama */
+    if(xcb_get_extension_data(globalconf.connection, &xcb_xinerama_id)->present)
+    {
+        xcb_xinerama_is_active_reply_t *xia;
+        xia = xcb_xinerama_is_active_reply(globalconf.connection, xcb_xinerama_is_active(globalconf.connection), NULL);
+        globalconf.xinerama_is_active = xia->state;
+        p_delete(&xia);
+    }
 
-            xsi = xcb_xinerama_query_screens_screen_info(xsq);
-            xinerama_screen_number = xcb_xinerama_query_screens_screen_info_length(xsq);
+    if(globalconf.xinerama_is_active)
+    {
+        xcb_xinerama_query_screens_reply_t *xsq;
+        xcb_xinerama_screen_info_t *xsi;
+        int xinerama_screen_number;
 
-            /* now check if screens overlaps (same x,y): if so, we take only the biggest one */
-            for(int screen = 0; screen < xinerama_screen_number; screen++)
-            {
-                bool drop = false;
-                foreach(screen_to_test, globalconf.screens)
-                    if(xsi[screen].x_org == screen_to_test->geometry.x
-                       && xsi[screen].y_org == screen_to_test->geometry.y)
-                        {
-                            /* we already have a screen for this area, just check if
-                             * it's not bigger and drop it */
-                            drop = true;
-                            int i = screen_array_indexof(&globalconf.screens, screen_to_test);
-                            screen_to_test->geometry.width =
-                                MAX(xsi[screen].width, xsi[i].width);
-                            screen_to_test->geometry.height =
-                                MAX(xsi[screen].height, xsi[i].height);
-                        }
-                if(!drop)
-                {
-                    screen_t s;
-                    p_clear(&s, 1);
-                    s.geometry = screen_xsitoarea(xsi[screen]);
-                    screen_array_append(&globalconf.screens, s);
-                }
-            }
+        xsq = xcb_xinerama_query_screens_reply(globalconf.connection,
+                                               xcb_xinerama_query_screens_unchecked(globalconf.connection),
+                                               NULL);
 
-            p_delete(&xsq);
+        xsi = xcb_xinerama_query_screens_screen_info(xsq);
+        xinerama_screen_number = xcb_xinerama_query_screens_screen_info_length(xsq);
 
-            xcb_screen_t *s = xutil_screen_get(globalconf.connection, globalconf.default_screen);
-            globalconf.screens.tab[0].visual = screen_default_visual(s);
-        }
-        else
-            /* One screen only / Zaphod mode */
-            for(int screen = 0;
-                screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
-                screen++)
+        /* now check if screens overlaps (same x,y): if so, we take only the biggest one */
+        for(int screen = 0; screen < xinerama_screen_number; screen++)
+        {
+            bool drop = false;
+            foreach(screen_to_test, globalconf.screens)
+                if(xsi[screen].x_org == screen_to_test->geometry.x
+                   && xsi[screen].y_org == screen_to_test->geometry.y)
+                    {
+                        /* we already have a screen for this area, just check if
+                         * it's not bigger and drop it */
+                        drop = true;
+                        int i = screen_array_indexof(&globalconf.screens, screen_to_test);
+                        screen_to_test->geometry.width =
+                            MAX(xsi[screen].width, xsi[i].width);
+                        screen_to_test->geometry.height =
+                            MAX(xsi[screen].height, xsi[i].height);
+                    }
+            if(!drop)
             {
-                xcb_screen_t *xcb_screen = xutil_screen_get(globalconf.connection, screen);
                 screen_t s;
                 p_clear(&s, 1);
-                s.geometry.x = 0;
-                s.geometry.y = 0;
-                s.geometry.width = xcb_screen->width_in_pixels;
-                s.geometry.height = xcb_screen->height_in_pixels;
-                s.visual = screen_default_visual(xcb_screen);
+                s.geometry = screen_xsitoarea(xsi[screen]);
                 screen_array_append(&globalconf.screens, s);
             }
+        }
+
+        p_delete(&xsq);
+
+        xcb_screen_t *s = xutil_screen_get(globalconf.connection, globalconf.default_screen);
+        globalconf.screens.tab[0].visual = screen_default_visual(s);
+
+        return true;
     }
 
+    return false;
+}
+
+static void screen_scan_x11(void)
+{
+    /* One screen only / Zaphod mode */
+    for(int screen = 0;
+        screen < xcb_setup_roots_length(xcb_get_setup(globalconf.connection));
+        screen++)
+    {
+        xcb_screen_t *xcb_screen = xutil_screen_get(globalconf.connection, screen);
+        screen_t s;
+        p_clear(&s, 1);
+        s.geometry.x = 0;
+        s.geometry.y = 0;
+        s.geometry.width = xcb_screen->width_in_pixels;
+        s.geometry.height = xcb_screen->height_in_pixels;
+        s.visual = screen_default_visual(xcb_screen);
+        screen_array_append(&globalconf.screens, s);
+    }
+}
+
+/** Get screens informations and fill global configuration.
+ */
+void
+screen_scan(void)
+{
+    if(!screen_scan_randr() && !screen_scan_xinerama())
+        screen_scan_x11();
+
     globalconf.screen_focus = globalconf.screens.tab;
 }
 
-- 
1.7.1

>From e830df60920496670ab29d5307f3ef5c1dab1d97 Mon Sep 17 00:00:00 2001
From: Uli Schlachter <[email protected]>
Date: Wed, 21 Jul 2010 14:46:49 +0200
Subject: [PATCH 2/2] Screen: Only use Xrandr if it provides data

This commit makes awesome ignore the screen geometry provided by Xrandr if it
only defines a single screen. This should work around nvidia's binary driver
which only provides useful data via Xinerama.

Signed-off-by: Uli Schlachter <[email protected]>
---
 screen.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/screen.c b/screen.c
index fcc3898..1e4fc22 100644
--- a/screen.c
+++ b/screen.c
@@ -91,6 +91,14 @@ screen_scan_randr(void)
             xcb_randr_get_screen_resources_cookie_t screen_res_c = xcb_randr_get_screen_resources(globalconf.connection, screen->root);
             xcb_randr_get_screen_resources_reply_t *screen_res_r = xcb_randr_get_screen_resources_reply(globalconf.connection, screen_res_c, NULL);
 
+            /* Only use the data from XRandR if there is more than one screen
+             * defined. This should work around the broken nvidia driver.  */
+            if (screen_res_r->num_crtcs <= 1)
+            {
+                p_delete(&screen_res_r);
+                return false;
+            }
+
             /* We go through CRTC, and build a screen for each one. */
             xcb_randr_crtc_t *randr_crtcs = xcb_randr_get_screen_resources_crtcs(screen_res_r);
 
-- 
1.7.1

Attachment: 0001-Split-up-screen_scan.patch.sig
Description: Binary data

Attachment: 0002-Screen-Only-use-Xrandr-if-it-provides-data.patch.sig
Description: Binary data

Reply via email to