/*
- * Copyright (c) 2009-2012 Marco Peereboom <marco@peereboom.us>
+ * Copyright (c) 2009-2015 Marco Peereboom <marco@peereboom.us>
* Copyright (c) 2009-2011 Ryan McBride <mcbride@countersiege.com>
* Copyright (c) 2009 Darrin Chandler <dwchandler@stilyagin.com>
* Copyright (c) 2009 Pierre-Yves Ritschard <pyr@spootnik.org>
* Copyright (c) 2010 Tuukka Kataja <stuge@xor.fi>
* Copyright (c) 2011 Jason L. Wright <jason@thought.net>
- * Copyright (c) 2011-2014 Reginald Kennedy <rk@rejii.com>
+ * Copyright (c) 2011-2015 Reginald Kennedy <rk@rejii.com>
* Copyright (c) 2011-2012 Lawrence Teo <lteo@lteo.net>
* Copyright (c) 2011-2012 Tiago Cunha <tcunha@gmx.com>
- * Copyright (c) 2012-2013 David Hill <dhill@mindcry.org>
+ * Copyright (c) 2012-2015 David Hill <dhill@mindcry.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
#include <ctype.h>
#include <err.h>
#include <errno.h>
+#include <poll.h>
#include <fcntl.h>
#include <locale.h>
#include <paths.h>
int font_adjusted = 0;
unsigned int mod_key = MODKEY;
bool warp_pointer = false;
+unsigned int mouse_button_move = XCB_BUTTON_INDEX_1;
+unsigned int mouse_button_resize = XCB_BUTTON_INDEX_3;
/* dmenu search */
struct swm_region *search_r;
bool stack_enabled = true;
bool clock_enabled = true;
bool iconic_enabled = false;
+bool maximize_hide_bar = false;
bool urgent_enabled = false;
bool urgent_collapse = false;
char *clock_format = NULL;
#define SWM_ARG_ID_FLIPLAYOUT (24)
#define SWM_ARG_ID_STACKRESET (30)
#define SWM_ARG_ID_STACKINIT (31)
+#define SWM_ARG_ID_STACKBALANCE (32)
#define SWM_ARG_ID_CYCLEWS_UP (40)
#define SWM_ARG_ID_CYCLEWS_DOWN (41)
#define SWM_ARG_ID_CYCLERG_UP (42)
#define SWM_Q_OBEYAPPFOCUSREQ (1<<8) /* Focus when applications ask. */
#define SWM_Q_IGNOREPID (1<<9) /* Ignore PID when determining ws. */
#define SWM_Q_IGNORESPAWNWS (1<<10) /* Ignore _SWM_WS when managing win. */
+#define SWM_Q_NOFOCUSCYCLE (1<<11) /* Remove from normal focus cycle. */
};
TAILQ_HEAD(quirk_list, quirk);
struct quirk_list quirks = TAILQ_HEAD_INITIALIZER(quirks);
KF_STACK_INC,
KF_STACK_DEC,
KF_STACK_RESET,
+ KF_STACK_BALANCE,
KF_SWAP_MAIN,
KF_SWAP_NEXT,
KF_SWAP_PREV,
int setconfbinding(const char *, const char *, int);
int setconfcolor(const char *, const char *, int);
int setconfmodkey(const char *, const char *, int);
+int setconfmousebuttonmove(const char *, const char *, int);
+int setconfmousebuttonresize(const char *, const char *, int);
int setconfquirk(const char *, const char *, int);
int setconfregion(const char *, const char *, int);
int setconfspawn(const char *, const char *, int);
void updatenumlockmask(void);
void update_floater(struct ws_win *);
void update_modkey(unsigned int);
+unsigned char update_mousebutton(unsigned char, unsigned int);
void update_win_stacking(struct ws_win *);
void update_window(struct ws_win *);
void update_window_color(struct ws_win *);
for (i = 0; i < num_screens; i++)
for (j = 0; j < workspace_limit; j++)
TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
- urgent[j] = get_urgent(win);
+ if (get_urgent(win))
+ urgent[j] = true;
for (i = 0; i < workspace_limit; i++) {
if (urgent[i]) {
} while (winfocus && (ICONIC(winfocus) ||
winfocus->id == cur_focus->transient ||
(cur_focus->transient != XCB_WINDOW_NONE &&
- winfocus->transient == cur_focus->transient)));
+ winfocus->transient == cur_focus->transient) ||
+ (winfocus->quirks & SWM_Q_NOFOCUSCYCLE)));
break;
case SWM_ARG_ID_FOCUSNEXT:
if (cur_focus == NULL)
} while (winfocus && (ICONIC(winfocus) ||
winfocus->id == cur_focus->transient ||
(cur_focus->transient != XCB_WINDOW_NONE &&
- winfocus->transient == cur_focus->transient)));
+ winfocus->transient == cur_focus->transient) ||
+ (winfocus->quirks & SWM_Q_NOFOCUSCYCLE)));
break;
case SWM_ARG_ID_FOCUSMAIN:
if (cur_focus == NULL)
win->g = r->g;
- if (bar_enabled && ws->bar_enabled) {
+ if (bar_enabled && ws->bar_enabled && !maximize_hide_bar) {
if (!bar_at_bottom)
Y(win) += bar_height;
HEIGHT(win) -= bar_height;
ws->l_state.vertical_mwin = 1;
ws->l_state.vertical_stacks = 1;
break;
+ case SWM_ARG_ID_STACKBALANCE:
+ ws->l_state.vertical_msize = SWM_V_SLICE / (ws->l_state.vertical_stacks + 1);
+ break;
case SWM_ARG_ID_MASTERSHRINK:
if (ws->l_state.vertical_msize > 1)
ws->l_state.vertical_msize--;
ws->l_state.horizontal_msize = SWM_H_SLICE / 2;
ws->l_state.horizontal_stacks = 1;
break;
+ case SWM_ARG_ID_STACKBALANCE:
+ ws->l_state.horizontal_msize = SWM_H_SLICE / (ws->l_state.horizontal_stacks + 1);
+ break;
case SWM_ARG_ID_MASTERSHRINK:
if (ws->l_state.horizontal_msize > 1)
ws->l_state.horizontal_msize--;
{ "stack_inc", stack_config, {.id = SWM_ARG_ID_STACKINC} },
{ "stack_dec", stack_config, {.id = SWM_ARG_ID_STACKDEC} },
{ "stack_reset", stack_config, {.id = SWM_ARG_ID_STACKRESET} },
+ { "stack_balance", stack_config, {.id = SWM_ARG_ID_STACKBALANCE} },
{ "swap_main", swapwin, {.id = SWM_ARG_ID_SWAPMAIN} },
{ "swap_next", swapwin, {.id = SWM_ARG_ID_SWAPNEXT} },
{ "swap_prev", swapwin, {.id = SWM_ARG_ID_SWAPPREV} },
buttons[i].mask = mod;
}
+unsigned char
+update_mousebutton(unsigned char type, unsigned int but)
+{
+ int i;
+
+ switch (type) {
+ case 0:
+ mouse_button_move = but;
+ break;
+ case 1:
+ mouse_button_resize = but;
+ break;
+ }
+
+ for (i = 0; i < LENGTH(buttons); i++) {
+ if (buttons[i].func == move)
+ buttons[i].button = mouse_button_move;
+
+ if (buttons[i].func == resize)
+ buttons[i].button = mouse_button_resize;
+ }
+
+ return(1);
+}
+
int
spawn_expand(struct swm_region *r, union arg *args, const char *spawn_name,
char ***ret_args)
*mod |= XCB_MOD_MASK_3;
else if (strncmp(name, "Mod4", SWM_MODNAME_SIZE) == 0)
*mod |= XCB_MOD_MASK_4;
+ else if (strncmp(name, "Mod5", SWM_MODNAME_SIZE) == 0)
+ *mod |= XCB_MOD_MASK_5;
else if (strncasecmp(name, "SHIFT", SWM_MODNAME_SIZE) == 0)
*mod |= XCB_MOD_MASK_SHIFT;
else if (strncasecmp(name, "CONTROL", SWM_MODNAME_SIZE) == 0)
setkeybinding(MODKEY_SHIFT, XK_comma, KF_STACK_INC, NULL);
setkeybinding(MODKEY_SHIFT, XK_period, KF_STACK_DEC, NULL);
setkeybinding(MODKEY_SHIFT, XK_space, KF_STACK_RESET, NULL);
+ setkeybinding(MODKEY_SHIFT, XK_h, KF_STACK_BALANCE, NULL);
setkeybinding(MODKEY, XK_Return, KF_SWAP_MAIN, NULL);
setkeybinding(MODKEY_SHIFT, XK_j, KF_SWAP_NEXT, NULL);
setkeybinding(MODKEY_SHIFT, XK_k, KF_SWAP_PREV, NULL);
"OBEYAPPFOCUSREQ",
"IGNOREPID",
"IGNORESPAWNWS",
+ "NOFOCUSCYCLE",
};
/* SWM_Q_DELIM: retain '|' for back compat for now (2009-08-11) */
SWM_S_FOCUS_MODE,
SWM_S_ICONIC_ENABLED,
SWM_S_JAVA_WORKAROUND,
+ SWM_S_MAXIMIZE_HIDE_BAR,
SWM_S_REGION_PADDING,
SWM_S_SPAWN_ORDER,
SWM_S_SPAWN_TERM,
case SWM_S_JAVA_WORKAROUND:
java_workaround = (atoi(value) != 0);
break;
+ case SWM_S_MAXIMIZE_HIDE_BAR:
+ maximize_hide_bar = atoi(value);
+ break;
case SWM_S_REGION_PADDING:
region_padding = atoi(value);
if (region_padding < 0)
update_modkey(XCB_MOD_MASK_3);
else if (strncasecmp(value, "Mod4", strlen("Mod4")) == 0)
update_modkey(XCB_MOD_MASK_4);
+ else if (strncasecmp(value, "Mod5", strlen("Mod5")) == 0)
+ update_modkey(XCB_MOD_MASK_5);
else
return (1);
return (0);
}
+int
+setconfmousebuttonmove(const char *selector, const char *value, int flags)
+{
+ /* suppress unused warnings since vars are needed */
+ (void)selector;
+ (void)flags;
+
+ if (strncasecmp(value, "But1", strlen("But1")) == 0) {
+ if (!update_mousebutton(0, XCB_BUTTON_INDEX_1))
+ return (1);
+ } else if (strncasecmp(value, "But2", strlen("But2")) == 0) {
+ if (!update_mousebutton(0, XCB_BUTTON_INDEX_2))
+ return (1);
+ } else if (strncasecmp(value, "But3", strlen("But3")) == 0) {
+ if (!update_mousebutton(0, XCB_BUTTON_INDEX_3))
+ return (1);
+ } else
+ return (1);
+ return (0);
+}
+
+int
+setconfmousebuttonresize(const char *selector, const char *value, int flags)
+{
+ /* suppress unused warnings since vars are needed */
+ (void)selector;
+ (void)flags;
+
+ if (strncasecmp(value, "But1", strlen("But1")) == 0) {
+ if (!update_mousebutton(1, XCB_BUTTON_INDEX_1))
+ return (1);
+ } else if (strncasecmp(value, "But2", strlen("But2")) == 0) {
+ if (!update_mousebutton(1, XCB_BUTTON_INDEX_2))
+ return (1);
+ } else if (strncasecmp(value, "But3", strlen("But3")) == 0) {
+ if (!update_mousebutton(1, XCB_BUTTON_INDEX_3))
+ return (1);
+ } else
+ return (1);
+ return (0);
+}
+
int
setconfcolor(const char *selector, const char *value, int flags)
{
{ "focus_mode", setconfvalue, SWM_S_FOCUS_MODE },
{ "iconic_enabled", setconfvalue, SWM_S_ICONIC_ENABLED },
{ "java_workaround", setconfvalue, SWM_S_JAVA_WORKAROUND },
+ { "maximize_hide_bar", setconfvalue, SWM_S_MAXIMIZE_HIDE_BAR },
{ "keyboard_mapping", setkeymapping, 0 },
{ "layout", setlayout, 0 },
{ "modkey", setconfmodkey, 0 },
+ { "move_button", setconfmousebuttonmove, 0 },
+ { "resize_button", setconfmousebuttonresize, 0 },
{ "program", setconfspawn, 0 },
{ "quirk", setconfquirk, 0 },
{ "region", setconfregion, 0 },
if (line)
free(line);
fclose(config);
+
+ if (mouse_button_move == mouse_button_resize) {
+ add_startup_exception("%s: move and resize mouse buttons match",
+ filename);
+ }
+
DNPRINTF(SWM_D_CONF, "conf_load: end\n");
return (0);
return;
}
+ if (focus_mode != SWM_FOCUS_FOLLOW &&
+ e->mode == XCB_NOTIFY_MODE_UNGRAB) {
+ DNPRINTF(SWM_D_EVENT, "enternotify: ungrab; ignoring.\n");
+ return;
+ }
+
last_event_time = e->time;
if ((win = find_window(e->event)) == NULL) {
int xfd, i, num_screens;
struct sigaction sact;
xcb_generic_event_t *evt;
- struct timeval tv;
- fd_set rd;
- int rd_max;
int num_readable;
+ struct pollfd pfd[2];
bool stdin_ready = false, startup = true;
/* suppress unused warning since var is needed */
TAILQ_FOREACH(r, &screens[i].rl, entry)
r->ws->state = SWM_WS_STATE_MAPPED;
- rd_max = xfd > STDIN_FILENO ? xfd : STDIN_FILENO;
+ memset(&pfd, 0, sizeof(pfd));
+ pfd[0].fd = xfd;
+ pfd[0].events = POLLIN;
+ pfd[1].fd = STDIN_FILENO;
+ pfd[1].events = POLLIN;
while (running) {
while ((evt = xcb_poll_for_event(conn))) {
}
}
- FD_ZERO(&rd);
-
- if (bar_extra)
- FD_SET(STDIN_FILENO, &rd);
-
- FD_SET(xfd, &rd);
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- num_readable = select(rd_max + 1, &rd, NULL, NULL, &tv);
- if (num_readable == -1 && errno != EINTR) {
- DNPRINTF(SWM_D_MISC, "select failed");
- } else if (num_readable > 0 && FD_ISSET(STDIN_FILENO, &rd)) {
+ num_readable = poll(pfd, bar_extra ? 2 : 1, 1000);
+ if (num_readable == -1) {
+ DNPRINTF(SWM_D_MISC, "poll failed: %s", strerror(errno));
+ } else if (num_readable > 0 && bar_extra && pfd[1].revents & POLLIN) {
stdin_ready = true;
}