VERSION = 0.3
CC = gcc
-LIBS = -lm -lxcb -lxcb-icccm -lxcb-ewmh -lxcb-xinerama
+LIBS = -lm -lxcb -lxcb-keysyms -lxcb-icccm -lxcb-ewmh -lxcb-xinerama
CFLAGS = -std=c99 -pedantic -Wall -Wextra -DVERSION=\"$(VERSION)\"
LDFLAGS = $(LIBS)
BINPREFIX = $(PREFIX)/bin
MANPREFIX = $(PREFIX)/share/man
-WM_SRC = bspwm.c events.c messages.c ewmh.c settings.c helpers.c tree.c types.c rules.c window.c
+WM_SRC = bspwm.c events.c messages.c buttons.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)
button_modifier
The modifier mask used for mouse bindings (possible values: 'shift', 'control', 'lock', 'mod1' ... 'mod5').
- numlock_modifier
- The modifier holding Num_Lock (cf. xmodmap).
-
- capslock_modifier
- The modifier holding Lock.
-
borderless_monocle
Whether to remove borders for tiled windows in monocle mode.
- libxcb
- xcb-util
- xcb-util-wm
+- xcb-util-keysyms
## Installation
The modifier mask used for mouse bindings (possible values:
.BR shift ", " control ", " lock ", " mod1 " ... " mod5 ).
.TP
-.I numlock_modifier
-The modifier holding Num_Lock (cf.
-.BR xmodmap (1)).
-.TP
-.I capslock_modifier
-The modifier holding Lock.
-.TP
.I borderless_monocle
Whether to remove borders for tiled windows in monocle mode.
.TP
#include <xcb/xcb.h>
#include <xcb/xcb_event.h>
#include <xcb/xcb_ewmh.h>
+#include <xcb/xcb_keysyms.h>
#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)
{
uint32_t values[] = {ROOT_EVENT_MASK};
- xcb_generic_error_t *e = xcb_request_check(dpy, xcb_change_window_attributes_checked(dpy, screen->root, XCB_CW_EVENT_MASK, values));
+ xcb_generic_error_t *e = xcb_request_check(dpy, xcb_change_window_attributes_checked(dpy, root, XCB_CW_EVENT_MASK, values));
if (e != NULL) {
xcb_disconnect(dpy);
err("another wm is already running\n");
}
}
-void handle_buttons(bool grab)
-{
- uint8_t buts[] = {XCB_BUTTON_INDEX_1, XCB_BUTTON_INDEX_2, XCB_BUTTON_INDEX_3};
- uint16_t mods[] = {button_modifier, button_modifier | numlock_modifier, button_modifier | capslock_modifier, button_modifier | numlock_modifier | capslock_modifier};
-
- for (unsigned int i = 0; i < LENGTH(buts); i++) {
- uint8_t b = buts[i];
- for (unsigned int j = 0; j < LENGTH(mods); j++) {
- uint16_t m = mods[j];
- if (grab)
- xcb_grab_button(dpy, false, screen->root, XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, b, m);
- else
- xcb_ungrab_button(dpy, b, screen->root, m);
- }
- }
-}
-
-void grab_buttons(void)
-{
- handle_buttons(true);
-}
-
-void ungrab_buttons(void)
-{
- handle_buttons(false);
-}
-
void setup(void)
{
ewmh_init();
screen = xcb_setup_roots_iterator(xcb_get_setup(dpy)).data;
if (!screen)
err("can't acquire screen\n");
+ root = screen->root;
register_events();
screen_width = screen->width_in_pixels;
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);
last_entered = XCB_NONE;
load_settings();
run_autostart();
+ get_lock_fields();
grab_buttons();
ewmh_update_wm_name();
FD_SET(sock_fd, &descriptors);
FD_SET(dpy_fd, &descriptors);
- if (select(sel, &descriptors, NULL, NULL, NULL)) {
+ if (select(sel, &descriptors, NULL, NULL, NULL) > 0) {
if (FD_ISSET(sock_fd, &descriptors)) {
ret_fd = accept(sock_fd, NULL, 0);
unsigned int client_uid;
unsigned int rule_uid;
xcb_screen_t *screen;
+xcb_window_t root;
uint8_t root_depth;
FILE *status_fifo;
monitor_t *mon_tail;
rule_t *rule_head;
rule_t *rule_tail;
+
pointer_state_t *frozen_pointer;
xcb_point_t pointer_position;
xcb_window_t last_entered;
+
int exit_status;
bool visible;
--- /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 = modfield_from_keysym(XK_Caps_Lock);
+ scroll_lock = modfield_from_keysym(XK_Scroll_Lock);
+ if (caps_lock == XCB_NO_SYMBOL)
+ caps_lock = XCB_MOD_MASK_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 <stdlib.h>
#include <string.h>
#include <xcb/xcb.h>
+#include <xcb/xcb_keysyms.h>
#include <xcb/xcb_event.h>
#include <xcb/xcb_icccm.h>
#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;
}
}
+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;
frozen_pointer->corner = TOP_LEFT;
}
}
- xcb_grab_pointer(dpy, false, screen->root, XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME);
+ xcb_grab_pointer(dpy, false, root, XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, XCB_CURRENT_TIME);
break;
}
}
void configure_request(xcb_generic_event_t *);
void client_message(xcb_generic_event_t *);
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 motion_notify(xcb_generic_event_t *);
void ewmh_update_wm_name(void)
{
if (wm_name != NULL)
- xcb_ewmh_set_wm_name(ewmh, screen->root, strlen(wm_name), wm_name);
+ xcb_ewmh_set_wm_name(ewmh, root, strlen(wm_name), wm_name);
}
void ewmh_update_active_window(void)
void get_pointer_position(xcb_point_t *pos)
{
- xcb_query_pointer_reply_t *qpr = xcb_query_pointer_reply(dpy, xcb_query_pointer(dpy, screen->root), NULL);
+ 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);
grab_buttons();
}
return;
- } else if (strcmp(name, "numlock_modifier") == 0) {
- unsigned int m;
- if (parse_modifier_mask(value, &m)) {
- ungrab_buttons();
- numlock_modifier = m;
- grab_buttons();
- }
- return;
- } else if (strcmp(name, "capslock_modifier") == 0) {
- unsigned int m;
- if (parse_modifier_mask(value, &m)) {
- ungrab_buttons();
- capslock_modifier = m;
- grab_buttons();
- }
- return;
} else {
snprintf(rsp, BUFSIZ, "unknown setting: %s", name);
return;
snprintf(rsp, BUFSIZ, "%s", wm_name);
else if (strcmp(name, "button_modifier") == 0)
print_modifier_mask(rsp, button_modifier);
- else if (strcmp(name, "numlock_modifier") == 0)
- print_modifier_mask(rsp, numlock_modifier);
- else if (strcmp(name, "capslock_modifier") == 0)
- print_modifier_mask(rsp, capslock_modifier);
else
snprintf(rsp, BUFSIZ, "unknown setting: %s", name);
}
strncpy(wm_name, WM_NAME, sizeof(wm_name));
button_modifier = BUTTON_MODIFIER;
- numlock_modifier = NUMLOCK_MODIFIER;
- capslock_modifier = CAPSLOCK_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 NUMLOCK_MODIFIER XCB_MOD_MASK_2
-#define CAPSLOCK_MODIFIER XCB_MOD_MASK_LOCK
#define FOCUSED_BORDER_COLOR "#7D7F8A"
#define ACTIVE_BORDER_COLOR "#7D7F8A"
char wm_name[MAXLEN];
unsigned int button_modifier;
-unsigned int numlock_modifier;
-unsigned int capslock_modifier;
void load_settings(void);
void run_autostart(void);
void adopt_orphans(void)
{
- xcb_query_tree_reply_t *qtr = xcb_query_tree_reply(dpy, xcb_query_tree(dpy, screen->root), NULL);
+ xcb_query_tree_reply_t *qtr = xcb_query_tree_reply(dpy, xcb_query_tree(dpy, root), NULL);
if (qtr == NULL)
return;
int len = xcb_query_tree_children_length(qtr);
void window_set_visibility(xcb_window_t win, bool visible) {
uint32_t values_off[] = {ROOT_EVENT_MASK & ~XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY};
uint32_t values_on[] = {ROOT_EVENT_MASK};
- xcb_change_window_attributes(dpy, screen->root, XCB_CW_EVENT_MASK, values_off);
+ xcb_change_window_attributes(dpy, root, XCB_CW_EVENT_MASK, values_off);
if (visible)
xcb_map_window(dpy, win);
else
xcb_unmap_window(dpy, win);
- xcb_change_window_attributes(dpy, screen->root, XCB_CW_EVENT_MASK, values_on);
+ xcb_change_window_attributes(dpy, root, XCB_CW_EVENT_MASK, values_on);
}
void window_hide(xcb_window_t win)