The code related to mouse buttons handling is gone.
Mouse bindings must now be created via sxhkd.
-VERSION = 0.3
+VERSION = 0.4
CC = gcc
-LIBS = -lm -lxcb -lxcb-keysyms -lxcb-icccm -lxcb-ewmh -lxcb-xinerama
+LIBS = -lm -lxcb -lxcb-icccm -lxcb-ewmh -lxcb-xinerama
CFLAGS = -std=c99 -pedantic -Wall -Wextra -D_POSIX_C_SOURCE=2 -DVERSION=\"$(VERSION)\"
LDFLAGS = $(LIBS)
BINPREFIX = $(PREFIX)/bin
MANPREFIX = $(PREFIX)/share/man
-WM_SRC = bspwm.c events.c messages.c buttons.c ewmh.c settings.c helpers.c tree.c types.c rules.c window.c
+WM_SRC = bspwm.c events.c messages.c ewmh.c settings.c helpers.c tree.c types.c rules.c window.c
CL_SRC = bspc.c helpers.c
WM_OBJ = $(WM_SRC:.c=.o)
circulate forward|backward
Circulate the leaves in the given direction.
+ mouse move|resize|focus
+ Perform the given mouse action on the window under the pointer.
+
toggle_fullscreen
Toggle the fullscreen state of the current window.
wm_name
The value that shall be used for the _NET_WM_NAME property of the root window.
- button_modifier
- The modifier mask used for mouse bindings (possible values: 'shift', 'control', 'lock', 'mod1' ... 'mod5').
-
borderless_monocle
Whether to remove borders for tiled windows in monocle mode.
adaptative_raise
Prevent floating windows from being raised when they might cover other floating windows.
-## Mouse Bindings
-
- button_modifier + left mouse button
- Move the window under the pointer.
-
- button_modifier + middle mouse button
- Focus the window under the pointer.
-
- button_modifier + right mouse button
- Resize the window under the pointer (by moving one of its four corners).
-
## Key Features
- Configured and controlled through messages
- libxcb
- xcb-util
- xcb-util-wm
-- xcb-util-keysyms
## Installation
.BI circulate " forward|backward"
Circulate the leaves in the given direction.
.TP
+.BI mouse " move|resize|focus"
+Perform the given mouse action on the window under the pointer.
+.TP
.BI toggle_fullscreen
Toggle the fullscreen state of the current window.
.TP
.B _NET_WM_NAME
property of the root window.
.TP
-.I button_modifier
-The modifier mask used for mouse bindings (possible values:
-.BR shift ", " control ", " lock ", " mod1 " ... " mod5 ).
-.TP
.I borderless_monocle
Whether to remove borders for tiled windows in monocle mode.
.TP
.TP
.I adaptative_raise
Prevent floating windows from being raised when they might cover other floating windows.
-.SH MOUSE BINDINGS
-.TP
-.I button_modifier + left mouse button
-Move the window under the pointer.
-.TP
-.I button_modifier + middle mouse button
-Focus the window under the pointer.
-.TP
-.I button_modifier + right mouse button
-Resize the window under the pointer (by moving one of its four corners).
.SH AUTHOR
.EX
Bastien Dejean <baskerville at lavabit.com>
#include <xcb/xinerama.h>
#include "types.h"
#include "settings.h"
-#include "buttons.h"
#include "messages.h"
#include "rules.h"
#include "events.h"
while (rule_head != NULL)
remove_rule(rule_head);
free(frozen_pointer);
- xcb_key_symbols_free(symbols);
}
void register_events(void)
ewmh_update_desktop_names();
ewmh_update_current_desktop();
rule_head = rule_tail = NULL;
- symbols = xcb_key_symbols_alloc(dpy);
frozen_pointer = make_pointer_state();
- get_pointer_position(&pointer_position);
+ update_pointer_position(&pointer_position);
last_entered = XCB_NONE;
split_mode = MODE_AUTOMATIC;
visible = true;
load_settings();
run_autostart();
- get_lock_fields();
- grab_buttons();
ewmh_update_wm_name();
while (running) {
bool running;
void register_events(void);
-void handle_buttons(bool);
-void grab_buttons(void);
-void ungrab_buttons(void);
void setup(void);
void cleanup(void);
void quit(void);
+++ /dev/null
-#include <stdlib.h>
-#include <xcb/xcb_keysyms.h>
-#include "settings.h"
-#include "bspwm.h"
-#include "helpers.h"
-#include "types.h"
-#include "buttons.h"
-
-void grab_buttons(void)
-{
-#define GRAB(b, m) xcb_grab_button(dpy, false, root, XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, b, m)
- uint8_t buttons[] = {XCB_BUTTON_INDEX_1, XCB_BUTTON_INDEX_2, XCB_BUTTON_INDEX_3};
- for (unsigned int i = 0; i < LENGTH(buttons); i++) {
- uint8_t button = buttons[i];
- GRAB(button, button_modifier);
- if (num_lock != XCB_NO_SYMBOL && caps_lock != XCB_NO_SYMBOL && scroll_lock != XCB_NO_SYMBOL)
- GRAB(button, button_modifier | num_lock | caps_lock | scroll_lock);
- if (num_lock != XCB_NO_SYMBOL && caps_lock != XCB_NO_SYMBOL)
- GRAB(button, button_modifier | num_lock | caps_lock);
- if (caps_lock != XCB_NO_SYMBOL && scroll_lock != XCB_NO_SYMBOL)
- GRAB(button, button_modifier | caps_lock | scroll_lock);
- if (num_lock != XCB_NO_SYMBOL && scroll_lock != XCB_NO_SYMBOL)
- GRAB(button, button_modifier | num_lock | scroll_lock);
- if (num_lock != XCB_NO_SYMBOL)
- GRAB(button, button_modifier | num_lock);
- if (caps_lock != XCB_NO_SYMBOL)
- GRAB(button, button_modifier | caps_lock);
- if (scroll_lock != XCB_NO_SYMBOL)
- GRAB(button, button_modifier | scroll_lock);
- }
-#undef GRAB
-}
-
-void ungrab_buttons(void)
-{
- xcb_ungrab_button(dpy, XCB_BUTTON_INDEX_ANY, root, XCB_MOD_MASK_ANY);
-}
-
-void get_lock_fields(void)
-{
- num_lock = modfield_from_keysym(XK_Num_Lock);
- caps_lock = XCB_MOD_MASK_LOCK;
- scroll_lock = modfield_from_keysym(XK_Scroll_Lock);
- PRINTF("lock fields %u %u %u\n", num_lock, caps_lock, scroll_lock);
-}
-
-int16_t modfield_from_keysym(xcb_keysym_t keysym)
-{
- uint16_t modfield = 0;
- xcb_keycode_t *keycodes = NULL, *mod_keycodes = NULL;
- xcb_get_modifier_mapping_reply_t *reply = NULL;
- if ((keycodes = xcb_key_symbols_get_keycode(symbols, keysym)) != NULL) {
- if ((reply = xcb_get_modifier_mapping_reply(dpy, xcb_get_modifier_mapping(dpy), NULL)) != NULL) {
- if ((mod_keycodes = xcb_get_modifier_mapping_keycodes(reply)) != NULL) {
- unsigned int num_mod = xcb_get_modifier_mapping_keycodes_length(reply) / reply->keycodes_per_modifier;
- for (unsigned int i = 0; i < num_mod; i++) {
- for (unsigned int j = 0; j < reply->keycodes_per_modifier; j++) {
- xcb_keycode_t mk = mod_keycodes[i * reply->keycodes_per_modifier + j];
- if (mk == XCB_NO_SYMBOL)
- continue;
- for (xcb_keycode_t *k = keycodes; *k != XCB_NO_SYMBOL; k++)
- if (*k == mk)
- modfield |= (1 << i);
- }
- }
-
- }
- }
- }
- free(keycodes);
- free(reply);
- return modfield;
-}
+++ /dev/null
-#ifndef _BUTTONS_H
-#define _BUTTONS_H
-
-#define XK_Num_Lock 0xff7f
-#define XK_Caps_Lock 0xffe5
-#define XK_Scroll_Lock 0xff14
-
-uint16_t num_lock;
-uint16_t caps_lock;
-uint16_t scroll_lock;
-
-xcb_key_symbols_t *symbols;
-
-void grab_buttons(void);
-void ungrab_buttons(void);
-void get_lock_fields(void);
-int16_t modfield_from_keysym(xcb_keysym_t);
-
-#endif
#include "types.h"
#include "bspwm.h"
#include "settings.h"
-#include "buttons.h"
#include "helpers.h"
#include "window.h"
#include "events.h"
case XCB_PROPERTY_NOTIFY:
property_notify(evt);
break;
- case XCB_MAPPING_NOTIFY:
- mapping_notify(evt);
- break;
case XCB_ENTER_NOTIFY:
enter_notify(evt);
break;
- case XCB_BUTTON_PRESS:
- button_press(evt);
- break;
case XCB_MOTION_NOTIFY:
motion_notify(evt);
break;
}
}
-void mapping_notify(xcb_generic_event_t *evt)
-{
- xcb_mapping_notify_event_t *e = (xcb_mapping_notify_event_t *) evt;
- if (e->count > 0) {
- ungrab_buttons();
- xcb_refresh_keyboard_mapping(symbols, e);
- get_lock_fields();
- grab_buttons();
- }
-}
-
void enter_notify(xcb_generic_event_t *evt)
{
xcb_enter_notify_event_t *e = (xcb_enter_notify_event_t *) evt;
}
}
-void button_press(xcb_generic_event_t *evt)
+void mouse_do(mouse_action_t mac)
{
- xcb_button_press_event_t *e = (xcb_button_press_event_t *) evt;
- xcb_window_t win = e->child;
+ PRINTF("mouse action %u\n", mac);
- PRINTF("button press %u %u %X\n", e->detail, e->state, win);
+ xcb_window_t win;
+ 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};
+ win = qpr->child;
+ free(qpr);
+ } else {
+ return;
+ }
window_location_t loc;
if (locate_window(win, &loc)) {
client_t *c = loc.node->client;
- switch (e->detail) {
- case XCB_BUTTON_INDEX_2:
+ switch (mac) {
+ case MOUSE_FOCUS:
focus_node(loc.monitor, loc.desktop, loc.node, true);
break;
- case XCB_BUTTON_INDEX_1:
- case XCB_BUTTON_INDEX_3:
+ case MOUSE_MOVE:
+ case MOUSE_RESIZE:
if (is_tiled(loc.node->client)) {
loc.node->client->floating_rectangle = loc.node->client->tiled_rectangle;
toggle_floating(loc.node);
frozen_pointer->desktop = loc.desktop;
frozen_pointer->node = loc.node;
frozen_pointer->rectangle = c->floating_rectangle;
- frozen_pointer->position = (xcb_point_t) {e->root_x, e->root_y};
- frozen_pointer->button = e->detail;
- if (e->detail == XCB_BUTTON_INDEX_3) {
+ frozen_pointer->position = pos;
+ frozen_pointer->action = mac;
+ if (mac == MOUSE_RESIZE) {
int16_t mid_x, mid_y;
mid_x = c->floating_rectangle.x + (c->floating_rectangle.width / 2);
mid_y = c->floating_rectangle.y + (c->floating_rectangle.height / 2);
- if (e->root_x > mid_x) {
- if (e->root_y > mid_y)
+ if (pos.x > mid_x) {
+ if (pos.y > mid_y)
frozen_pointer->corner = BOTTOM_RIGHT;
else
frozen_pointer->corner = TOP_RIGHT;
} else {
- if (e->root_y > mid_y)
+ if (pos.y > mid_y)
frozen_pointer->corner = BOTTOM_LEFT;
else
frozen_pointer->corner = TOP_LEFT;
delta_x = e->root_x - frozen_pointer->position.x;
delta_y = e->root_y - frozen_pointer->position.y;
- switch (frozen_pointer->button) {
- case XCB_BUTTON_INDEX_1:
+ switch (frozen_pointer->action) {
+ case MOUSE_MOVE:
x = rect.x + delta_x;
y = rect.y + delta_y;
window_move(win, x, y);
break;
- case XCB_BUTTON_INDEX_3:
+ case MOUSE_RESIZE:
switch (frozen_pointer->corner) {
case TOP_LEFT:
x = rect.x + delta_x;
c->floating_rectangle = (xcb_rectangle_t) {x, y, width, height};
window_draw_border(n, d->focus == n, mon == m);
break;
+ case MOUSE_FOCUS:
+ break;
}
}
void property_notify(xcb_generic_event_t *);
void mapping_notify(xcb_generic_event_t *);
void enter_notify(xcb_generic_event_t *);
-void button_press(xcb_generic_event_t *);
+void mouse_do(mouse_action_t);
void motion_notify(xcb_generic_event_t *);
void button_release(void);
void handle_state(monitor_t *, desktop_t *, node_t *, xcb_atom_t, unsigned int);
return pxl;
}
-void get_pointer_position(xcb_point_t *pos)
+void update_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) {
__attribute__((noreturn))
void err(char *, ...);
uint32_t get_color(char *);
-void get_pointer_position(xcb_point_t *);
+void update_pointer_position(xcb_point_t *);
#endif
#include "ewmh.h"
#include "helpers.h"
#include "window.h"
+#include "events.h"
#include "tree.h"
#include "rules.h"
rotate_tree(mon->desk->root, r);
}
}
+ } else if (strcmp(cmd, "mouse") == 0) {
+ char *mac = strtok(NULL, TOK_SEP);
+ if (mac != NULL) {
+ mouse_action_t a;
+ if (parse_mouse_action(mac, &a))
+ mouse_do(a);
+ }
} else if (strcmp(cmd, "layout") == 0) {
char *lyt = strtok(NULL, TOK_SEP);
if (lyt != NULL) {
strncpy(wm_name, value, sizeof(wm_name));
ewmh_update_wm_name();
return;
- } else if (strcmp(name, "button_modifier") == 0) {
- unsigned int m;
- if (parse_modifier_mask(value, &m)) {
- ungrab_buttons();
- button_modifier = m;
- grab_buttons();
- }
- return;
} else {
snprintf(rsp, BUFSIZ, "unknown setting: %s", name);
return;
snprintf(rsp, BUFSIZ, "%s", BOOLSTR(adaptative_raise));
else if (strcmp(name, "wm_name") == 0)
snprintf(rsp, BUFSIZ, "%s", wm_name);
- else if (strcmp(name, "button_modifier") == 0)
- print_modifier_mask(rsp, button_modifier);
else
snprintf(rsp, BUFSIZ, "unknown setting: %s", name);
}
return false;
}
-bool parse_modifier_mask(char *s, unsigned int *m)
+bool parse_mouse_action(char *s, mouse_action_t *a)
{
- if (strcmp(s, "shift") == 0) {
- *m = XCB_MOD_MASK_SHIFT;
- return true;
- } else if (strcmp(s, "control") == 0) {
- *m = XCB_MOD_MASK_CONTROL;
- return true;
- } else if (strcmp(s, "lock") == 0) {
- *m = XCB_MOD_MASK_LOCK;
- return true;
- } else if (strcmp(s, "mod1") == 0) {
- *m = XCB_MOD_MASK_1;
+ if (strcmp(s, "move") == 0) {
+ *a = MOUSE_MOVE;
return true;
- } else if (strcmp(s, "mod2") == 0) {
- *m = XCB_MOD_MASK_2;
+ } else if (strcmp(s, "focus") == 0) {
+ *a = MOUSE_FOCUS;
return true;
- } else if (strcmp(s, "mod3") == 0) {
- *m = XCB_MOD_MASK_3;
- return true;
- } else if (strcmp(s, "mod4") == 0) {
- *m = XCB_MOD_MASK_4;
- return true;
- } else if (strcmp(s, "mod5") == 0) {
- *m = XCB_MOD_MASK_5;
+ } else if (strcmp(s, "resize") == 0) {
+ *a = MOUSE_RESIZE;
return true;
}
return false;
}
-
-void print_modifier_mask(char *s, unsigned int m)
-{
- switch(m) {
- case XCB_MOD_MASK_SHIFT:
- snprintf(s, BUFSIZ, "shift");
- break;
- case XCB_MOD_MASK_CONTROL:
- snprintf(s, BUFSIZ, "control");
- break;
- case XCB_MOD_MASK_LOCK:
- snprintf(s, BUFSIZ, "lock");
- break;
- case XCB_MOD_MASK_1:
- snprintf(s, BUFSIZ, "mod1");
- break;
- case XCB_MOD_MASK_2:
- snprintf(s, BUFSIZ, "mod2");
- break;
- case XCB_MOD_MASK_3:
- snprintf(s, BUFSIZ, "mod3");
- break;
- case XCB_MOD_MASK_4:
- snprintf(s, BUFSIZ, "mod4");
- break;
- case XCB_MOD_MASK_5:
- snprintf(s, BUFSIZ, "mod5");
- break;
- }
-}
bool parse_skip_desktop(char *, skip_desktop_t *);
bool parse_rotate(char *, rotate_t *);
bool parse_fence_move(char *, fence_move_t *);
-bool parse_modifier_mask(char *, unsigned int *);
-void print_modifier_mask(char *, unsigned int);
+bool parse_mouse_action(char *, mouse_action_t *);
#endif
urgent_border_color_pxl = get_color(urgent_border_color);
strncpy(wm_name, WM_NAME, sizeof(wm_name));
- button_modifier = BUTTON_MODIFIER;
inner_border_width = INNER_BORDER_WIDTH;
main_border_width = MAIN_BORDER_WIDTH;
#define WM_NAME "bspwm"
#define AUTOSTART_FILE "autostart"
-#define BUTTON_MODIFIER XCB_MOD_MASK_4
#define FOCUSED_BORDER_COLOR "#7D7F8A"
#define ACTIVE_BORDER_COLOR "#7D7F8A"
bool adaptative_raise;
char wm_name[MAXLEN];
-unsigned int button_modifier;
void load_settings(void);
void run_autostart(void);
rect.width -= m->left_padding + m->right_padding + wg;
rect.height -= m->top_padding + m->bottom_padding + wg;
if (focus_follows_mouse)
- get_pointer_position(&pointer_position);
+ update_pointer_position(&pointer_position);
apply_layout(m, d, d->root, rect, rect);
}
window_draw_border(n, true, true);
}
if (focus_follows_mouse)
- get_pointer_position(&pointer_position);
+ update_pointer_position(&pointer_position);
xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, n->client->window, XCB_CURRENT_TIME);
}
BOTTOM_RIGHT
} corner_t;
+typedef enum {
+ MOUSE_MOVE,
+ MOUSE_RESIZE,
+ MOUSE_FOCUS
+} mouse_action_t;
+
typedef struct {
xcb_window_t window;
unsigned int uid;
typedef struct {
xcb_point_t position;
- xcb_button_t button;
+ mouse_action_t action;
xcb_rectangle_t rectangle;
monitor_t *monitor;
desktop_t *desktop;