]> git.lizzy.rs Git - bspwm.git/blobdiff - desktop.c
Handle clients outside of every monitors
[bspwm.git] / desktop.c
index c6d6b3163d5d70166dbf72b9191752f6213e2a5e..d4bc4b18ccb9b82d6463c4f264ccb2a2f5184e8a 100644 (file)
--- a/desktop.c
+++ b/desktop.c
@@ -1,27 +1,49 @@
+/* * Copyright (c) 2012-2013 Bastien Dejean
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ *  * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
 #include <stdlib.h>
-#include <string.h>
 #include "bspwm.h"
-#include "desktop.h"
+#include "ewmh.h"
+#include "history.h"
 #include "monitor.h"
+#include "query.h"
 #include "tree.h"
-#include "history.h"
 #include "window.h"
-#include "query.h"
-#include "ewmh.h"
+#include "desktop.h"
 
-void select_desktop(monitor_t *m, desktop_t *d)
+void focus_desktop(monitor_t *m, desktop_t *d)
 {
-    select_monitor(m);
+    focus_monitor(m);
 
     if (d == mon->desk)
         return;
 
-    PRINTF("select desktop %s\n", d->name);
+    PRINTF("focus desktop %s\n", d->name);
 
     show_desktop(d);
     hide_desktop(mon->desk);
 
-    mon->last_desk = mon->desk;
     mon->desk = d;
 
     ewmh_update_current_desktop();
@@ -35,7 +57,8 @@ desktop_t *closest_desktop(monitor_t *m, desktop_t *d, cycle_dir_t dir, desktop_
         f = (dir == CYCLE_PREV ? m->desk_tail : m->desk_head);
 
     while (f != d) {
-        if (desktop_matches(f, sel))
+        coordinates_t loc = {m, f, NULL};
+        if (desktop_matches(&loc, &loc, sel))
             return f;
         f = (dir == CYCLE_PREV ? f->prev : f->next);
         if (f == NULL)
@@ -70,11 +93,14 @@ void transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d)
     }
 
     for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
-        fit_monitor(md, n->client);
+        translate_client(ms, md, n->client);
+
     arrange(md, d);
-    if (d != dd && md->desk == d) {
+
+    if (d != dd && md->desk == d)
         show_desktop(d);
-    }
+
+    history_transfer_desktop(md, d);
 
     ewmh_update_wm_desktops();
     ewmh_update_desktop_names();
@@ -86,14 +112,15 @@ desktop_t *make_desktop(const char *name)
 {
     desktop_t *d = malloc(sizeof(desktop_t));
     if (name == NULL)
-        snprintf(d->name, sizeof(d->name), "%s%02d", DEFAULT_DESK_NAME, ++desktop_uid);
+        snprintf(d->name, sizeof(d->name), "%s%d", DEFAULT_DESK_NAME, ++desktop_uid);
     else
-        strncpy(d->name, name, sizeof(d->name));
+        snprintf(d->name, sizeof(d->name), "%s", name);
     d->layout = LAYOUT_TILED;
     d->prev = d->next = NULL;
     d->root = d->focus = NULL;
-    d->history = make_focus_history();
     d->window_gap = WINDOW_GAP;
+    d->border_width = BORDER_WIDTH;
+    d->floating = false;
     return d;
 }
 
@@ -125,13 +152,13 @@ void empty_desktop(desktop_t *d)
 {
     destroy_tree(d->root);
     d->root = d->focus = NULL;
-    empty_history(d->history);
 }
 
 void unlink_desktop(monitor_t *m, desktop_t *d)
 {
     desktop_t *prev = d->prev;
     desktop_t *next = d->next;
+    desktop_t *last_desk = history_get_desktop(m, d);
     if (prev != NULL)
         prev->next = next;
     if (next != NULL)
@@ -140,10 +167,8 @@ void unlink_desktop(monitor_t *m, desktop_t *d)
         m->desk_head = next;
     if (m->desk_tail == d)
         m->desk_tail = prev;
-    if (m->last_desk == d)
-        m->last_desk = NULL;
     if (m->desk == d)
-        m->desk = (m->last_desk == NULL ? (prev == NULL ? next : prev) : m->last_desk);
+        m->desk = (last_desk == NULL ? (prev == NULL ? next : prev) : last_desk);
     d->prev = d->next = NULL;
 }
 
@@ -152,6 +177,7 @@ void remove_desktop(monitor_t *m, desktop_t *d)
     PRINTF("remove desktop %s\n", d->name);
 
     unlink_desktop(m, d);
+    history_remove(d, NULL);
     empty_desktop(d);
     free(d);
     num_desktops--;
@@ -160,19 +186,51 @@ void remove_desktop(monitor_t *m, desktop_t *d)
     put_status();
 }
 
-void swap_desktops(monitor_t *m, desktop_t *d1, desktop_t *d2)
+void merge_desktops(monitor_t *ms, desktop_t *ds, monitor_t *md, desktop_t *dd)
+{
+    if (ds == NULL || dd == NULL || ds == dd)
+        return;
+    node_t *n = first_extrema(ds->root);
+    while (n != NULL) {
+        node_t *next = next_leaf(n, ds->root);
+        transfer_node(ms, ds, n, md, dd, dd->focus);
+        n = next;
+    }
+}
+
+void swap_desktops(monitor_t *m1, desktop_t *d1, monitor_t *m2, desktop_t *d2)
 {
     if (d1 == NULL || d2 == NULL || d1 == d2)
         return;
 
-    if (m->desk_head == d1)
-        m->desk_head = d2;
-    else if (m->desk_head == d2)
-        m->desk_head = d1;
-    if (m->desk_tail == d1)
-        m->desk_tail = d2;
-    else if (m->desk_tail == d2)
-        m->desk_tail = d1;
+    PRINTF("swap desktops %s %s\n", d1->name, d2->name);
+
+    bool d1_focused = (m1->desk == d1);
+    bool d2_focused = (m2->desk == d2);
+
+    if (m1 != m2) {
+        if (m1->desk == d1)
+            m1->desk = d2;
+        if (m1->desk_head == d1)
+            m1->desk_head = d2;
+        if (m1->desk_tail == d1)
+            m1->desk_tail = d2;
+        if (m2->desk == d2)
+            m2->desk = d1;
+        if (m2->desk_head == d2)
+            m2->desk_head = d1;
+        if (m2->desk_tail == d2)
+            m2->desk_tail = d1;
+    } else {
+        if (m1->desk_head == d1)
+            m1->desk_head = d2;
+        else if (m1->desk_head == d2)
+            m1->desk_head = d1;
+        if (m1->desk_tail == d1)
+            m1->desk_tail = d2;
+        else if (m1->desk_tail == d2)
+            m1->desk_tail = d1;
+    }
 
     desktop_t *p1 = d1->prev;
     desktop_t *n1 = d1->next;
@@ -193,6 +251,24 @@ void swap_desktops(monitor_t *m, desktop_t *d1, desktop_t *d2)
     d2->prev = p1 == d2 ? d1 : p1;
     d2->next = n1 == d2 ? d1 : n1;
 
+    if (m1 != m2) {
+        for (node_t *n = first_extrema(d1->root); n != NULL; n = next_leaf(n, d1->root))
+            translate_client(m1, m2, n->client);
+        for (node_t *n = first_extrema(d2->root); n != NULL; n = next_leaf(n, d2->root))
+            translate_client(m2, m1, n->client);
+        history_swap_desktops(m1, d1, m2, d2);
+        arrange(m1, d2);
+        arrange(m2, d1);
+        if (d1_focused && !d2_focused) {
+            hide_desktop(d1);
+            show_desktop(d2);
+        } else if (!d1_focused && d2_focused) {
+            show_desktop(d1);
+            hide_desktop(d2);
+        }
+    }
+
+    update_input_focus();
     ewmh_update_wm_desktops();
     ewmh_update_desktop_names();
     ewmh_update_current_desktop();