New setting: 'focus_follows_pointer'

This commit is contained in:
Bastien Dejean 2013-03-04 11:25:12 +01:00
parent 0acdab744c
commit 829bc9b91f
12 changed files with 112 additions and 2 deletions

View file

@ -217,6 +217,8 @@ Colors are either [X color names](http://en.wikipedia.org/wiki/X11_color_names)
- `gapless_monocle` — Whether to remove gaps for tiled windows in monocle mode.
- `focus_follows_pointer` — Wether to focus the window under the pointer.
- `adaptative_raise` — Prevent floating windows from being raised when they might cover other floating windows.
- `apply_shadow_property` — Enable shadows for floating windows via the `_COMPTON_SHADOW` property.

View file

@ -329,6 +329,9 @@ Whether to remove borders for tiled windows in monocle mode.
.I gapless_monocle
Whether to remove gaps for tiled windows in monocle mode.
.TP
.I focus_follows_pointer
Wether to focus the window under the pointer.
.TP
.I adaptative_raise
Prevent floating windows from being raised when they might cover other floating windows.
.TP

View file

@ -62,6 +62,11 @@ void setup(void)
screen_height = screen->height_in_pixels;
root_depth = screen->root_depth;
uint32_t mask = XCB_CW_EVENT_MASK;
uint32_t values[] = {XCB_EVENT_MASK_POINTER_MOTION};
motion_recorder = xcb_generate_id(dpy);
xcb_create_window(dpy, XCB_COPY_FROM_PARENT, motion_recorder, root, 0, 0, screen_width, screen_height, 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, mask, values);
xcb_atom_t net_atoms[] = {ewmh->_NET_SUPPORTED,
ewmh->_NET_DESKTOP_NAMES,
ewmh->_NET_NUMBER_OF_DESKTOPS,
@ -238,6 +243,7 @@ int main(int argc, char *argv[])
if (status_fifo != NULL)
fclose(status_fifo);
xcb_ewmh_connection_wipe(ewmh);
xcb_destroy_window(dpy, motion_recorder);
free(ewmh);
xcb_flush(dpy);
xcb_disconnect(dpy);

View file

@ -5,6 +5,7 @@
#define ROOT_EVENT_MASK (XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY)
#define CLIENT_EVENT_MASK (XCB_EVENT_MASK_PROPERTY_CHANGE)
#define CLIENT_EVENT_MASK_FFP (XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_ENTER_WINDOW)
xcb_connection_t *dpy;
int default_screen, screen_width, screen_height;
@ -30,6 +31,7 @@ rule_t *rule_head;
rule_t *rule_tail;
pointer_state_t *frozen_pointer;
xcb_window_t motion_recorder;
xcb_atom_t compton_shadow;
int exit_status;

View file

@ -35,6 +35,12 @@ void handle_event(xcb_generic_event_t *evt)
case XCB_PROPERTY_NOTIFY:
property_notify(evt);
break;
case XCB_ENTER_NOTIFY:
enter_notify(evt);
break;
case XCB_MOTION_NOTIFY:
motion_notify();
break;
default:
break;
}
@ -220,6 +226,32 @@ void client_message(xcb_generic_event_t *evt)
}
}
void enter_notify(xcb_generic_event_t *evt)
{
xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *) evt;
xcb_window_t win = e->event;
PRINTF("enter notify %X %d %d\n", win, e->mode, e->detail);
if (e->mode != XCB_NOTIFY_MODE_NORMAL
|| (mon->desk->focus != NULL && mon->desk->focus->client->window == win))
return;
enable_motion_recorder();
}
void motion_notify(void)
{
PUTS("motion notify");
disable_motion_recorder();
xcb_window_t win = XCB_NONE;
get_pointed_window(&win);
if (win != XCB_NONE)
window_focus(win);
}
void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsigned int action)
{
if (state == ewmh->_NET_WM_STATE_FULLSCREEN) {

View file

@ -11,6 +11,8 @@ void unmap_notify(xcb_generic_event_t *);
void configure_request(xcb_generic_event_t *);
void client_message(xcb_generic_event_t *);
void property_notify(xcb_generic_event_t *);
void enter_notify(xcb_generic_event_t *);
void motion_notify(void);
void handle_state(monitor_t *, desktop_t *, node_t *, xcb_atom_t, unsigned int);
void grab_pointer(pointer_action_t);
void track_pointer(int, int);

View file

@ -491,6 +491,20 @@ void set_setting(char *name, char *value, char *rsp)
bool b;
if (parse_bool(value, &b))
gapless_monocle = b;
} else if (strcmp(name, "focus_follows_pointer") == 0) {
bool b;
if (parse_bool(value, &b) && b != focus_follows_pointer) {
uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK : CLIENT_EVENT_MASK_FFP)};
for (monitor_t *m = mon_head; m != NULL; m = m->next)
for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n))
xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
if (focus_follows_pointer)
disable_motion_recorder();
else
enable_motion_recorder();
focus_follows_pointer = b;
}
} else if (strcmp(name, "adaptative_raise") == 0) {
bool b;
if (parse_bool(value, &b))
@ -548,6 +562,8 @@ void get_setting(char *name, char* rsp)
snprintf(rsp, BUFSIZ, "%s", BOOLSTR(borderless_monocle));
else if (strcmp(name, "gapless_monocle") == 0)
snprintf(rsp, BUFSIZ, "%s", BOOLSTR(gapless_monocle));
else if (strcmp(name, "focus_follows_pointer") == 0)
snprintf(rsp, BUFSIZ, "%s", BOOLSTR(focus_follows_pointer));
else if (strcmp(name, "adaptative_raise") == 0)
snprintf(rsp, BUFSIZ, "%s", BOOLSTR(adaptative_raise));
else if (strcmp(name, "apply_shadow_property") == 0)

View file

@ -61,6 +61,7 @@ void load_settings(void)
borderless_monocle = BORDERLESS_MONOCLE;
gapless_monocle = GAPLESS_MONOCLE;
focus_follows_pointer = FOCUS_FOLLOWS_POINTER;
adaptative_raise = ADAPTATIVE_RAISE;
apply_shadow_property = APPLY_SHADOW_PROPERTY;
}

View file

@ -22,6 +22,7 @@
#define BORDERLESS_MONOCLE false
#define GAPLESS_MONOCLE false
#define FOCUS_FOLLOWS_POINTER false
#define ADAPTATIVE_RAISE false
#define APPLY_SHADOW_PROPERTY false
@ -48,6 +49,7 @@ int window_gap;
bool borderless_monocle;
bool gapless_monocle;
bool focus_follows_pointer;
bool adaptative_raise;
bool apply_shadow_property;

11
tree.c
View file

@ -386,6 +386,15 @@ void focus_node(monitor_t *m, desktop_t *d, node_t *n, bool is_mapped)
xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, n->client->window, XCB_CURRENT_TIME);
}
if (focus_follows_pointer) {
xcb_window_t win = XCB_NONE;
get_pointed_window(&win);
if (win != n->client->window)
enable_motion_recorder();
else
disable_motion_recorder();
}
if (!is_tiled(n->client)) {
if (!adaptative_raise || !might_cover(d, n))
window_raise(n->client->window);
@ -940,7 +949,7 @@ void restore(char *file_path)
for (monitor_t *m = mon_head; m != NULL; m = m->next)
for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n)) {
uint32_t values[] = {CLIENT_EVENT_MASK};
uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK_FFP : CLIENT_EVENT_MASK)};
xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
if (n->client->floating) {
n->vacant = true;

View file

@ -154,7 +154,7 @@ void manage_window(monitor_t *m, desktop_t *d, xcb_window_t win)
if (takes_focus)
xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME);
uint32_t values[] = {CLIENT_EVENT_MASK};
uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK_FFP : CLIENT_EVENT_MASK)};
xcb_change_window_attributes(dpy, c->window, XCB_CW_EVENT_MASK, values);
num_clients++;
@ -411,6 +411,27 @@ void update_floating_rectangle(client_t *c)
}
}
void save_pointer_position(xcb_point_t *pos)
{
xcb_query_pointer_reply_t *qpr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), NULL);
if (qpr != NULL) {
*pos = (xcb_point_t) {qpr->root_x, qpr->root_y};
free(qpr);
}
}
void get_pointed_window(xcb_window_t *win)
{
window_lower(motion_recorder);
xcb_query_pointer_reply_t *qpr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), NULL);
if (qpr != NULL) {
*win = qpr->child;
free(qpr);
}
window_raise(motion_recorder);
}
void window_focus(xcb_window_t win)
{
window_location_t loc;
@ -490,3 +511,14 @@ void toggle_visibility(void)
if (visible)
update_current();
}
void enable_motion_recorder(void)
{
window_raise(motion_recorder);
window_show(motion_recorder);
}
void disable_motion_recorder(void)
{
window_hide(motion_recorder);
}

View file

@ -34,9 +34,12 @@ void window_lower(xcb_window_t);
void window_set_visibility(xcb_window_t, bool);
void window_hide(xcb_window_t);
void window_show(xcb_window_t);
void enable_motion_recorder(void);
void disable_motion_recorder(void);
void toggle_visibility(void);
uint32_t get_border_color(client_t *, bool, bool);
void update_floating_rectangle(client_t *);
void get_pointed_window(xcb_window_t *);
void list_windows(char *);
#endif