Closes #919.
Fixes #730.
return false;
}
-bool set_layout(monitor_t *m, desktop_t *d, layout_t l)
+bool set_layout(monitor_t *m, desktop_t *d, layout_t l, bool user)
{
- layout_t actual_layout = IS_SINGLE_MONOCLE(d) ? LAYOUT_MONOCLE : l;
- bool actual_layout_changed = (d->layout != actual_layout);
-
- if (d->layout == l) {
+ if ((user && d->user_layout == l) || (!user && d->layout == l)) {
return false;
}
- d->layout = l;
+ layout_t old_layout = d->layout;
- handle_presel_feedbacks(m, d);
+ if (user) {
+ d->user_layout = l;
+ } else {
+ d->layout = l;
+ }
- if (!actual_layout_changed) {
- return true;
+ if (user && (!single_monocle || tiled_count(d->root, true) > 1)) {
+ d->layout = l;
}
- arrange(m, d);
+ if (d->layout != old_layout) {
+ handle_presel_feedbacks(m, d);
- put_status(SBSC_MASK_DESKTOP_LAYOUT, "desktop_layout 0x%08X 0x%08X %s\n", m->id, d->id, LAYOUT_STR(actual_layout));
+ if (user) {
+ arrange(m, d);
+ }
- if (d == m->desk) {
- put_status(SBSC_MASK_REPORT);
- }
+ put_status(SBSC_MASK_DESKTOP_LAYOUT, "desktop_layout 0x%08X 0x%08X %s\n", m->id, d->id, LAYOUT_STR(d->layout));
- return true;
+ if (d == m->desk) {
+ put_status(SBSC_MASK_REPORT);
+ }
+
+ return true;
+ } else {
+ return false;
+ }
}
void handle_presel_feedbacks(monitor_t *m, desktop_t *d)
}
d->prev = d->next = NULL;
d->root = d->focus = NULL;
- d->layout = LAYOUT_TILED;
+ d->layout = d->user_layout = LAYOUT_TILED;
d->padding = (padding_t) PADDING;
d->window_gap = window_gap;
d->border_width = border_width;
bool activate_desktop(monitor_t *m, desktop_t *d);
bool find_closest_desktop(coordinates_t *ref, coordinates_t *dst, cycle_dir_t dir, desktop_select_t *sel);
bool find_any_desktop(coordinates_t *ref, coordinates_t *dst, desktop_select_t *sel);
-bool set_layout(monitor_t *m, desktop_t *d, layout_t l);
+bool set_layout(monitor_t *m, desktop_t *d, layout_t l, bool user);
void handle_presel_feedbacks(monitor_t *m, desktop_t *d);
bool transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d, bool follow);
desktop_t *make_desktop(const char *name, uint32_t id);
#define IS_FULLSCREEN(c) (c->state == STATE_FULLSCREEN)
#define IS_RECEPTACLE(n) (is_leaf(n) && n->client == NULL)
-#define IS_SINGLE_MONOCLE(d) (single_monocle && tiled_count(d->root, true) <= 1)
-#define IS_MONOCLE(d) (d->layout == LAYOUT_MONOCLE || IS_SINGLE_MONOCLE(d))
-#define ACTUAL_LAYOUT(d) (IS_MONOCLE(d) ? LAYOUT_MONOCLE : d->layout)
-
#define BOOL_STR(A) ((A) ? "true" : "false")
#define ON_OFF_STR(A) ((A) ? "on" : "off")
#define LAYOUT_STR(A) ((A) == LAYOUT_TILED ? "tiled" : "monocle")
layout_t lyt;
cycle_dir_t cyc;
if (parse_cycle_direction(*args, &cyc)) {
- ret = set_layout(trg.monitor, trg.desktop, (trg.desktop->layout + 1) % 2);
+ ret = set_layout(trg.monitor, trg.desktop, (trg.desktop->layout + 1) % 2, true);
} else if (parse_layout(*args, &lyt)) {
- ret = set_layout(trg.monitor, trg.desktop, lyt);
+ ret = set_layout(trg.monitor, trg.desktop, lyt, true);
} else {
fail(rsp, "desktop %s: Invalid argument: '%s'.\n", *(args - 1), *args);
break;
fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value);
return;
}
+ } else if (streq("single_monocle", name)) {
+ bool b;
+ if (parse_bool(value, &b)) {
+ if (b == single_monocle) {
+ fail(rsp, "");
+ return;
+ }
+ single_monocle = b;
+ for (monitor_t *m = mon_head; m != NULL; m = m->next) {
+ for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
+ layout_t l = (single_monocle && tiled_count(d->root, true) <= 1) ? LAYOUT_MONOCLE : d->user_layout;
+ set_layout(m, d, l, false);
+ }
+ }
+ } else {
+ fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value);
+ return;
+ }
} else if (streq("focus_follows_pointer", name)) {
bool b;
if (parse_bool(value, &b)) {
SET_BOOL(presel_feedback)
SET_BOOL(borderless_monocle)
SET_BOOL(gapless_monocle)
- SET_BOOL(single_monocle)
- put_status(SBSC_MASK_REPORT);
SET_BOOL(swallow_first_click)
SET_BOOL(pointer_follows_focus)
SET_BOOL(pointer_follows_monitor)
fprintf(rsp, "\"name\":\"%s\",", d->name);
fprintf(rsp, "\"id\":%u,", d->id);
fprintf(rsp, "\"layout\":\"%s\",", LAYOUT_STR(d->layout));
+ fprintf(rsp, "\"userLayout\":\"%s\",", LAYOUT_STR(d->user_layout));
fprintf(rsp, "\"windowGap\":%i,", d->window_gap);
fprintf(rsp, "\"borderWidth\":%u,", d->border_width);
fprintf(rsp, "\"focusedNodeId\":%u,", d->focus != NULL ? d->focus->id : 0);
snprintf(d->name, (*t)->end - (*t)->start + 1, "%s", json + (*t)->start);
RESTORE_UINT(id, &d->id)
RESTORE_ANY(layout, &d->layout, parse_layout)
+ RESTORE_ANY(userLayout, &d->user_layout, parse_layout)
RESTORE_INT(windowGap, &d->window_gap)
RESTORE_UINT(borderWidth, &d->border_width)
} else if (keyeq("focusedNodeId", *t, json)) {
fprintf(stream, ":%c%s", c, d->name);
}
if (m->desk != NULL) {
- fprintf(stream, ":L%c", LAYOUT_CHR(ACTUAL_LAYOUT(m->desk)));
+ fprintf(stream, ":L%c", LAYOUT_CHR(m->desk->layout));
if (m->desk->focus != NULL) {
node_t *n = m->desk->focus;
if (n->client != NULL) {
return;
}
- layout_t l = ACTUAL_LAYOUT(d);
-
xcb_rectangle_t rect = m->rectangle;
rect.x += m->padding.left + d->padding.left;
rect.width -= m->padding.left + d->padding.left + d->padding.right + m->padding.right;
rect.height -= m->padding.top + d->padding.top + d->padding.bottom + m->padding.bottom;
- if (l == LAYOUT_MONOCLE) {
+ if (d->layout == LAYOUT_MONOCLE) {
rect.x += monocle_padding.left;
rect.y += monocle_padding.top;
rect.width -= monocle_padding.left + monocle_padding.right;
rect.height -= monocle_padding.top + monocle_padding.bottom;
}
- if (!gapless_monocle || l != LAYOUT_MONOCLE) {
+ if (!gapless_monocle || d->layout != LAYOUT_MONOCLE) {
rect.x += d->window_gap;
rect.y += d->window_gap;
rect.width -= d->window_gap;
rect.height -= d->window_gap;
}
- apply_layout(m, d, d->root, l, rect, rect);
+ apply_layout(m, d, d->root, rect, rect);
}
-void apply_layout(monitor_t *m, desktop_t *d, node_t *n, layout_t l, xcb_rectangle_t rect, xcb_rectangle_t root_rect)
+void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, xcb_rectangle_t root_rect)
{
if (n == NULL) {
return;
}
unsigned int bw;
- if ((borderless_monocle && l == LAYOUT_MONOCLE && IS_TILED(n->client))
+ if ((borderless_monocle && d->layout == LAYOUT_MONOCLE && IS_TILED(n->client))
|| n->client->state == STATE_FULLSCREEN) {
bw = 0;
} else {
client_state_t s = n->client->state;
/* tiled and pseudo-tiled clients */
if (s == STATE_TILED || s == STATE_PSEUDO_TILED) {
- int wg = (gapless_monocle && l == LAYOUT_MONOCLE ? 0 : d->window_gap);
+ int wg = (gapless_monocle && d->layout == LAYOUT_MONOCLE ? 0 : d->window_gap);
r = rect;
int bleed = wg + 2 * bw;
r.width = (bleed < r.width ? r.width - bleed : 1);
xcb_rectangle_t first_rect;
xcb_rectangle_t second_rect;
- if (l == LAYOUT_MONOCLE || n->first_child->vacant || n->second_child->vacant) {
+ if (d->layout == LAYOUT_MONOCLE || n->first_child->vacant || n->second_child->vacant) {
first_rect = second_rect = rect;
} else {
unsigned int fence;
}
}
- apply_layout(m, d, n->first_child, l, first_rect, root_rect);
- apply_layout(m, d, n->second_child, l, second_rect, root_rect);
+ apply_layout(m, d, n->first_child, first_rect, root_rect);
+ apply_layout(m, d, n->second_child, second_rect, root_rect);
}
}
node_t *r = make_node(XCB_NONE);
insert_node(m, d, r, n);
- put_status(SBSC_MASK_REPORT);
+ if (single_monocle && d->layout == LAYOUT_MONOCLE && tiled_count(d->root, true) > 1) {
+ set_layout(m, d, d->user_layout, false);
+ }
}
bool activate_node(monitor_t *m, desktop_t *d, node_t *n)
}
free_node(n);
+ if (single_monocle && d->layout != LAYOUT_MONOCLE && tiled_count(d->root, true) <= 1) {
+ set_layout(m, d, LAYOUT_MONOCLE, false);
+ }
+
ewmh_update_client_list(false);
ewmh_update_client_list(true);
show_node(d1, n2);
}
+ if (single_monocle) {
+ layout_t l1 = tiled_count(d1->root, true) <= 1 ? LAYOUT_MONOCLE : d1->user_layout;
+ layout_t l2 = tiled_count(d2->root, true) <= 1 ? LAYOUT_MONOCLE : d2->user_layout;
+ set_layout(m1, d1, l1, false);
+ set_layout(m2, d2, l2, false);
+ }
+
if (n1_held_focus) {
if (d1_was_focused) {
if (follow) {
draw_border(ns, is_descendant(ns, ds->focus), (ms == mon));
}
} else {
+ if (single_monocle) {
+ if (ds->layout != LAYOUT_MONOCLE && tiled_count(ds->root, true) <= 1) {
+ set_layout(ms, ds, LAYOUT_MONOCLE, false);
+ }
+ if (dd->layout == LAYOUT_MONOCLE && tiled_count(dd->root, true) > 1) {
+ set_layout(md, dd, dd->user_layout, false);
+ }
+ }
if (held_focus) {
if (follow) {
if (ds_was_focused) {
client_t *c = n->client;
+ bool was_tiled = IS_TILED(c);
+
c->last_state = c->state;
c->state = s;
put_status(SBSC_MASK_REPORT);
}
+ if (single_monocle && was_tiled != IS_TILED(c)) {
+ if (was_tiled && d->layout != LAYOUT_MONOCLE && tiled_count(d->root, true) <= 1) {
+ set_layout(m, d, LAYOUT_MONOCLE, false);
+ } else if (!was_tiled && d->layout == LAYOUT_MONOCLE && tiled_count(d->root, true) > 1) {
+ set_layout(m, d, d->user_layout, false);
+ }
+ }
+
return true;
}
return c->tiled_rectangle;
}
} else {
- int wg = (d == NULL ? 0 : (gapless_monocle && IS_MONOCLE(d) ? 0 : d->window_gap));
+ int wg = (d == NULL ? 0 : (gapless_monocle && d->layout == LAYOUT_MONOCLE ? 0 : d->window_gap));
xcb_rectangle_t rect = n->rectangle;
rect.width -= wg;
rect.height -= wg;
#define MIN_HEIGHT 32
void arrange(monitor_t *m, desktop_t *d);
-void apply_layout(monitor_t *m, desktop_t *d, node_t *n, layout_t l, xcb_rectangle_t rect, xcb_rectangle_t root_rect);
+void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, xcb_rectangle_t root_rect);
presel_t *make_presel(void);
void set_ratio(node_t *n, double rat);
void presel_dir(monitor_t *m, desktop_t *d, node_t *n, direction_t dir);
char name[SMALEN];
uint32_t id;
layout_t layout;
+ layout_t user_layout;
node_t *root;
node_t *focus;
desktop_t *prev;
#include "bspwm.h"
#include "ewmh.h"
#include "monitor.h"
+#include "desktop.h"
#include "query.h"
#include "rule.h"
#include "settings.h"
f = insert_node(m, d, n, f);
clients_count++;
+ if (single_monocle && d->layout == LAYOUT_MONOCLE && tiled_count(d->root, true) > 1) {
+ set_layout(m, d, d->user_layout, false);
+ }
n->vacant = false;
initialize_presel_feedback(n);
}
- int gap = gapless_monocle && IS_MONOCLE(d) ? 0 : d->window_gap;
+ int gap = gapless_monocle && d->layout == LAYOUT_MONOCLE ? 0 : d->window_gap;
presel_t *p = n->presel;
xcb_rectangle_t rect = n->rectangle;
rect.x = rect.y = 0;