mirror of
https://github.com/vale981/bspwm
synced 2025-03-05 18:01:37 -05:00
parent
184f444309
commit
32e3005d7a
10 changed files with 152 additions and 86 deletions
|
@ -195,6 +195,7 @@ int main(int argc, char *argv[])
|
|||
ungrab_buttons();
|
||||
xcb_ewmh_connection_wipe(ewmh);
|
||||
xcb_destroy_window(dpy, meta_window);
|
||||
xcb_destroy_window(dpy, motion_recorder.id);
|
||||
free(ewmh);
|
||||
xcb_flush(dpy);
|
||||
xcb_disconnect(dpy);
|
||||
|
@ -237,6 +238,14 @@ void setup(void)
|
|||
xcb_create_window(dpy, XCB_COPY_FROM_PARENT, meta_window, root, -1, -1, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, XCB_NONE, NULL);
|
||||
xcb_icccm_set_wm_class(dpy, meta_window, sizeof(META_WINDOW_IC), META_WINDOW_IC);
|
||||
|
||||
motion_recorder.id = xcb_generate_id(dpy);
|
||||
motion_recorder.sequence = 0;
|
||||
motion_recorder.enabled = false;
|
||||
uint32_t values[] = {XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_POINTER_MOTION};
|
||||
xcb_create_window(dpy, XCB_COPY_FROM_PARENT, motion_recorder.id, root, 0, 0, 1, 1, 0,
|
||||
XCB_WINDOW_CLASS_INPUT_ONLY, XCB_COPY_FROM_PARENT, XCB_CW_EVENT_MASK, values);
|
||||
xcb_icccm_set_wm_class(dpy, motion_recorder.id, sizeof(MOTION_RECORDER_IC), MOTION_RECORDER_IC);
|
||||
|
||||
xcb_atom_t net_atoms[] = {ewmh->_NET_SUPPORTED,
|
||||
ewmh->_NET_SUPPORTING_WM_CHECK,
|
||||
ewmh->_NET_DESKTOP_NAMES,
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
#define ROOT_WINDOW_IC "root\0" BSPWM_CLASS_NAME
|
||||
#define PRESEL_FEEDBACK_I "presel_feedback"
|
||||
#define PRESEL_FEEDBACK_IC PRESEL_FEEDBACK_I "\0" BSPWM_CLASS_NAME
|
||||
#define MOTION_RECORDER_I "motion_recorder"
|
||||
#define MOTION_RECORDER_IC MOTION_RECORDER_I "\0" BSPWM_CLASS_NAME
|
||||
|
||||
xcb_connection_t *dpy;
|
||||
int default_screen, screen_width, screen_height;
|
||||
|
@ -59,6 +61,11 @@ pending_rule_t *pending_rule_head;
|
|||
pending_rule_t *pending_rule_tail;
|
||||
|
||||
xcb_window_t meta_window;
|
||||
struct {
|
||||
xcb_window_t id;
|
||||
uint16_t sequence;
|
||||
bool enabled;
|
||||
} motion_recorder;
|
||||
xcb_atom_t WM_STATE;
|
||||
xcb_atom_t WM_TAKE_FOCUS;
|
||||
xcb_atom_t WM_DELETE_WINDOW;
|
||||
|
|
|
@ -43,14 +43,8 @@ void focus_desktop(monitor_t *m, desktop_t *d)
|
|||
focus_monitor(m);
|
||||
|
||||
if (m->desk != d) {
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(d->root, false);
|
||||
}
|
||||
show_desktop(d);
|
||||
hide_desktop(m->desk);
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(d->root, true);
|
||||
}
|
||||
m->desk = d;
|
||||
}
|
||||
|
||||
|
@ -139,17 +133,11 @@ void handle_presel_feedbacks(monitor_t *m, desktop_t *d)
|
|||
if (m->desk != d) {
|
||||
return;
|
||||
}
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(d->root, false);
|
||||
}
|
||||
if (d->layout == LAYOUT_MONOCLE) {
|
||||
hide_presel_feedbacks(m, d, d->root);
|
||||
} else {
|
||||
show_presel_feedbacks(m, d, d->root);
|
||||
}
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(d->root, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool transfer_desktop(monitor_t *ms, monitor_t *md, desktop_t *d)
|
||||
|
|
82
src/events.c
82
src/events.c
|
@ -62,6 +62,9 @@ void handle_event(xcb_generic_event_t *evt)
|
|||
case XCB_ENTER_NOTIFY:
|
||||
enter_notify(evt);
|
||||
break;
|
||||
case XCB_MOTION_NOTIFY:
|
||||
motion_notify(evt);
|
||||
break;
|
||||
case XCB_BUTTON_PRESS:
|
||||
button_press(evt);
|
||||
break;
|
||||
|
@ -162,16 +165,8 @@ void configure_request(xcb_generic_event_t *evt)
|
|||
c->floating_rectangle.height = height;
|
||||
xcb_rectangle_t r = c->floating_rectangle;
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(loc.desktop->root, false);
|
||||
}
|
||||
|
||||
window_move_resize(e->window, r.x, r.y, r.width, r.height);
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(loc.desktop->root, true);
|
||||
}
|
||||
|
||||
put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc.monitor->id, loc.desktop->id, e->window, r.width, r.height, r.x, r.y);
|
||||
|
||||
monitor_t *m = monitor_from_client(c);
|
||||
|
@ -238,6 +233,15 @@ void unmap_notify(xcb_generic_event_t *evt)
|
|||
{
|
||||
xcb_unmap_notify_event_t *e = (xcb_unmap_notify_event_t *) evt;
|
||||
|
||||
if (e->window == motion_recorder.id) {
|
||||
/* Unmapping the motion recorder in `query_pointer` will produce
|
||||
* unwanted enter notify events. We can filter those events because
|
||||
* their sequence number is the same as the sequence number of the
|
||||
* related unmap notify event. This is a technique used by i3-wm to
|
||||
* filter enter notify events. */
|
||||
motion_recorder.sequence = e->sequence;
|
||||
}
|
||||
|
||||
unmanage_window(e->window);
|
||||
}
|
||||
|
||||
|
@ -370,30 +374,64 @@ void enter_notify(xcb_generic_event_t *evt)
|
|||
return;
|
||||
}
|
||||
|
||||
xcb_point_t pt = {e->root_x, e->root_y};
|
||||
monitor_t *m = monitor_from_point(pt);
|
||||
|
||||
if (m == NULL) {
|
||||
/* Ignore the enter notify events that we generated by unmapping the motion
|
||||
* recorder window in `query_pointer`. */
|
||||
if (motion_recorder.enabled && motion_recorder.sequence == e->sequence) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (win == mon->root || (mon->desk->focus != NULL &&
|
||||
(win == mon->desk->focus->id ||
|
||||
(mon->desk->focus->presel != NULL &&
|
||||
win == mon->desk->focus->presel->feedback)))) {
|
||||
return;
|
||||
}
|
||||
|
||||
update_motion_recorder();
|
||||
}
|
||||
|
||||
void motion_notify(xcb_generic_event_t *evt)
|
||||
{
|
||||
xcb_motion_notify_event_t *e = (xcb_motion_notify_event_t *) evt;
|
||||
|
||||
static uint16_t last_motion_x = 0, last_motion_y = 0;
|
||||
static xcb_timestamp_t last_motion_time = 0;
|
||||
|
||||
int64_t dtime = e->time - last_motion_time;
|
||||
|
||||
/* Ignore unintentional pointer motions. */
|
||||
if (dtime > 1000) {
|
||||
last_motion_time = e->time;
|
||||
last_motion_x = e->event_x;
|
||||
last_motion_y = e->event_y;
|
||||
return;
|
||||
}
|
||||
int mdist = abs(e->event_x - last_motion_x) + abs(e->event_y - last_motion_y);
|
||||
if (mdist < 10) {
|
||||
return;
|
||||
}
|
||||
|
||||
disable_motion_recorder();
|
||||
|
||||
xcb_window_t win = XCB_NONE;
|
||||
query_pointer(&win, NULL);
|
||||
coordinates_t loc;
|
||||
bool pff = pointer_follows_focus;
|
||||
bool pfm = pointer_follows_monitor;
|
||||
pointer_follows_focus = false;
|
||||
pointer_follows_monitor = false;
|
||||
auto_raise = false;
|
||||
|
||||
desktop_t *d = m->desk;
|
||||
node_t *n = NULL;
|
||||
|
||||
for (n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
|
||||
if (n->id == win || (n->presel != NULL && n->presel->feedback == win)) {
|
||||
break;
|
||||
if (locate_window(win, &loc)) {
|
||||
if (loc.monitor->desk == loc.desktop && loc.node != mon->desk->focus) {
|
||||
focus_node(loc.monitor, loc.desktop, loc.node);
|
||||
}
|
||||
} else {
|
||||
xcb_point_t pt = {e->root_x, e->root_y};
|
||||
monitor_t *m = monitor_from_point(pt);
|
||||
if (m != NULL && m != mon) {
|
||||
focus_node(m, m->desk, m->desk->focus);
|
||||
}
|
||||
}
|
||||
|
||||
if (n != mon->desk->focus || mon->desk->focus == NULL) {
|
||||
focus_node(m, d, n == NULL ? d->focus : n);
|
||||
}
|
||||
|
||||
pointer_follows_focus = pff;
|
||||
|
|
|
@ -41,6 +41,7 @@ void client_message(xcb_generic_event_t *evt);
|
|||
void focus_in(xcb_generic_event_t *evt);
|
||||
void button_press(xcb_generic_event_t *evt);
|
||||
void enter_notify(xcb_generic_event_t *evt);
|
||||
void motion_notify(xcb_generic_event_t *evt);
|
||||
void handle_state(monitor_t *m, desktop_t *d, node_t *n, xcb_atom_t state, unsigned int action);
|
||||
void process_error(xcb_generic_event_t *evt);
|
||||
|
||||
|
|
|
@ -1475,15 +1475,20 @@ void set_setting(coordinates_t loc, char *name, char *value, FILE *rsp)
|
|||
}
|
||||
focus_follows_pointer = b;
|
||||
for (monitor_t *m = mon_head; m != NULL; m = m->next) {
|
||||
if (b) {
|
||||
if (focus_follows_pointer) {
|
||||
window_show(m->root);
|
||||
} else {
|
||||
window_hide(m->root);
|
||||
}
|
||||
for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
|
||||
listen_enter_notify(d->root, b);
|
||||
listen_enter_notify(d->root, focus_follows_pointer);
|
||||
}
|
||||
}
|
||||
if (focus_follows_pointer) {
|
||||
update_motion_recorder();
|
||||
} else {
|
||||
disable_motion_recorder();
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
fail(rsp, "config: %s: Invalid value: '%s'.\n", name, value);
|
||||
|
|
|
@ -454,7 +454,7 @@ int node_from_desc(char *desc, coordinates_t *ref, coordinates_t *dst)
|
|||
} else if (streq("biggest", desc)) {
|
||||
find_biggest(ref, dst, sel);
|
||||
} else if (streq("pointed", desc)) {
|
||||
xcb_window_t win;
|
||||
xcb_window_t win = XCB_NONE;
|
||||
query_pointer(&win, NULL);
|
||||
if (locate_window(win, dst) && node_matches(dst, ref, sel)) {
|
||||
return SELECTOR_OK;
|
||||
|
|
30
src/tree.c
30
src/tree.c
|
@ -67,15 +67,7 @@ void arrange(monitor_t *m, desktop_t *d)
|
|||
rect.height -= d->window_gap;
|
||||
}
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(d->root, false);
|
||||
}
|
||||
|
||||
apply_layout(m, d, d->root, l, rect, rect);
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(d->root, true);
|
||||
}
|
||||
}
|
||||
|
||||
void apply_layout(monitor_t *m, desktop_t *d, node_t *n, layout_t l, xcb_rectangle_t rect, xcb_rectangle_t root_rect)
|
||||
|
@ -224,18 +216,10 @@ void cancel_presel(monitor_t *m, desktop_t *d, node_t *n)
|
|||
return;
|
||||
}
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(n, false);
|
||||
}
|
||||
|
||||
if (n->presel->feedback != XCB_NONE) {
|
||||
xcb_destroy_window(dpy, n->presel->feedback);
|
||||
}
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(n, true);
|
||||
}
|
||||
|
||||
free(n->presel);
|
||||
n->presel = NULL;
|
||||
|
||||
|
@ -594,6 +578,9 @@ bool focus_node(monitor_t *m, desktop_t *d, node_t *n)
|
|||
put_status(SBSC_MASK_REPORT);
|
||||
|
||||
if (n == NULL) {
|
||||
if (focus_follows_pointer) {
|
||||
update_motion_recorder();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -604,6 +591,8 @@ bool focus_node(monitor_t *m, desktop_t *d, node_t *n)
|
|||
|
||||
if (pointer_follows_focus) {
|
||||
center_pointer(get_rectangle(d, n));
|
||||
} else if (focus_follows_pointer) {
|
||||
update_motion_recorder();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1725,11 +1714,6 @@ void set_hidden(monitor_t *m, desktop_t *d, node_t *n, bool value)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(d->root, false);
|
||||
}
|
||||
|
||||
bool held_focus = is_descendant(d->focus, n);
|
||||
|
||||
propagate_hidden_downward(m, d, n, value);
|
||||
|
@ -1748,10 +1732,6 @@ void set_hidden(monitor_t *m, desktop_t *d, node_t *n, bool value)
|
|||
activate_node(m, d, d->focus);
|
||||
}
|
||||
}
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(d->root, true);
|
||||
}
|
||||
}
|
||||
|
||||
void set_hidden_local(monitor_t *m, desktop_t *d, node_t *n, bool value)
|
||||
|
|
83
src/window.c
83
src/window.c
|
@ -274,10 +274,6 @@ void draw_presel_feedback(monitor_t *m, desktop_t *d, node_t *n)
|
|||
return;
|
||||
}
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(d->root, false);
|
||||
}
|
||||
|
||||
bool exists = (n->presel->feedback != XCB_NONE);
|
||||
if (!exists) {
|
||||
initialize_presel_feedback(n);
|
||||
|
@ -314,10 +310,6 @@ void draw_presel_feedback(monitor_t *m, desktop_t *d, node_t *n)
|
|||
if (!exists && m->desk == d) {
|
||||
window_show(p->feedback);
|
||||
}
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(d->root, true);
|
||||
}
|
||||
}
|
||||
|
||||
void refresh_presel_feedbacks(monitor_t *m, desktop_t *d, node_t *n)
|
||||
|
@ -510,16 +502,8 @@ bool move_client(coordinates_t *loc, int dx, int dy)
|
|||
int16_t x = rect.x + dx;
|
||||
int16_t y = rect.y + dy;
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(loc->desktop->root, false);
|
||||
}
|
||||
|
||||
window_move(n->id, x, y);
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(loc->desktop->root, true);
|
||||
}
|
||||
|
||||
c->floating_rectangle.x = x;
|
||||
c->floating_rectangle.y = y;
|
||||
if (!grabbing) {
|
||||
|
@ -594,16 +578,8 @@ bool resize_client(coordinates_t *loc, resize_handle_t rh, int dx, int dy)
|
|||
}
|
||||
n->client->floating_rectangle = (xcb_rectangle_t) {x, y, width, height};
|
||||
if (n->client->state == STATE_FLOATING) {
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(loc->desktop->root, false);
|
||||
}
|
||||
|
||||
window_move_resize(n->id, x, y, width, height);
|
||||
|
||||
if (focus_follows_pointer) {
|
||||
listen_enter_notify(loc->desktop->root, true);
|
||||
}
|
||||
|
||||
if (!grabbing) {
|
||||
put_status(SBSC_MASK_NODE_GEOMETRY, "node_geometry 0x%08X 0x%08X 0x%08X %ux%u+%i+%i\n", loc->monitor->id, loc->desktop->id, loc->node->id, width, height, x, y);
|
||||
}
|
||||
|
@ -709,6 +685,10 @@ void apply_size_hints(client_t *c, uint16_t *width, uint16_t *height)
|
|||
|
||||
void query_pointer(xcb_window_t *win, xcb_point_t *pt)
|
||||
{
|
||||
if (motion_recorder.enabled) {
|
||||
window_hide(motion_recorder.id);
|
||||
}
|
||||
|
||||
xcb_query_pointer_reply_t *qpr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, root), NULL);
|
||||
|
||||
if (qpr != NULL) {
|
||||
|
@ -734,6 +714,59 @@ void query_pointer(xcb_window_t *win, xcb_point_t *pt)
|
|||
}
|
||||
|
||||
free(qpr);
|
||||
|
||||
if (motion_recorder.enabled) {
|
||||
window_show(motion_recorder.id);
|
||||
}
|
||||
}
|
||||
|
||||
void update_motion_recorder(void)
|
||||
{
|
||||
xcb_point_t pt;
|
||||
xcb_window_t win = XCB_NONE;
|
||||
query_pointer(&win, &pt);
|
||||
if (win == XCB_NONE) {
|
||||
return;
|
||||
}
|
||||
monitor_t *m = monitor_from_point(pt);
|
||||
if (m == NULL) {
|
||||
return;
|
||||
}
|
||||
desktop_t *d = m->desk;
|
||||
node_t *n = NULL;
|
||||
for (n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
|
||||
if (n->id == win || (n->presel != NULL && n->presel->feedback == win)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((n != NULL && n != mon->desk->focus) || (n == NULL && m != mon)) {
|
||||
enable_motion_recorder(win);
|
||||
} else {
|
||||
disable_motion_recorder();
|
||||
}
|
||||
}
|
||||
|
||||
void enable_motion_recorder(xcb_window_t win)
|
||||
{
|
||||
xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply(dpy, xcb_get_geometry(dpy, win), NULL);
|
||||
if (geo != NULL) {
|
||||
uint16_t width = geo->width + 2 * geo->border_width;
|
||||
uint16_t height = geo->height + 2 * geo->border_width;
|
||||
window_move_resize(motion_recorder.id, geo->x, geo->y, width, height);
|
||||
window_above(motion_recorder.id, win);
|
||||
window_show(motion_recorder.id);
|
||||
motion_recorder.enabled = true;
|
||||
}
|
||||
free(geo);
|
||||
}
|
||||
|
||||
void disable_motion_recorder(void)
|
||||
{
|
||||
if (!motion_recorder.enabled) {
|
||||
return;
|
||||
}
|
||||
window_hide(motion_recorder.id);
|
||||
motion_recorder.enabled = false;
|
||||
}
|
||||
|
||||
void window_border_width(xcb_window_t win, uint32_t bw)
|
||||
|
@ -788,11 +821,13 @@ void window_stack(xcb_window_t w1, xcb_window_t w2, uint32_t mode)
|
|||
xcb_configure_window(dpy, w1, mask, values);
|
||||
}
|
||||
|
||||
/* Stack w1 above w2 */
|
||||
void window_above(xcb_window_t w1, xcb_window_t w2)
|
||||
{
|
||||
window_stack(w1, w2, XCB_STACK_MODE_ABOVE);
|
||||
}
|
||||
|
||||
/* Stack w1 below w2 */
|
||||
void window_below(xcb_window_t w1, xcb_window_t w2)
|
||||
{
|
||||
window_stack(w1, w2, XCB_STACK_MODE_BELOW);
|
||||
|
|
|
@ -53,6 +53,9 @@ bool move_client(coordinates_t *loc, int dx, int dy);
|
|||
bool resize_client(coordinates_t *loc, resize_handle_t rh, int dx, int dy);
|
||||
void apply_size_hints(client_t *c, uint16_t *width, uint16_t *height);
|
||||
void query_pointer(xcb_window_t *win, xcb_point_t *pt);
|
||||
void update_motion_recorder(void);
|
||||
void enable_motion_recorder(xcb_window_t win);
|
||||
void disable_motion_recorder(void);
|
||||
void window_border_width(xcb_window_t win, uint32_t bw);
|
||||
void window_move(xcb_window_t win, int16_t x, int16_t y);
|
||||
void window_resize(xcb_window_t win, uint16_t w, uint16_t h);
|
||||
|
|
Loading…
Add table
Reference in a new issue