mirror of
https://github.com/vale981/bspwm
synced 2025-03-04 17:31:39 -05:00
New setting: history_aware_focus
This commit is contained in:
parent
7fb314a3d4
commit
d5d8805ad2
10 changed files with 143 additions and 51 deletions
|
@ -247,6 +247,8 @@ All the boolean settings are *false* by default.
|
|||
|
||||
- `focus_by_distance` — Use window or leaf distance for focus movement.
|
||||
|
||||
- `history_aware_focus` — Give priority to the focus history when focusing nodes.
|
||||
|
||||
## Environment Variables
|
||||
|
||||
- `BSPWM_SOCKET` — The path of the socket used for the communication between `bspc` and `bspwm`.
|
||||
|
|
|
@ -2,7 +2,7 @@ _bspc()
|
|||
{
|
||||
local messages='get set list list_desktops list_monitors list_windows list_rules list_history presel cancel ratio pad focus shift swap push pull fence_ratio cycle nearest biggest circulate grab_pointer track_pointer ungrab_pointer toggle_fullscreen toggle_floating toggle_locked toggle_visibility close kill send_to drop_to send_to_monitor drop_to_monitor use use_monitor alternate alternate_desktop alternate_monitor add add_in rename_monitor rename remove_desktop send_desktop_to cycle_monitor cycle_desktop layout cycle_layout rotate flip balance rule remove_rule put_status adopt_orphans restore_layout restore_history quit'
|
||||
|
||||
local settings='focused_border_color active_border_color normal_border_color presel_border_color focused_locked_border_color active_locked_border_color normal_locked_border_color urgent_border_color border_width window_gap split_ratio top_padding right_padding bottom_padding left_padding wm_name borderless_monocle gapless_monocle focus_follows_pointer pointer_follows_monitor adaptative_raise apply_shadow_property auto_alternate focus_by_distance'
|
||||
local settings='focused_border_color active_border_color normal_border_color presel_border_color focused_locked_border_color active_locked_border_color normal_locked_border_color urgent_border_color border_width window_gap split_ratio top_padding right_padding bottom_padding left_padding wm_name borderless_monocle gapless_monocle focus_follows_pointer pointer_follows_monitor adaptative_raise apply_shadow_property auto_alternate focus_by_distance history_aware_focus'
|
||||
|
||||
COMPREPLY=()
|
||||
|
||||
|
|
3
bspwm.1
3
bspwm.1
|
@ -372,6 +372,9 @@ message.
|
|||
.TP
|
||||
.I focus_by_distance
|
||||
Use window or leaf distance for focus movement.
|
||||
.TP
|
||||
.I history_aware_focus
|
||||
Give priority to the focus history when focusing nodes.
|
||||
.SH ENVIRONMENT VARIABLES
|
||||
.TP
|
||||
.I BSPWM_SOCKET
|
||||
|
|
25
messages.c
25
messages.c
|
@ -445,17 +445,23 @@ void process_message(char *msg, char *rsp)
|
|||
}
|
||||
}
|
||||
} else if (strcmp(cmd, "focus") == 0) {
|
||||
if (mon->desk->focus == NULL || mon->desk->focus->client->fullscreen)
|
||||
node_t *f = mon->desk->focus;
|
||||
if (f == NULL || f->client->fullscreen)
|
||||
return;
|
||||
char *dir = strtok(NULL, TOK_SEP);
|
||||
if (dir != NULL) {
|
||||
direction_t d;
|
||||
if (parse_direction(dir, &d)) {
|
||||
node_t *n;
|
||||
if (focus_by_distance)
|
||||
n = nearest_neighbor(mon->desk, mon->desk->focus, d);
|
||||
else
|
||||
n = find_neighbor(mon->desk->focus, d);
|
||||
node_t *n = NULL;
|
||||
if (history_aware_focus)
|
||||
n = nearest_from_history(mon->desk->history, f, d);
|
||||
if (n == NULL) {
|
||||
if (focus_by_distance) {
|
||||
n = nearest_neighbor(mon->desk, f, d);
|
||||
} else {
|
||||
n = find_neighbor(f, d);
|
||||
}
|
||||
}
|
||||
focus_node(mon, mon->desk, n);
|
||||
}
|
||||
}
|
||||
|
@ -570,6 +576,11 @@ void set_setting(char *name, char *value, char *rsp)
|
|||
if (parse_bool(value, &b))
|
||||
focus_by_distance = b;
|
||||
return;
|
||||
} else if (strcmp(name, "history_aware_focus") == 0) {
|
||||
bool b;
|
||||
if (parse_bool(value, &b))
|
||||
history_aware_focus = b;
|
||||
return;
|
||||
} else if (strcmp(name, "wm_name") == 0) {
|
||||
strncpy(wm_name, value, sizeof(wm_name));
|
||||
ewmh_update_wm_name();
|
||||
|
@ -635,6 +646,8 @@ void get_setting(char *name, char* rsp)
|
|||
snprintf(rsp, BUFSIZ, "%s", BOOLSTR(auto_alternate));
|
||||
else if (strcmp(name, "focus_by_distance") == 0)
|
||||
snprintf(rsp, BUFSIZ, "%s", BOOLSTR(focus_by_distance));
|
||||
else if (strcmp(name, "history_aware_focus") == 0)
|
||||
snprintf(rsp, BUFSIZ, "%s", BOOLSTR(history_aware_focus));
|
||||
else if (strcmp(name, "wm_name") == 0)
|
||||
snprintf(rsp, BUFSIZ, "%s", wm_name);
|
||||
else
|
||||
|
|
|
@ -68,4 +68,5 @@ void load_settings(void)
|
|||
apply_shadow_property = APPLY_SHADOW_PROPERTY;
|
||||
auto_alternate = AUTO_ALTERNATE;
|
||||
focus_by_distance = FOCUS_BY_DISTANCE;
|
||||
history_aware_focus = HISTORY_AWARE_FOCUS;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define APPLY_SHADOW_PROPERTY false
|
||||
#define AUTO_ALTERNATE false
|
||||
#define FOCUS_BY_DISTANCE false
|
||||
#define HISTORY_AWARE_FOCUS false
|
||||
|
||||
char focused_border_color[MAXLEN];
|
||||
char active_border_color[MAXLEN];
|
||||
|
@ -59,6 +60,7 @@ bool adaptative_raise;
|
|||
bool apply_shadow_property;
|
||||
bool auto_alternate;
|
||||
bool focus_by_distance;
|
||||
bool history_aware_focus;
|
||||
|
||||
char wm_name[MAXLEN];
|
||||
|
||||
|
|
140
tree.c
140
tree.c
|
@ -2,6 +2,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
@ -100,6 +101,19 @@ node_t *prev_leaf(node_t *n, node_t *r)
|
|||
return second_extrema(p->parent->first_child);
|
||||
}
|
||||
|
||||
bool is_adjacent(node_t *a, node_t *r)
|
||||
{
|
||||
node_t *f = r->parent;
|
||||
node_t *p = a;
|
||||
bool first_child = is_first_child(r);
|
||||
while (p != r) {
|
||||
if (p->parent->split_type == f->split_type && is_first_child(p) == first_child)
|
||||
return false;
|
||||
p = p->parent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
node_t *find_fence(node_t *n, direction_t dir)
|
||||
{
|
||||
node_t *p;
|
||||
|
@ -123,20 +137,97 @@ node_t *find_fence(node_t *n, direction_t dir)
|
|||
|
||||
node_t *find_neighbor(node_t *n, direction_t dir)
|
||||
{
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
|
||||
node_t *fence = find_fence(n, dir);
|
||||
|
||||
if (fence == NULL)
|
||||
return NULL;
|
||||
|
||||
if (dir == DIR_UP || dir == DIR_LEFT)
|
||||
return second_extrema(fence->first_child);
|
||||
else if (dir == DIR_DOWN || dir == DIR_RIGHT)
|
||||
return first_extrema(fence->second_child);
|
||||
node_t *nearest = NULL;
|
||||
|
||||
return NULL;
|
||||
if (dir == DIR_UP || dir == DIR_LEFT)
|
||||
nearest = second_extrema(fence->first_child);
|
||||
else if (dir == DIR_DOWN || dir == DIR_RIGHT)
|
||||
nearest = first_extrema(fence->second_child);
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
void get_opposite(direction_t src, direction_t* dst)
|
||||
node_t *nearest_from_history(focus_history_t *f, node_t *n, direction_t dir)
|
||||
{
|
||||
if (n == NULL || !is_tiled(n->client))
|
||||
return NULL;
|
||||
|
||||
node_t *target = find_fence(n, dir);
|
||||
if (target == NULL)
|
||||
return NULL;
|
||||
if (dir == DIR_UP || dir == DIR_LEFT)
|
||||
target = target->first_child;
|
||||
else if (dir == DIR_DOWN || dir == DIR_RIGHT)
|
||||
target = target->second_child;
|
||||
|
||||
node_t *nearest = NULL;
|
||||
int min_rank = INT_MAX;
|
||||
|
||||
for (node_t *a = first_extrema(target); a != NULL; a = next_leaf(a, target)) {
|
||||
if (!is_tiled(a->client) || !is_adjacent(a, target) || a == n)
|
||||
continue;
|
||||
int rank = history_rank(f, a);
|
||||
if (rank >= 0 && rank < min_rank) {
|
||||
nearest = a;
|
||||
min_rank = rank;
|
||||
}
|
||||
}
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
node_t *nearest_neighbor(desktop_t *d, node_t *n, direction_t dir)
|
||||
{
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
|
||||
node_t *target = NULL;
|
||||
|
||||
if (is_tiled(n->client)) {
|
||||
target = find_fence(n, dir);
|
||||
if (target == NULL)
|
||||
return NULL;
|
||||
if (dir == DIR_UP || dir == DIR_LEFT)
|
||||
target = target->first_child;
|
||||
else if (dir == DIR_DOWN || dir == DIR_RIGHT)
|
||||
target = target->second_child;
|
||||
} else {
|
||||
target = d->root;
|
||||
}
|
||||
|
||||
node_t *nearest = NULL;
|
||||
direction_t dir2;
|
||||
xcb_point_t pt;
|
||||
xcb_point_t pt2;
|
||||
get_side_handle(n->client, dir, &pt);
|
||||
get_opposite(dir, &dir2);
|
||||
double ds = DBL_MAX;
|
||||
|
||||
for (node_t *a = first_extrema(target); a != NULL; a = next_leaf(a, target)) {
|
||||
if (is_tiled(a->client) != is_tiled(n->client)
|
||||
|| (is_tiled(a->client) && !is_adjacent(a, target))
|
||||
|| a == n)
|
||||
continue;
|
||||
get_side_handle(a->client, dir2, &pt2);
|
||||
double ds2 = distance(pt, pt2);
|
||||
if (ds2 < ds) {
|
||||
ds = ds2;
|
||||
nearest = a;
|
||||
}
|
||||
}
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
void get_opposite(direction_t src, direction_t *dst)
|
||||
{
|
||||
switch (src) {
|
||||
case DIR_RIGHT:
|
||||
|
@ -154,43 +245,6 @@ void get_opposite(direction_t src, direction_t* dst)
|
|||
}
|
||||
}
|
||||
|
||||
node_t *nearest_neighbor(desktop_t *d, node_t *n, direction_t dir)
|
||||
{
|
||||
if (n == NULL)
|
||||
return NULL;
|
||||
|
||||
node_t *target = NULL;
|
||||
if (is_tiled(n->client)) {
|
||||
target = find_fence(n, dir);
|
||||
if (target == NULL)
|
||||
return NULL;
|
||||
if (dir == DIR_UP || dir == DIR_LEFT)
|
||||
target = target->first_child;
|
||||
else if (dir == DIR_DOWN || dir == DIR_RIGHT)
|
||||
target = target->second_child;
|
||||
} else {
|
||||
target = d->root;
|
||||
}
|
||||
node_t *nearest = NULL;
|
||||
direction_t dir2;
|
||||
xcb_point_t pt;
|
||||
xcb_point_t pt2;
|
||||
get_side_handle(n->client, dir, &pt);
|
||||
get_opposite(dir, &dir2);
|
||||
double ds = DBL_MAX;
|
||||
for (node_t *a = first_extrema(target); a != NULL; a = next_leaf(a, target)) {
|
||||
if (is_tiled(a->client) != is_tiled(n->client) || a == n)
|
||||
continue;
|
||||
get_side_handle(a->client, dir2, &pt2);
|
||||
double ds2 = distance(pt, pt2);
|
||||
if (ds2 < ds) {
|
||||
ds = ds2;
|
||||
nearest = a;
|
||||
}
|
||||
}
|
||||
return nearest;
|
||||
}
|
||||
|
||||
int tiled_area(node_t *n)
|
||||
{
|
||||
if (n == NULL)
|
||||
|
|
4
tree.h
4
tree.h
|
@ -15,10 +15,12 @@ node_t *first_extrema(node_t *);
|
|||
node_t *second_extrema(node_t *);
|
||||
node_t *next_leaf(node_t *, node_t *);
|
||||
node_t *prev_leaf(node_t *, node_t *);
|
||||
bool is_adjacent(node_t *, node_t *);
|
||||
node_t *find_fence(node_t *, direction_t);
|
||||
node_t *find_neighbor(node_t *, direction_t);
|
||||
void get_opposite(direction_t, direction_t*);
|
||||
node_t *nearest_neighbor(desktop_t *, node_t *, direction_t);
|
||||
node_t *nearest_from_history(focus_history_t *, node_t *, direction_t);
|
||||
void get_opposite(direction_t, direction_t *);
|
||||
int tiled_area(node_t *);
|
||||
node_t *find_biggest(desktop_t *);
|
||||
void move_fence(node_t *, direction_t, fence_move_t);
|
||||
|
|
14
types.c
14
types.c
|
@ -336,3 +336,17 @@ node_t *history_get(focus_history_t *f, int i)
|
|||
else
|
||||
return a->node;
|
||||
}
|
||||
|
||||
int history_rank(focus_history_t *f, node_t *n)
|
||||
{
|
||||
int i = 0;
|
||||
node_list_t *a = f->head;
|
||||
while (a != NULL && (!a->latest || a->node != n)) {
|
||||
a = a->next;
|
||||
i++;
|
||||
}
|
||||
if (a == NULL)
|
||||
return -1;
|
||||
else
|
||||
return i;
|
||||
}
|
||||
|
|
1
types.h
1
types.h
|
@ -267,5 +267,6 @@ void history_add(focus_history_t *, node_t *);
|
|||
void history_remove(focus_history_t *, node_t *);
|
||||
void empty_history(focus_history_t *);
|
||||
node_t *history_get(focus_history_t *, int);
|
||||
int history_rank(focus_history_t *, node_t *);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue