Add *focused* modifier to desktops and monitors

This commit is contained in:
Bastien Dejean 2015-11-26 20:07:46 +01:00
parent 512e9044e3
commit d3166dd399
10 changed files with 115 additions and 48 deletions

View file

@ -2,12 +2,12 @@
.\" Title: bspwm
.\" Author: [see the "Author" section]
.\" Generator: DocBook XSL Stylesheets v1.78.1 <http://docbook.sf.net/>
.\" Date: 11/25/2015
.\" Date: 11/26/2015
.\" Manual: Bspwm Manual
.\" Source: Bspwm 0.9
.\" Language: English
.\"
.TH "BSPWM" "1" "11/25/2015" "Bspwm 0\&.9" "Bspwm Manual"
.TH "BSPWM" "1" "11/26/2015" "Bspwm 0\&.9" "Bspwm Manual"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
@ -195,7 +195,7 @@ Select a desktop\&.
.RS 4
.\}
.nf
DESKTOP_SEL := (<desktop_name>|[MONITOR_SEL:](focused|^<n>)CYCLE_DIR|last|older|newer)[\&.[!]occupied][\&.[!]urgent][\&.[!]local]
DESKTOP_SEL := (<desktop_name>|[MONITOR_SEL:](focused|^<n>)CYCLE_DIR|last|older|newer)[\&.[!]occupied][\&.[!]focused][\&.[!]urgent][\&.[!]local]
.fi
.if n \{\
.RE
@ -258,6 +258,11 @@ Selects the desktop newer than the focused desktop in the history\&.
Only consider occupied or free desktops\&.
.RE
.PP
[!]focused
.RS 4
Only consider focused or unfocused desktops\&.
.RE
.PP
[!]urgent
.RS 4
Only consider urgent or non urgent desktops\&.
@ -276,7 +281,7 @@ Select a monitor\&.
.RS 4
.\}
.nf
MONITOR_SEL := (<monitor_name>|^<n>|DIR|CYCLE_DIR|last|primary|focused|older|newer)[\&.[!]occupied]
MONITOR_SEL := (<monitor_name>|^<n>|DIR|CYCLE_DIR|last|primary|focused|older|newer)[\&.[!]occupied][\&.[!]focused]
.fi
.if n \{\
.RE
@ -348,6 +353,11 @@ Selects the monitor newer than the focused monitor in the history\&.
.RS 4
Only consider monitors where the focused desktop is occupied or free\&.
.RE
.PP
[!]focused
.RS 4
Only consider focused or unfocused monitors\&.
.RE
.RE
.SH "WINDOW STATES"
.PP

View file

@ -124,7 +124,7 @@ Desktop
Select a desktop.
----
DESKTOP_SEL := (<desktop_name>|[MONITOR_SEL:](focused|^<n>)CYCLE_DIR|last|older|newer)[.[!]occupied][.[!]urgent][.[!]local]
DESKTOP_SEL := (<desktop_name>|[MONITOR_SEL:](focused|^<n>)CYCLE_DIR|last|older|newer)[.[!]occupied][.[!]focused][.[!]urgent][.[!]local]
----
Primary Selectors
@ -157,6 +157,9 @@ Modifiers
[!]occupied::
Only consider occupied or free desktops.
[!]focused::
Only consider focused or unfocused desktops.
[!]urgent::
Only consider urgent or non urgent desktops.
@ -169,7 +172,7 @@ Monitor
Select a monitor.
----
MONITOR_SEL := (<monitor_name>|^<n>|DIR|CYCLE_DIR|last|primary|focused|older|newer)[.[!]occupied]
MONITOR_SEL := (<monitor_name>|^<n>|DIR|CYCLE_DIR|last|primary|focused|older|newer)[.[!]occupied][.[!]focused]
----
Primary Selectors
@ -208,6 +211,9 @@ Modifiers
[!]occupied::
Only consider monitors where the focused desktop is occupied or free.
[!]focused::
Only consider focused or unfocused monitors.
Window States
-------------

View file

@ -205,22 +205,27 @@ bool history_find_desktop(history_dir_t hdi, coordinates_t *ref, coordinates_t *
return false;
}
bool history_find_monitor(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, desktop_select_t sel)
bool history_find_monitor(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, monitor_select_t sel)
{
if (history_needle == NULL || record_history)
if (history_needle == NULL || record_history) {
history_needle = history_tail;
}
history_t *h;
for (h = history_needle; h != NULL; h = (hdi == HISTORY_OLDER ? h->prev : h->next)) {
if (!h->latest ||
h->loc.monitor == ref->monitor ||
!desktop_matches(&h->loc, ref, sel))
!monitor_matches(&h->loc, ref, sel)) {
continue;
if (!record_history)
}
if (!record_history) {
history_needle = h;
}
*dst = h->loc;
return true;
}
return false;
}

View file

@ -40,7 +40,7 @@ desktop_t *history_get_desktop(monitor_t *m, desktop_t *d);
monitor_t *history_get_monitor(monitor_t *m);
bool history_find_node(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, client_select_t sel);
bool history_find_desktop(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, desktop_select_t sel);
bool history_find_monitor(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, desktop_select_t sel);
bool history_find_monitor(history_dir_t hdi, coordinates_t *ref, coordinates_t *dst, monitor_select_t sel);
int history_rank(desktop_t *d, node_t *n);
#endif

View file

@ -544,7 +544,7 @@ int cmd_monitor(char **args, int num)
return MSG_FAILURE;
}
if (auto_alternate && dst.monitor == mon) {
desktop_select_t sel = make_desktop_select();
monitor_select_t sel = make_monitor_select();
history_find_monitor(HISTORY_OLDER, &trg, &dst, sel);
}
focus_node(dst.monitor, dst.monitor->desk, dst.monitor->desk->focus);

View file

@ -277,19 +277,23 @@ void swap_monitors(monitor_t *m1, monitor_t *m2)
put_status(SBSC_MASK_REPORT);
}
monitor_t *closest_monitor(monitor_t *m, cycle_dir_t dir, desktop_select_t sel)
monitor_t *closest_monitor(monitor_t *m, cycle_dir_t dir, monitor_select_t sel)
{
monitor_t *f = (dir == CYCLE_PREV ? m->prev : m->next);
if (f == NULL)
if (f == NULL) {
f = (dir == CYCLE_PREV ? mon_tail : mon_head);
}
while (f != m) {
coordinates_t loc = {m, m->desk, NULL};
if (desktop_matches(&loc, &loc, sel))
coordinates_t loc = {m, NULL, NULL};
if (monitor_matches(&loc, &loc, sel)) {
return f;
}
f = (dir == CYCLE_PREV ? m->prev : m->next);
if (f == NULL)
if (f == NULL) {
f = (dir == CYCLE_PREV ? mon_tail : mon_head);
}
}
return NULL;
@ -332,17 +336,19 @@ monitor_t *monitor_from_client(client_t *c)
return nearest;
}
monitor_t *nearest_monitor(monitor_t *m, direction_t dir, desktop_select_t sel)
monitor_t *nearest_monitor(monitor_t *m, direction_t dir, monitor_select_t sel)
{
int dmin = INT_MAX;
monitor_t *nearest = NULL;
xcb_rectangle_t rect = m->rectangle;
for (monitor_t *f = mon_head; f != NULL; f = f->next) {
if (f == m)
if (f == m) {
continue;
coordinates_t loc = {f, f->desk, NULL};
if (!desktop_matches(&loc, &loc, sel))
}
coordinates_t loc = {f, NULL, NULL};
if (!monitor_matches(&loc, &loc, sel)) {
continue;
}
xcb_rectangle_t r = f->rectangle;
if ((dir == DIR_LEFT && r.x < rect.x) ||
(dir == DIR_RIGHT && r.x >= (rect.x + rect.width)) ||

View file

@ -39,11 +39,11 @@ void add_monitor(monitor_t *m);
void remove_monitor(monitor_t *m);
void merge_monitors(monitor_t *ms, monitor_t *md);
void swap_monitors(monitor_t *m1, monitor_t *m2);
monitor_t *closest_monitor(monitor_t *m, cycle_dir_t dir, desktop_select_t sel);
monitor_t *closest_monitor(monitor_t *m, cycle_dir_t dir, monitor_select_t sel);
bool is_inside_monitor(monitor_t *m, xcb_point_t pt);
monitor_t *monitor_from_point(xcb_point_t pt);
monitor_t *monitor_from_client(client_t *c);
monitor_t *nearest_monitor(monitor_t *m, direction_t dir, desktop_select_t sel);
monitor_t *nearest_monitor(monitor_t *m, direction_t dir, monitor_select_t sel);
bool update_monitors(void);
#endif

82
query.c
View file

@ -264,12 +264,28 @@ desktop_select_t make_desktop_select(void)
{
desktop_select_t sel = {
.occupied = OPTION_NONE,
.focused = OPTION_NONE,
.urgent = OPTION_NONE,
.local = OPTION_NONE
};
return sel;
}
monitor_select_t make_monitor_select(void)
{
monitor_select_t sel = {
.occupied = OPTION_NONE,
.focused = OPTION_NONE
};
return sel;
}
#define GET_MOD(k) \
} else if (streq(#k, tok)) { \
sel.k = OPTION_TRUE; \
} else if (streq("!" #k, tok)) { \
sel.k = OPTION_FALSE;
bool node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
{
client_select_t sel = make_client_select();
@ -277,11 +293,6 @@ bool node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
while ((tok = strrchr(desc, CAT_CHR)) != NULL) {
tok[0] = '\0';
tok++;
#define GET_MOD(k) \
} else if (streq(#k, tok)) { \
sel.k = OPTION_TRUE; \
} else if (streq("!" #k, tok)) { \
sel.k = OPTION_FALSE;
if (streq("tiled", tok)) {
sel.tiled = OPTION_TRUE;
} else if (streq("!tiled", tok)) {
@ -302,7 +313,6 @@ bool node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
GET_MOD(above)
}
}
#undef GET_MOD
dst->monitor = ref->monitor;
dst->desktop = ref->desktop;
@ -314,7 +324,7 @@ bool node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
if (parse_direction(desc, &dir)) {
dst->node = nearest_neighbor(ref->monitor, ref->desktop, ref->node, dir, sel);
if (dst->node == NULL && mon_head != mon_tail) {
monitor_t *m = nearest_monitor(ref->monitor, dir, make_desktop_select());
monitor_t *m = nearest_monitor(ref->monitor, dir, make_monitor_select());
if (m != NULL) {
coordinates_t loc = {m, m->desk, m->desk->focus};
if (node_matches(&loc, ref, sel)) {
@ -360,14 +370,9 @@ bool desktop_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
sel.occupied = OPTION_TRUE;
} else if (streq("!occupied", tok)) {
sel.occupied = OPTION_FALSE;
} else if (streq("urgent", tok)) {
sel.urgent = OPTION_TRUE;
} else if (streq("!urgent", tok)) {
sel.urgent = OPTION_FALSE;
} else if (streq("local", tok)) {
sel.local = OPTION_TRUE;
} else if (streq("!local", tok)) {
sel.local = OPTION_FALSE;
GET_MOD(focused)
GET_MOD(urgent)
GET_MOD(local)
}
}
@ -419,7 +424,7 @@ bool desktop_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
bool monitor_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
{
desktop_select_t sel = make_desktop_select();
monitor_select_t sel = make_monitor_select();
char *tok;
while ((tok = strrchr(desc, CAT_CHR)) != NULL) {
tok[0] = '\0';
@ -428,6 +433,7 @@ bool monitor_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
sel.occupied = OPTION_TRUE;
} else if (streq("!occupied", tok)) {
sel.occupied = OPTION_FALSE;
GET_MOD(focused)
}
}
@ -447,31 +453,31 @@ bool monitor_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
history_find_monitor(HISTORY_OLDER, ref, dst, sel);
} else if (streq("primary", desc)) {
if (pri_mon != NULL) {
coordinates_t loc = {pri_mon, pri_mon->desk, NULL};
if (desktop_matches(&loc, ref, sel)) {
coordinates_t loc = {pri_mon, NULL, NULL};
if (monitor_matches(&loc, ref, sel)) {
dst->monitor = pri_mon;
}
}
} else if (streq("focused", desc)) {
coordinates_t loc = {mon, mon->desk, NULL};
if (desktop_matches(&loc, ref, sel)) {
coordinates_t loc = {mon, NULL, NULL};
if (monitor_matches(&loc, ref, sel)) {
dst->monitor = mon;
}
} else if (parse_index(desc, &idx)) {
if (monitor_from_index(idx, dst)) {
coordinates_t loc = {dst->monitor, dst->monitor->desk, NULL};
return desktop_matches(&loc, ref, sel);
monitor_matches(dst, ref, sel);
}
} else {
if (locate_monitor(desc, dst)) {
coordinates_t loc = {dst->monitor, dst->monitor->desk, NULL};
return desktop_matches(&loc, ref, sel);
return monitor_matches(dst, ref, sel);
}
}
return (dst->monitor != NULL);
}
#undef GET_MOD
bool locate_window(xcb_window_t win, coordinates_t *loc)
{
for (monitor_t *m = mon_head; m != NULL; m = m->next)
@ -625,7 +631,7 @@ bool node_matches(coordinates_t *loc, coordinates_t *ref, client_select_t sel)
}
if (sel.focused != OPTION_NONE &&
loc->node != loc->desktop->focus
loc->node != mon->desk->focus
? sel.focused == OPTION_TRUE
: sel.focused == OPTION_FALSE) {
return false;
@ -643,6 +649,13 @@ bool desktop_matches(coordinates_t *loc, coordinates_t *ref, desktop_select_t se
return false;
}
if (sel.focused != OPTION_NONE &&
mon->desk != loc->desktop
? sel.focused == OPTION_TRUE
: sel.focused == OPTION_FALSE) {
return false;
}
if (sel.urgent != OPTION_NONE &&
!is_urgent(loc->desktop)
? sel.urgent == OPTION_TRUE
@ -659,3 +672,22 @@ bool desktop_matches(coordinates_t *loc, coordinates_t *ref, desktop_select_t se
return true;
}
bool monitor_matches(coordinates_t *loc, __attribute__((unused)) coordinates_t *ref, monitor_select_t sel)
{
if (sel.occupied != OPTION_NONE &&
loc->monitor->desk->root == NULL
? sel.occupied == OPTION_TRUE
: sel.occupied == OPTION_FALSE) {
return false;
}
if (sel.focused != OPTION_NONE &&
mon != loc->monitor
? sel.focused == OPTION_TRUE
: sel.focused == OPTION_FALSE) {
return false;
}
return true;
}

View file

@ -47,6 +47,7 @@ void query_windows(coordinates_t loc, FILE *rsp);
void query_names(domain_t dom, coordinates_t loc, FILE *rsp);
client_select_t make_client_select(void);
desktop_select_t make_desktop_select(void);
monitor_select_t make_monitor_select(void);
bool node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst);
bool desktop_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst);
bool monitor_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst);
@ -57,5 +58,6 @@ bool desktop_from_index(int i, coordinates_t *loc, monitor_t *mm);
bool monitor_from_index(int i, coordinates_t *loc);
bool node_matches(coordinates_t *loc, coordinates_t *ref, client_select_t sel);
bool desktop_matches(coordinates_t *loc, coordinates_t *ref, desktop_select_t sel);
bool monitor_matches(coordinates_t *loc, __attribute__((unused)) coordinates_t *ref, monitor_select_t sel);
#endif

View file

@ -146,10 +146,16 @@ typedef struct {
typedef struct {
option_bool_t occupied;
option_bool_t focused;
option_bool_t urgent;
option_bool_t local;
} desktop_select_t;
typedef struct {
option_bool_t occupied;
option_bool_t focused;
} monitor_select_t;
typedef struct {
xcb_window_t window;
char class_name[3 * SMALEN / 2];