Implement the pseudo-tiled window state

This commit is contained in:
Bastien Dejean 2013-12-27 14:23:25 +01:00
parent e0b6cd3cd4
commit 48e0043f84
14 changed files with 73 additions and 38 deletions

View file

@ -444,6 +444,11 @@ floating
Is above any tiled window and can be moved/resized freely\&. Although it doesn\(cqt occupy any tiling space, it is still part of the window tree\&.
.RE
.PP
pseudo_tiled
.RS 4
Has a libre size while being centered in its tiling space\&.
.RE
.PP
fullscreen
.RS 4
Fills its monitor rectangle, is above all the other windows and has no borders\&.
@ -534,7 +539,7 @@ Set and change the splitting ratio of (or pull, or push) the edge located in the
Rotate the tree holding the edge located in the given direction in relation to the selected window\&.
.RE
.PP
\fB\-t\fR, \fB\-\-toggle\fR floating|fullscreen|locked|sticky|private[=on|off]
\fB\-t\fR, \fB\-\-toggle\fR floating|fullscreen|pseudo_tiled|locked|sticky|private[=on|off]
.RS 4
Set or toggle the given state for the selected window\&.
.RE
@ -876,7 +881,7 @@ rule \fIOPTIONS\fR
\fBOptions\fR
.RS 4
.PP
\fB\-a\fR, \fB\-\-add\fR <class_name>|<instance_name>|* [\fB\-o\fR|\fB\-\-one\-shot\fR] [desktop=DESKTOP_SEL|monitor=MONITOR_SEL] [(floating|fullscreen|locked|sticky|private|center|lower|follow|manage|focus)=(true|false)]
\fB\-a\fR, \fB\-\-add\fR <class_name>|<instance_name>|* [\fB\-o\fR|\fB\-\-one\-shot\fR] [desktop=DESKTOP_SEL|monitor=MONITOR_SEL] [(floating|fullscreen|pseudo_tiled|locked|sticky|private|center|lower|follow|manage|focus)=(true|false)]
.RS 4
Create a new rule\&.
.RE

View file

@ -293,6 +293,9 @@ Window States
floating::
Is above any tiled window and can be moved/resized freely. Although it doesn't occupy any tiling space, it is still part of the window tree.
pseudo_tiled::
Has a libre size while being centered in its tiling space.
fullscreen::
Fills its monitor rectangle, is above all the other windows and has no borders.
@ -346,7 +349,7 @@ Options
*-R*, *--rotate* 'DIR' '90|270|180'::
Rotate the tree holding the edge located in the given direction in relation to the selected window.
*-t*, *--toggle* floating|fullscreen|locked|sticky|private[=on|off]::
*-t*, *--toggle* floating|fullscreen|pseudo_tiled|locked|sticky|private[=on|off]::
Set or toggle the given state for the selected window.
*-c*, *--close*::
@ -538,7 +541,7 @@ rule 'OPTIONS'
Options
^^^^^^^
*-a*, *--add* <class_name>|<instance_name>|* [*-o*|*--one-shot*] [desktop=DESKTOP_SEL|monitor=MONITOR_SEL] [(floating|fullscreen|locked|sticky|private|center|lower|follow|manage|focus)=(true|false)]::
*-a*, *--add* <class_name>|<instance_name>|* [*-o*|*--one-shot*] [desktop=DESKTOP_SEL|monitor=MONITOR_SEL] [(floating|fullscreen|pseudo_tiled|locked|sticky|private|center|lower|follow|manage|focus)=(true|false)]::
Create a new rule.
*-r*, *--remove* ^<n>|head|tail|<class_name>|<instance_name>|*...::

View file

@ -120,6 +120,9 @@ void configure_request(xcb_generic_event_t *evt)
evt.override_redirect = false;
xcb_send_event(dpy, false, win, XCB_EVENT_MASK_STRUCTURE_NOTIFY, (const char *) &evt);
if (loc.node->client->pseudo_tiled)
arrange(loc.monitor, loc.desktop);
} else {
uint16_t mask = 0;
uint32_t values[7];
@ -170,8 +173,12 @@ void configure_request(xcb_generic_event_t *evt)
xcb_configure_window(dpy, e->window, mask, values);
}
if (is_managed)
translate_client(monitor_from_client(loc.node->client), loc.monitor, loc.node->client);
if (is_managed) {
monitor_t *m = monitor_from_client(loc.node->client);
if (m != NULL && m != loc.monitor)
transfer_node(loc.monitor, loc.desktop, loc.node, m, m->desk, m->desk->focus);
}
}
void destroy_notify(xcb_generic_event_t *evt)

View file

@ -83,3 +83,9 @@ double distance(xcb_point_t a, xcb_point_t b)
{
return hypot(a.x - b.x, a.y - b.y);
}
void center_rectangle(xcb_rectangle_t *src, xcb_rectangle_t dst)
{
src->x = dst.x + (dst.width - src->width) / 2;
src->y = dst.y + (dst.height - src->height) / 2;
}

View file

@ -56,9 +56,9 @@
#endif
void warn(char *fmt, ...);
__attribute__((noreturn))
void err(char *fmt, ...);
bool get_color(char *col, xcb_window_t win, uint32_t *pxl);
double distance(xcb_point_t a, xcb_point_t b);
void center_rectangle(xcb_rectangle_t *src, xcb_rectangle_t dst);
#endif

View file

@ -204,6 +204,9 @@ bool cmd_window(char **args, int num)
if (streq("fullscreen", key)) {
set_fullscreen(trg.node, (a == ALTER_SET ? b : !trg.node->client->fullscreen));
dirty = true;
} else if (streq("pseudo_tiled", key)) {
set_pseudo_tiled(trg.node, (a == ALTER_SET ? b : !trg.node->client->pseudo_tiled));
dirty = true;
} else if (streq("floating", key)) {
set_floating(trg.node, (a == ALTER_SET ? b : !trg.node->client->floating));
dirty = true;

View file

@ -69,12 +69,12 @@ void grab_pointer(pointer_action_t pac)
case ACTION_MOVE:
case ACTION_RESIZE_SIDE:
case ACTION_RESIZE_CORNER:
if (is_tiled(c)) {
frozen_pointer->rectangle = c->tiled_rectangle;
frozen_pointer->is_tiled = true;
} else if (is_floating(c)) {
if (is_floating(c)) {
frozen_pointer->rectangle = c->floating_rectangle;
frozen_pointer->is_tiled = false;
} else if (is_tiled(c)) {
frozen_pointer->rectangle = c->tiled_rectangle;
frozen_pointer->is_tiled = true;
} else {
frozen_pointer->action = ACTION_NONE;
return;
@ -254,7 +254,7 @@ void track_pointer(int root_x, int root_y)
sr = MIN(1, sr);
horizontal_fence->split_ratio = sr;
}
arrange(mon, mon->desk);
arrange(m, d);
} else {
if (pac == ACTION_RESIZE_SIDE) {
switch (frozen_pointer->side) {
@ -283,11 +283,6 @@ void track_pointer(int root_x, int root_y)
h = rect.height;
break;
}
width = MAX(1, w);
height = MAX(1, h);
window_move_resize(win, x, y, width, height);
c->floating_rectangle = (xcb_rectangle_t) {x, y, width, height};
window_draw_border(n, d->focus == n, mon == m);
} else if (pac == ACTION_RESIZE_CORNER) {
switch (frozen_pointer->corner) {
case CORNER_TOP_LEFT:
@ -315,12 +310,11 @@ void track_pointer(int root_x, int root_y)
h = rect.height + delta_y;
break;
}
}
width = MAX(1, w);
height = MAX(1, h);
window_move_resize(win, x, y, width, height);
c->floating_rectangle = (xcb_rectangle_t) {x, y, width, height};
window_draw_border(n, d->focus == n, mon == m);
}
}
break;
case ACTION_FOCUS:

View file

@ -90,7 +90,7 @@ void query_tree(desktop_t *d, node_t *n, char *rsp, unsigned int depth)
if (is_leaf(n)) {
client_t *c = n->client;
snprintf(line, sizeof(line), "%c %s 0x%X %u %ux%u%+i%+i %c %c%c%c%c%c%c%c%c", (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')), c->class_name, c->window, c->border_width, c->floating_rectangle.width, c->floating_rectangle.height, c->floating_rectangle.x, c->floating_rectangle.y, (n->split_dir == DIR_UP ? 'U' : (n->split_dir == DIR_RIGHT ? 'R' : (n->split_dir == DIR_DOWN ? 'D' : 'L'))), (c->floating ? 'f' : '-'), (c->transient ? 't' : '-'), (c->fullscreen ? 'F' : '-'), (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'), (c->sticky ? 's' : '-'), (c->private ? 'i' : '-'), (n->split_mode ? 'p' : '-'));
snprintf(line, sizeof(line), "%c %s 0x%X %u %ux%u%+i%+i %c %c%c%c%c%c%c%c%c%c", (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')), c->class_name, c->window, c->border_width, c->floating_rectangle.width, c->floating_rectangle.height, c->floating_rectangle.x, c->floating_rectangle.y, (n->split_dir == DIR_UP ? 'U' : (n->split_dir == DIR_RIGHT ? 'R' : (n->split_dir == DIR_DOWN ? 'D' : 'L'))), (c->floating ? 'f' : '-'), (c->pseudo_tiled ? 'd' : '-'), (c->transient ? 't' : '-'), (c->fullscreen ? 'F' : '-'), (c->urgent ? 'u' : '-'), (c->locked ? 'l' : '-'), (c->sticky ? 's' : '-'), (c->private ? 'i' : '-'), (n->split_mode ? 'p' : '-'));
} else {
snprintf(line, sizeof(line), "%c %c %lf", (n->split_type == TYPE_HORIZONTAL ? 'H' : 'V'), (n->birth_rotation == 90 ? 'a' : (n->birth_rotation == 270 ? 'c' : 'm')), n->split_ratio);
}

View file

@ -134,9 +134,10 @@ void restore_tree(char *file_path)
} else {
client_t *c = make_client(XCB_NONE);
num_clients++;
char floating, transient, fullscreen, urgent, locked, sticky, private, sd, sm, end = 0;
sscanf(line + level, "%c %s %X %u %hux%hu%hi%hi %c %c%c%c%c%c%c%c%c %c", &br, c->class_name, &c->window, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &sd, &floating, &transient, &fullscreen, &urgent, &locked, &sticky, &private, &sm, &end);
char floating, pseudo_tiled, transient, fullscreen, urgent, locked, sticky, private, sd, sm, end = 0;
sscanf(line + level, "%c %s %X %u %hux%hu%hi%hi %c %c%c%c%c%c%c%c%c%c %c", &br, c->class_name, &c->window, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &sd, &floating, &pseudo_tiled, &transient, &fullscreen, &urgent, &locked, &sticky, &private, &sm, &end);
c->floating = (floating == '-' ? false : true);
c->pseudo_tiled = (pseudo_tiled == '-' ? false : true);
c->transient = (transient == '-' ? false : true);
c->fullscreen = (fullscreen == '-' ? false : true);
c->urgent = (urgent == '-' ? false : true);

1
rule.c
View file

@ -276,6 +276,7 @@ void parse_key_value(char *key, char *value, rule_consequence_t *csq)
#define SETCSQ(name) \
else if (streq(#name, key)) \
csq->name = v;
SETCSQ(pseudo_tiled)
SETCSQ(fullscreen)
SETCSQ(locked)
SETCSQ(sticky)

17
tree.c
View file

@ -70,17 +70,18 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, x
xcb_rectangle_t r;
if (!n->client->fullscreen) {
if (!n->client->floating) {
if (n->client->pseudo_tiled) {
/* pseudo-tiled clients */
r = n->client->floating_rectangle;
center_rectangle(&r, rect);
} else {
/* tiled clients */
if (d->layout == LAYOUT_TILED)
r = rect;
else if (d->layout == LAYOUT_MONOCLE)
r = root_rect;
else
return;
int wg = (gapless_monocle && d->layout == LAYOUT_MONOCLE ? 0 : d->window_gap);
int bleed = wg + 2 * n->client->border_width;
r.width = (bleed < r.width ? r.width - bleed : 1);
r.height = (bleed < r.height ? r.height - bleed : 1);
}
n->client->tiled_rectangle = r;
} else {
/* floating clients */
@ -99,7 +100,7 @@ void apply_layout(monitor_t *m, desktop_t *d, node_t *n, xcb_rectangle_t rect, x
xcb_rectangle_t first_rect;
xcb_rectangle_t second_rect;
if (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;
@ -360,8 +361,8 @@ client_t *make_client(xcb_window_t win)
snprintf(c->class_name, sizeof(c->class_name), "%s", MISSING_VALUE);
c->border_width = BORDER_WIDTH;
c->window = win;
c->floating = c->transient = c->fullscreen = c->locked = c->sticky = c->urgent = false;
c->private = c->icccm_focus = false;
c->pseudo_tiled = c->floating = c->transient = c->fullscreen = false;
c->locked = c->sticky = c->urgent = c->private = c->icccm_focus = false;
xcb_icccm_get_wm_protocols_reply_t protocols;
if (xcb_icccm_get_wm_protocols_reply(dpy, xcb_icccm_get_wm_protocols(dpy, win, ewmh->WM_PROTOCOLS), &protocols, NULL) == 1) {
if (has_proto(WM_TAKE_FOCUS, &protocols))

View file

@ -155,6 +155,7 @@ typedef struct {
xcb_window_t window;
char class_name[SMALEN];
unsigned int border_width;
bool pseudo_tiled;
bool floating;
bool transient; /* transient window are always floating */
bool fullscreen;
@ -260,6 +261,7 @@ typedef struct {
char instance_name[SMALEN];
char desktop_desc[MAXLEN];
char monitor_desc[MAXLEN];
bool pseudo_tiled;
bool floating;
bool transient;
bool fullscreen;

View file

@ -118,6 +118,7 @@ void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
insert_node(m, d, n, d->focus);
disable_floating_atom(c->window);
set_pseudo_tiled(n, csq->pseudo_tiled);
set_floating(n, csq->floating);
set_locked(m, d, n, csq->locked);
set_sticky(m, d, n, csq->sticky);
@ -360,6 +361,16 @@ void set_fullscreen(node_t *n, bool value)
stack(n, STACK_ABOVE);
}
void set_pseudo_tiled(node_t *n, bool value)
{
if (n == NULL || n->client->transient || n->client->pseudo_tiled == value)
return;
PRINTF("pseudo-tiled %X: %s\n", n->client->window, BOOLSTR(value));
n->client->pseudo_tiled = value;
}
void set_floating(node_t *n, bool value)
{
if (n == NULL || n->client->transient || n->client->fullscreen || n->client->floating == value)

View file

@ -43,6 +43,7 @@ void adopt_orphans(void);
void window_close(node_t *n);
void window_kill(monitor_t *m, desktop_t *d, node_t *n);
void set_fullscreen(node_t *n, bool value);
void set_pseudo_tiled(node_t *n, bool value);
void set_floating(node_t *n, bool value);
void set_locked(monitor_t *m, desktop_t *d, node_t *n, bool value);
void set_sticky(monitor_t *m, desktop_t *d, node_t *n, bool value);