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)
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;
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);
}
}
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;