]> git.lizzy.rs Git - bspwm.git/blobdiff - window.c
Move a few functions from tree to desktop/monitor
[bspwm.git] / window.c
index a765b696513b3761e714bb41b031f2d645550ebf..6aa184f7e751a40429e4e8787c257682536183ff 100644 (file)
--- a/window.c
+++ b/window.c
@@ -1,19 +1,26 @@
-#include <stdio.h>
 #include <stdlib.h>
-#include <stdarg.h>
 #include <string.h>
-#include <xcb/xcb.h>
-#include <xcb/xcb_event.h>
-#include <xcb/xcb_icccm.h>
 #include "types.h"
+#include "monitor.h"
 #include "tree.h"
 #include "bspwm.h"
 #include "settings.h"
 #include "ewmh.h"
-#include "rules.h"
 #include "query.h"
+#include "rule.h"
 #include "window.h"
 
+pointer_state_t *make_pointer_state(void)
+{
+    pointer_state_t *p = malloc(sizeof(pointer_state_t));
+    p->monitor = NULL;
+    p->desktop = NULL;
+    p->node = p->vertical_fence = p->horizontal_fence = NULL;
+    p->client = NULL;
+    p->window = XCB_NONE;
+    return p;
+}
+
 void center(xcb_rectangle_t a, xcb_rectangle_t *b)
 {
     if (b->width < a.width)
@@ -28,14 +35,6 @@ bool contains(xcb_rectangle_t a, xcb_rectangle_t b)
             && a.y <= b.y && (a.y + a.height) >= (b.y + b.height));
 }
 
-bool might_cover(desktop_t *d, node_t *n)
-{
-    for (node_t *f = first_extrema(d->root); f != NULL; f = next_leaf(f, d->root))
-        if (f != n && is_floating(f->client) && contains(n->client->floating_rectangle, f->client->floating_rectangle))
-            return true;
-    return false;
-}
-
 bool is_inside(monitor_t *m, xcb_point_t pt)
 {
     xcb_rectangle_t r = m->rectangle;
@@ -102,9 +101,8 @@ void manage_window(monitor_t *m, desktop_t *d, xcb_window_t win)
     if (override_redirect || locate_window(win, &loc))
         return;
 
-    bool floating = false, follow = false, transient = false, fullscreen = false, takes_focus = true, manage = true;
-
-    handle_rules(win, &m, &d, &floating, &follow, &transient, &fullscreen, &takes_focus, &manage);
+    bool floating = false, fullscreen = false, locked = false, follow = false, transient = false, takes_focus = true, manage = true;
+    handle_rules(win, &m, &d, &floating, &fullscreen, &locked, &follow, &transient, &takes_focus, &manage);
 
     if (!manage) {
         disable_floating_atom(win);
@@ -130,27 +128,27 @@ void manage_window(monitor_t *m, desktop_t *d, xcb_window_t win)
     insert_node(m, d, n, d->focus);
 
     disable_floating_atom(c->window);
-
-    if (floating)
-        set_floating(d, n, true);
+    set_floating(d, n, floating);
+    set_locked(m, d, n, locked);
 
     if (d->focus != NULL && d->focus->client->fullscreen)
         set_fullscreen(d, d->focus, false);
 
-    if (fullscreen)
-        set_fullscreen(d, n, true);
-
-    if (is_tiled(c))
-        window_lower(c->window);
+    set_fullscreen(d, n, fullscreen);
 
     c->transient = transient;
 
-    bool give_focus = takes_focus && (d == mon->desk || follow);
-
-    if (give_focus)
+    bool give_focus = (takes_focus && (d == mon->desk || follow));
+    if (give_focus) {
         focus_node(m, d, n);
-    else if (takes_focus)
+    } else if (takes_focus) {
+        pseudo_focus(d, n);
+    } else {
+        node_t *f = d->focus;
         pseudo_focus(d, n);
+        if (f != NULL)
+            pseudo_focus(d, f);
+    }
 
     xcb_rectangle_t *frect = &n->client->floating_rectangle;
     if (frect->x == 0 && frect->y == 0)
@@ -281,28 +279,7 @@ void window_close(node_t *n)
 
     PRINTF("close window %X\n", n->client->window);
 
-    xcb_atom_t WM_DELETE_WINDOW;
-    xcb_window_t win = n->client->window;
-    xcb_client_message_event_t e;
-
-    xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(dpy, xcb_intern_atom(dpy, 0, strlen("WM_DELETE_WINDOW"), "WM_DELETE_WINDOW"), NULL);
-    if (reply) {
-        WM_DELETE_WINDOW = reply->atom;
-        free(reply);
-    } else {
-        warn("close_window %X: could not acquire WM_DELETE_WINDOW atom\n", win);
-        return;
-    }
-
-    e.response_type = XCB_CLIENT_MESSAGE;
-    e.window = win;
-    e.format = 32;
-    e.sequence = 0;
-    e.type = ewmh->WM_PROTOCOLS;
-    e.data.data32[0] = WM_DELETE_WINDOW;
-    e.data.data32[1] = XCB_CURRENT_TIME;
-
-    xcb_send_event(dpy, false, win, XCB_EVENT_MASK_NO_EVENT, (char *) &e);
+    send_client_message(n->client->window, ewmh->WM_PROTOCOLS, WM_DELETE_WINDOW);
 }
 
 void window_kill(desktop_t *d, node_t *n)
@@ -330,13 +307,13 @@ void set_fullscreen(desktop_t *d, node_t *n, bool value)
         c->fullscreen = true;
         xcb_atom_t values[] = {ewmh->_NET_WM_STATE_FULLSCREEN};
         xcb_ewmh_set_wm_state(ewmh, c->window, LENGTH(values), values);
-        window_raise(c->window);
     } else {
         c->fullscreen = false;
         xcb_atom_t values[] = {XCB_NONE};
         xcb_ewmh_set_wm_state(ewmh, c->window, LENGTH(values), values);
-        stack(d, n);
     }
+
+    stack(d, n);
 }
 
 void set_floating(desktop_t *d, node_t *n, bool value)
@@ -350,6 +327,7 @@ void set_floating(desktop_t *d, node_t *n, bool value)
     client_t *c = n->client;
     c->floating = n->vacant = value;
     update_vacant_state(n->parent);
+
     if (value) {
         enable_floating_atom(c->window);
         unrotate_brother(n);
@@ -357,6 +335,7 @@ void set_floating(desktop_t *d, node_t *n, bool value)
         disable_floating_atom(c->window);
         rotate_brother(n);
     }
+
     stack(d, n);
 }
 
@@ -446,7 +425,9 @@ void update_floating_rectangle(client_t *c)
 void query_pointer(xcb_window_t *win, xcb_point_t *pt)
 {
     window_lower(motion_recorder);
+
     xcb_query_pointer_reply_t *qpr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), NULL);
+
     if (qpr != NULL) {
         if (win != NULL)
             *win = qpr->child;
@@ -454,6 +435,7 @@ void query_pointer(xcb_window_t *win, xcb_point_t *pt)
             *pt = (xcb_point_t) {qpr->root_x, qpr->root_y};
         free(qpr);
     }
+
     window_raise(motion_recorder);
 }
 
@@ -497,19 +479,53 @@ void window_raise(xcb_window_t win)
     xcb_configure_window(dpy, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
 }
 
-void stack_tiled(desktop_t *d)
+void window_stack(xcb_window_t w1, xcb_window_t w2, uint32_t mode)
 {
-    for (node_list_t *a = d->history->head; a != NULL; a = a->next)
-        if (a->latest && is_tiled(a->node->client))
-            window_lower(a->node->client->window);
+    if (w2 == XCB_NONE)
+        return;
+    uint16_t mask = XCB_CONFIG_WINDOW_SIBLING | XCB_CONFIG_WINDOW_STACK_MODE;
+    uint32_t values[] = {w2, mode};
+    xcb_configure_window(dpy, w1, mask, values);
+}
+
+void window_above(xcb_window_t w1, xcb_window_t w2)
+{
+    window_stack(w1, w2, XCB_STACK_MODE_ABOVE);
+}
+
+void window_below(xcb_window_t w1, xcb_window_t w2)
+{
+    window_stack(w1, w2, XCB_STACK_MODE_BELOW);
 }
 
 void stack(desktop_t *d, node_t *n)
 {
-    if (is_tiled(n->client))
-        stack_tiled(d);
-    else if (auto_raise && (!adaptative_raise || !might_cover(d, n)))
+    if (is_leaf(d->root))
+        return;
+    if (n->client->fullscreen) {
         window_raise(n->client->window);
+    } else {
+        if (n->client->floating && !auto_raise)
+            return;
+        xcb_window_t latest_tiled = XCB_NONE;
+        xcb_window_t oldest_floating = XCB_NONE;
+        for (node_list_t *a = d->history->head; a != NULL; a = a->next) {
+            if (a->latest && a->node != n) {
+                if (a->node->client->floating == n->client->floating) {
+                    window_above(n->client->window, a->node->client->window);
+                    return;
+                } else if (latest_tiled == XCB_NONE && !a->node->client->floating) {
+                    latest_tiled = a->node->client->window;
+                } else if (a->node->client->floating) {
+                    oldest_floating = a->node->client->window;
+                }
+            }
+        }
+        if (n->client->floating)
+            window_above(n->client->window, latest_tiled);
+        else
+            window_below(n->client->window, oldest_floating);
+    }
 }
 
 void window_lower(xcb_window_t win)
@@ -552,22 +568,6 @@ void toggle_visibility(void)
         update_input_focus();
 }
 
-void desktop_show(desktop_t *d)
-{
-    if (!visible)
-        return;
-    for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
-        window_show(n->client->window);
-}
-
-void desktop_hide(desktop_t *d)
-{
-    if (!visible)
-        return;
-    for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
-        window_hide(n->client->window);
-}
-
 void enable_motion_recorder(void)
 {
     PUTS("enable motion recorder");
@@ -604,7 +604,7 @@ void set_input_focus(node_t *n)
         clear_input_focus();
     } else {
         if (n->client->icccm_focus)
-            icccm_focus(n->client->window);
+            send_client_message(n->client->window, ewmh->WM_PROTOCOLS, WM_TAKE_FOCUS);
         xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, n->client->window, XCB_CURRENT_TIME);
     }
 }
@@ -646,17 +646,16 @@ bool has_proto(xcb_atom_t atom, xcb_icccm_get_wm_protocols_reply_t *protocols)
     return false;
 }
 
-void icccm_focus(xcb_window_t win)
+void send_client_message(xcb_window_t win, xcb_atom_t property, xcb_atom_t value)
 {
-    PRINTF("focus via ICCCM %X\n", win);
     xcb_client_message_event_t e;
 
     e.response_type = XCB_CLIENT_MESSAGE;
     e.window = win;
     e.format = 32;
     e.sequence = 0;
-    e.type = ewmh->WM_PROTOCOLS;
-    e.data.data32[0] = WM_TAKE_FOCUS;
+    e.type = property;
+    e.data.data32[0] = value;
     e.data.data32[1] = XCB_CURRENT_TIME;
 
     xcb_send_event(dpy, false, win, XCB_EVENT_MASK_NO_EVENT, (char *) &e);