]> git.sur5r.net Git - i3/i3/commitdiff
Bugfix: Fix clone mode with new RandR code (Thanks Merovius)
authorMichael Stapelberg <michael@stapelberg.de>
Fri, 5 Mar 2010 13:32:48 +0000 (14:32 +0100)
committerMichael Stapelberg <michael@stapelberg.de>
Fri, 5 Mar 2010 13:32:48 +0000 (14:32 +0100)
include/data.h
src/randr.c
src/workspace.c

index 84ea1cd2b0efb564ffcf8216659115ed52cca5ad..2cc8362f267c6969dcce2ff979f2c4bff1e1d02b 100644 (file)
@@ -513,6 +513,11 @@ struct xoutput {
          * mode) */
         bool active;
 
+        /** Internal flags, necessary for querying RandR screens (happens in
+         * two stages) */
+        bool changed;
+        bool to_be_disabled;
+
         /** Current workspace selected on this virtual screen */
         Workspace *current_workspace;
 
index eb7dce906087a664fd7d0fd58a56415a3391f44a..ac41e34f801a9f75ff82bc0ef8248126843f025e 100644 (file)
@@ -270,14 +270,14 @@ static void output_change_mode(xcb_connection_t *conn, Output *output) {
 /*
  * Gets called by randr_query_screens() for each output. The function adds new
  * outputs to the list of outputs, checks if the mode of existing outputs has
- * been changed or if an existing output has been disabled.
+ * been changed or if an existing output has been disabled. It will then change
+ * either the "changed" or the "to_be_deleted" flag of the output, if
+ * appropriate.
  *
  */
 static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
                           xcb_randr_get_output_info_reply_t *output,
                           xcb_timestamp_t cts, resources_reply *res) {
-        Workspace *ws;
-
         /* each CRT controller has a position in which we are interested in */
         crtc_info *crtc;
 
@@ -303,15 +303,7 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
                 if (!existing)
                         TAILQ_INSERT_TAIL(&outputs, new, outputs);
                 else if (new->active) {
-                        new->active = false;
-                        new->current_workspace = NULL;
-                        DLOG("Output %s disabled (no CRTC)\n", new->name);
-                        TAILQ_FOREACH(ws, workspaces, workspaces) {
-                                if (ws->output != new)
-                                        continue;
-
-                                workspace_assign_to(ws, get_first_output());
-                        }
+                        new->to_be_disabled = true;
 
                 }
                 free(output);
@@ -348,7 +340,7 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
                 return;
         }
 
-        output_change_mode(conn, new);
+        new->changed = true;
 }
 
 /*
@@ -356,6 +348,7 @@ static void handle_output(xcb_connection_t *conn, xcb_randr_output_t id,
  *
  */
 void randr_query_screens(xcb_connection_t *conn) {
+        Workspace *ws;
         xcb_randr_get_screen_resources_current_cookie_t rcookie;
         resources_reply *res;
         /* timestamp of the configuration so that we get consistent replies to all
@@ -380,8 +373,9 @@ void randr_query_screens(xcb_connection_t *conn) {
                 ocookie[i] = xcb_randr_get_output_info(conn, randr_outputs[i], cts);
 
         /* Loop through all outputs available for this X11 screen */
-        xcb_randr_get_output_info_reply_t *output;
         for (int i = 0; i < len; i++) {
+                xcb_randr_get_output_info_reply_t *output;
+
                 if ((output = xcb_randr_get_output_info_reply(conn, ocookie[i], NULL)) == NULL)
                         continue;
 
@@ -390,15 +384,17 @@ void randr_query_screens(xcb_connection_t *conn) {
 
         free(res);
         Output *screen, *oscreen;
-        /* Check for clones and reduce the mode  to the lowest common mode */
+        /* Check for clones and reduce the mode to the lowest common mode */
         TAILQ_FOREACH(screen, &outputs, outputs) {
-                if (!screen->active)
+                if (!screen->active || screen->to_be_disabled)
                         continue;
                 DLOG("screen %p, position (%d, %d), checking for clones\n",
                         screen, screen->rect.x, screen->rect.y);
 
-                TAILQ_FOREACH(oscreen, &outputs, outputs) {
-                        if (oscreen == screen || !oscreen->active)
+                for (oscreen = screen;
+                     oscreen != TAILQ_END(&outputs);
+                     oscreen = TAILQ_NEXT(oscreen, outputs)) {
+                        if (oscreen == screen || !oscreen->active || oscreen->to_be_disabled)
                                 continue;
 
                         if (oscreen->rect.x != screen->rect.x ||
@@ -412,12 +408,13 @@ void randr_query_screens(xcb_connection_t *conn) {
 
                         if (update_if_necessary(&(screen->rect.width), width) |
                             update_if_necessary(&(screen->rect.height), height))
-                                output_change_mode(conn, screen);
+                                screen->changed = true;
 
-                        if (update_if_necessary(&(oscreen->rect.width), width) |
-                            update_if_necessary(&(oscreen->rect.height), height))
-                                output_change_mode(conn, oscreen);
+                        update_if_necessary(&(oscreen->rect.width), width);
+                        update_if_necessary(&(oscreen->rect.height), height);
 
+                        DLOG("disabling screen %p (%s)\n", oscreen, oscreen->name);
+                        oscreen->to_be_disabled = true;
 
                         DLOG("new screen mode %d x %d, oscreen mode %d x %d\n",
                                         screen->rect.width, screen->rect.height,
@@ -425,13 +422,49 @@ void randr_query_screens(xcb_connection_t *conn) {
                 }
         }
 
+        Output *output, *first;
+        TAILQ_FOREACH(output, &outputs, outputs) {
+                if (output->to_be_disabled) {
+                        output->active = false;
+                        DLOG("Output %s disabled, re-assigning workspaces/docks\n", output->name);
+
+                        if ((first = get_first_output()) == NULL)
+                                die("No usable outputs available\n");
+
+                        bool needs_init = (first->current_workspace == NULL);
+
+                        TAILQ_FOREACH(ws, workspaces, workspaces) {
+                                if (ws->output != output)
+                                        continue;
+
+                                workspace_assign_to(ws, first);
+                                if (!needs_init)
+                                        continue;
+                                initialize_output(conn, first, ws);
+                                needs_init = false;
+                        }
+
+                        Client *dock;
+                        while (!SLIST_EMPTY(&(output->dock_clients))) {
+                                dock = SLIST_FIRST(&(output->dock_clients));
+                                SLIST_INSERT_HEAD(&(first->dock_clients), dock, dock_clients);
+                                SLIST_REMOVE_HEAD(&(output->dock_clients), dock_clients);
+                        }
+                        output->current_workspace = NULL;
+                        output->to_be_disabled = false;
+                } else if (output->changed) {
+                        output_change_mode(conn, output);
+                        output->changed = false;
+                }
+        }
+
         ewmh_update_workarea();
 
         /* Just go through each active output and associate one workspace */
         TAILQ_FOREACH(screen, &outputs, outputs) {
                 if (!screen->active || screen->current_workspace != NULL)
                         continue;
-                Workspace *ws = get_first_workspace_for_screen(screen);
+                ws = get_first_workspace_for_screen(screen);
                 initialize_output(conn, screen, ws);
         }
 
index 70b034ab068725e8ec35093792d6689513f0843e..ea1134b667552acb45740d0b78f2ad45f7a63817 100644 (file)
@@ -207,6 +207,7 @@ void workspace_show(xcb_connection_t *conn, int workspace) {
 void workspace_assign_to(Workspace *ws, Output *output) {
         Client *client;
         bool empty = true;
+        bool visible = workspace_is_visible(ws);
 
         ws->output = output;
 
@@ -228,14 +229,14 @@ void workspace_assign_to(Workspace *ws, Output *output) {
         render_workspace(global_conn, output, ws);
 
         /* â€¦unless we want to see them at the moment, we should hide that workspace */
-        if (workspace_is_visible(ws))
+        if (visible)
                 return;
 
         workspace_unmap_clients(global_conn, ws);
 
         if (c_ws == ws) {
-                DLOG("Need to adjust c_ws...\n");
-                c_ws = output->current_workspace;
+                DLOG("Need to adjust output->current_workspace...\n");
+                output->current_workspace = c_ws;
         }
 }