]> git.lizzy.rs Git - bspwm.git/blobdiff - monitor.c
Use default sxhkd config path in DM session
[bspwm.git] / monitor.c
index f41bdfed756509f224f22185c0954869f68086e9..ea8e8c156811fcdbf7c39ae0c9f99333ea86e585 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -71,22 +71,52 @@ monitor_t *get_monitor_by_id(xcb_randr_output_t id)
     return NULL;
 }
 
-void fit_monitor(monitor_t *m, client_t *c)
+void embrace_client(monitor_t *m, client_t *c)
 {
-    xcb_rectangle_t a = m->rectangle;
-    xcb_rectangle_t *b = &c->floating_rectangle;
-    if (b->x <= a.x || (b->x + b->width) >= (a.x + a.width)) {
-        if (b->width >= a.width)
-            b->x = 0;
-        else
-            b->x = a.x + (a.width - b->width) / 2;
-    }
-    if (b->y <= a.y || (b->y + b->height) >= (a.y + a.height)) {
-        if (b->height >= a.height)
-            b->y = 0;
-        else
-            b->y = a.y + (a.height - b->height) / 2;
-    }
+    if ((c->floating_rectangle.x + c->floating_rectangle.width) <= m->rectangle.x)
+        c->floating_rectangle.x = m->rectangle.x;
+    else if (c->floating_rectangle.x >= (m->rectangle.x + m->rectangle.width))
+        c->floating_rectangle.x = (m->rectangle.x + m->rectangle.width) - c->floating_rectangle.width;
+    if ((c->floating_rectangle.y + c->floating_rectangle.height) <= m->rectangle.y)
+        c->floating_rectangle.y = m->rectangle.y;
+    else if (c->floating_rectangle.y >= (m->rectangle.y + m->rectangle.height))
+        c->floating_rectangle.y = (m->rectangle.y + m->rectangle.height) - c->floating_rectangle.height;
+}
+
+void translate_client(monitor_t *ms, monitor_t *md, client_t *c)
+{
+    if (frozen_pointer->action != ACTION_NONE || ms == md)
+        return;
+
+    /* Clip the rectangle to fit into the monitor.  Without this, the fitting
+     * algorithm doesn't work as expected. This also conserves the
+     * out-of-bounds regions */
+    int left_adjust = MAX((ms->rectangle.x - c->floating_rectangle.x), 0);
+    int top_adjust = MAX((ms->rectangle.y - c->floating_rectangle.y), 0);
+    int right_adjust = MAX((c->floating_rectangle.x + c->floating_rectangle.width) - (ms->rectangle.x + ms->rectangle.width), 0);
+    int bottom_adjust = MAX((c->floating_rectangle.y + c->floating_rectangle.height) - (ms->rectangle.y + ms->rectangle.height), 0);
+    c->floating_rectangle.x += left_adjust;
+    c->floating_rectangle.y += top_adjust;
+    c->floating_rectangle.width -= (left_adjust + right_adjust);
+    c->floating_rectangle.height -= (top_adjust + bottom_adjust);
+
+    int dx_s = c->floating_rectangle.x - ms->rectangle.x;
+    int dy_s = c->floating_rectangle.y - ms->rectangle.y;
+
+    int nume_x = dx_s * (md->rectangle.width - c->floating_rectangle.width);
+    int nume_y = dy_s * (md->rectangle.height - c->floating_rectangle.height);
+
+    int deno_x = ms->rectangle.width - c->floating_rectangle.width;
+    int deno_y = ms->rectangle.height - c->floating_rectangle.height;
+
+    int dx_d = (deno_x == 0 ? 0 : nume_x / deno_x);
+    int dy_d = (deno_y == 0 ? 0 : nume_y / deno_y);
+
+    /* Translate and undo clipping */
+    c->floating_rectangle.width += left_adjust + right_adjust;
+    c->floating_rectangle.height += top_adjust + bottom_adjust;
+    c->floating_rectangle.x = md->rectangle.x + dx_d - left_adjust;
+    c->floating_rectangle.y = md->rectangle.y + dy_d - top_adjust;
 }
 
 void update_root(monitor_t *m)
@@ -227,6 +257,41 @@ monitor_t *closest_monitor(monitor_t *m, cycle_dir_t dir, desktop_select_t sel)
     return NULL;
 }
 
+bool is_inside_monitor(monitor_t *m, xcb_point_t pt)
+{
+    xcb_rectangle_t r = m->rectangle;
+    return (r.x <= pt.x && pt.x < (r.x + r.width)
+            && r.y <= pt.y && pt.y < (r.y + r.height));
+}
+
+monitor_t *monitor_from_point(xcb_point_t pt)
+{
+    for (monitor_t *m = mon_head; m != NULL; m = m->next)
+        if (is_inside_monitor(m, pt))
+            return m;
+    return NULL;
+}
+
+monitor_t *monitor_from_client(client_t *c)
+{
+    xcb_point_t pt = {c->floating_rectangle.x, c->floating_rectangle.y};
+    monitor_t *nearest = monitor_from_point(pt);
+    if (nearest == NULL) {
+        int x = (c->floating_rectangle.x + c->floating_rectangle.width) / 2;
+        int y = (c->floating_rectangle.y + c->floating_rectangle.height) / 2;
+        int dmin = INT_MAX;
+        for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+            xcb_rectangle_t r = m->rectangle;
+            int d = abs((r.x + r.width / 2) - x) + abs((r.y + r.height / 2) - y);
+            if (d < dmin) {
+                dmin = d;
+                nearest = m;
+            }
+        }
+    }
+    return nearest;
+}
+
 monitor_t *nearest_monitor(monitor_t *m, direction_t dir, desktop_select_t sel)
 {
     int dmin = INT_MAX;
@@ -286,7 +351,7 @@ bool import_monitors(void)
                         update_root(mm);
                         for (desktop_t *d = mm->desk_head; d != NULL; d = d->next)
                             for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
-                                fit_monitor(mm, n->client);
+                                translate_client(mm, mm, n->client);
                         arrange(mm, mm->desk);
                         mm->wired = true;
                         PRINTF("update monitor %s (0x%X)\n", mm->name, mm->id);
@@ -300,7 +365,7 @@ bool import_monitors(void)
                     }
                 }
                 free(cir);
-            } else if (info->connection != XCB_RANDR_CONNECTION_DISCONNECTED) {
+            } else if (!remove_disabled_monitor && info->connection != XCB_RANDR_CONNECTION_DISCONNECTED) {
                 m = get_monitor_by_id(outputs[i]);
                 if (m != NULL)
                     m->wired = true;