xcb_timestamp_t last_event_time = 0;
int outputs = 0;
int other_wm;
-int ss_enabled = 0;
int xrandr_support;
int xrandr_eventbase;
unsigned int numlockmask = 0;
char *bar_argv[] = { NULL, NULL };
int bar_pipe[2];
-unsigned char bar_ext[SWM_BAR_MAX];
+char bar_ext[SWM_BAR_MAX];
+char bar_ext_buf[SWM_BAR_MAX];
char bar_vertext[SWM_BAR_MAX];
int bar_version = 0;
-sig_atomic_t bar_alarm = 0;
-int bar_delay = 30;
int bar_enabled = 1;
int bar_border_width = 1;
int bar_at_bottom = 0;
int idx; /* workspace index */
char *name; /* workspace name */
int always_raise; /* raise windows on focus */
+ int bar_enabled; /* bar visibility */
struct layout *cur_layout; /* current layout handlers */
struct ws_win *focus; /* may be NULL */
struct ws_win *focus_prev; /* may be NULL */
#define SWM_ARG_ID_MOVEDOWN (101)
#define SWM_ARG_ID_MOVELEFT (102)
#define SWM_ARG_ID_MOVERIGHT (103)
+#define SWM_ARG_ID_BAR_TOGGLE (110)
+#define SWM_ARG_ID_BAR_TOGGLE_WS (111)
char **argv;
};
{"top_right_corner", XC_top_right_corner, XCB_CURSOR_NONE},
};
+/* spawn */
+struct spawn_prog {
+ TAILQ_ENTRY(spawn_prog) entry;
+ char *name;
+ int argc;
+ char **argv;
+};
+TAILQ_HEAD(spawn_list, spawn_prog);
+struct spawn_list spawns = TAILQ_HEAD_INITIALIZER(spawns);
+
+/* user/key callable function IDs */
+enum keyfuncid {
+ KF_BAR_TOGGLE,
+ KF_BAR_TOGGLE_WS,
+ KF_BUTTON2,
+ KF_CYCLE_LAYOUT,
+ KF_FLIP_LAYOUT,
+ KF_FLOAT_TOGGLE,
+ KF_FOCUS_MAIN,
+ KF_FOCUS_NEXT,
+ KF_FOCUS_PREV,
+ KF_HEIGHT_GROW,
+ KF_HEIGHT_SHRINK,
+ KF_ICONIFY,
+ KF_MASTER_SHRINK,
+ KF_MASTER_GROW,
+ KF_MASTER_ADD,
+ KF_MASTER_DEL,
+ KF_MOVE_DOWN,
+ KF_MOVE_LEFT,
+ KF_MOVE_RIGHT,
+ KF_MOVE_UP,
+ KF_MVWS_1,
+ KF_MVWS_2,
+ KF_MVWS_3,
+ KF_MVWS_4,
+ KF_MVWS_5,
+ KF_MVWS_6,
+ KF_MVWS_7,
+ KF_MVWS_8,
+ KF_MVWS_9,
+ KF_MVWS_10,
+ KF_MVWS_11,
+ KF_MVWS_12,
+ KF_MVWS_13,
+ KF_MVWS_14,
+ KF_MVWS_15,
+ KF_MVWS_16,
+ KF_MVWS_17,
+ KF_MVWS_18,
+ KF_MVWS_19,
+ KF_MVWS_20,
+ KF_MVWS_21,
+ KF_MVWS_22,
+ KF_NAME_WORKSPACE,
+ KF_QUIT,
+ KF_RAISE_TOGGLE,
+ KF_RESTART,
+ KF_SCREEN_NEXT,
+ KF_SCREEN_PREV,
+ KF_SEARCH_WIN,
+ KF_SEARCH_WORKSPACE,
+ KF_SPAWN_CUSTOM,
+ KF_STACK_INC,
+ KF_STACK_DEC,
+ KF_STACK_RESET,
+ KF_SWAP_MAIN,
+ KF_SWAP_NEXT,
+ KF_SWAP_PREV,
+ KF_UNICONIFY,
+ KF_VERSION,
+ KF_WIDTH_GROW,
+ KF_WIDTH_SHRINK,
+ KF_WIND_DEL,
+ KF_WIND_KILL,
+ KF_WS_1,
+ KF_WS_2,
+ KF_WS_3,
+ KF_WS_4,
+ KF_WS_5,
+ KF_WS_6,
+ KF_WS_7,
+ KF_WS_8,
+ KF_WS_9,
+ KF_WS_10,
+ KF_WS_11,
+ KF_WS_12,
+ KF_WS_13,
+ KF_WS_14,
+ KF_WS_15,
+ KF_WS_16,
+ KF_WS_17,
+ KF_WS_18,
+ KF_WS_19,
+ KF_WS_20,
+ KF_WS_21,
+ KF_WS_22,
+ KF_WS_NEXT,
+ KF_WS_NEXT_ALL,
+ KF_WS_PREV,
+ KF_WS_PREV_ALL,
+ KF_WS_PRIOR,
+ KF_DUMPWINS, /* MUST BE LAST */
+ KF_INVALID
+};
+
+struct key {
+ RB_ENTRY(key) entry;
+ unsigned int mod;
+ KeySym keysym;
+ enum keyfuncid funcid;
+ char *spawn_name;
+};
+RB_HEAD(key_tree, key);
+
/* function prototypes */
+void adjust_font(struct ws_win *);
+void bar_class_name(char *, size_t, struct swm_region *);
+void bar_class_title_name(char *, size_t, struct swm_region *);
+void bar_cleanup(struct swm_region *);
+void bar_extra_stop(void);
+void bar_fmt(const char *, char *, struct swm_region *, size_t);
+void bar_fmt_expand(char *, size_t);
+void bar_fmt_print(void);
+void bar_print(struct swm_region *, const char *);
+void bar_print_legacy(struct swm_region *, const char *);
+void bar_refresh(void);
+void bar_replace(char *, char *, struct swm_region *, size_t);
+void bar_replace_pad(char *, int *, size_t);
+char * bar_replace_seq(char *, char *, struct swm_region *, size_t *,
+ size_t);
+void bar_setup(struct swm_region *);
+void bar_title_name(char *, size_t, struct swm_region *);
+void bar_toggle(struct swm_region *, union arg *);
+void bar_update(void);
+void bar_urgent(char *, size_t);
+void bar_window_float(char *, size_t, struct swm_region *);
+void bar_window_name(char *, size_t, struct swm_region *);
+void bar_workspace_name(char *, size_t, struct swm_region *);
void buttonpress(xcb_button_press_event_t *);
void check_conn(void);
+void clear_keys(void);
void clientmessage(xcb_client_message_event_t *);
-int conf_load(char *, int);
+void client_msg(struct ws_win *, xcb_atom_t, xcb_timestamp_t);
+int conf_load(const char *, int);
void configurenotify(xcb_configure_notify_event_t *);
void configurerequest(xcb_configure_request_event_t *);
+void config_win(struct ws_win *, xcb_configure_request_event_t *);
void constrain_window(struct ws_win *, struct swm_region *, int);
+int count_win(struct workspace *, int);
+void cursors_cleanup(void);
+void cursors_load(void);
+void custom_region(char *);
+void cyclescr(struct swm_region *, union arg *);
+void cyclews(struct swm_region *, union arg *);
+void cycle_layout(struct swm_region *, union arg *);
void destroynotify(xcb_destroy_notify_event_t *);
+void dumpwins(struct swm_region *, union arg *);
+int enable_wm(void);
void enternotify(xcb_enter_notify_event_t *);
void event_drain(uint8_t);
void event_error(xcb_generic_error_t *);
void event_handle(xcb_generic_event_t *);
-char *expand_tilde(char *);
+void ewmh_autoquirk(struct ws_win *);
+void ewmh_get_win_state(struct ws_win *);
+int ewmh_set_win_fullscreen(struct ws_win *, int);
+void ewmh_update_actions(struct ws_win *);
+void ewmh_update_win_state(struct ws_win *, xcb_atom_t, long);
+char *expand_tilde(const char *);
void expose(xcb_expose_event_t *);
+void fake_keypress(struct ws_win *, xcb_keysym_t, uint16_t);
+struct pid_e *find_pid(pid_t);
+struct ws_win *find_unmanaged_window(xcb_window_t);
struct ws_win *find_window(xcb_window_t);
+void floating_toggle(struct swm_region *, union arg *);
int floating_toggle_win(struct ws_win *);
void focus(struct swm_region *, union arg *);
-void focus_flush(void);
-struct ws_win *get_focus_magic(struct ws_win *);
-struct ws_win *get_focus_prev(struct ws_win *);
-void focus_win(struct ws_win *);
#ifdef SWM_DEBUG
void focusin(xcb_focus_in_event_t *);
+void focusout(xcb_focus_out_event_t *);
#endif
+void focus_flush(void);
+void focus_win(struct ws_win *);
+void fontset_init(void);
+void free_window(struct ws_win *);
xcb_atom_t get_atom_from_string(const char *);
#ifdef SWM_DEBUG
char *get_atom_name(xcb_atom_t);
+#endif
+struct ws_win *get_focus_magic(struct ws_win *);
+struct ws_win *get_focus_prev(struct ws_win *);
+#ifdef SWM_DEBUG
char *get_notify_detail_label(uint8_t);
char *get_notify_mode_label(uint8_t);
#endif
struct ws_win *get_pointer_win(xcb_window_t);
struct ws_win *get_region_focus(struct swm_region *);
xcb_screen_t *get_screen(int);
+#ifdef SWM_DEBUG
+char *get_stack_mode_name(uint8_t);
+#endif
+int32_t get_swm_iconic(struct ws_win *);
char *get_win_name(xcb_window_t);
+int get_ws_idx(xcb_window_t);
uint32_t getstate(xcb_window_t);
void grabbuttons(struct ws_win *);
+void grabkeys(void);
+void grab_windows(void);
+void iconify(struct swm_region *, union arg *);
+int isxlfd(char *);
void keypress(xcb_key_press_event_t *);
+int key_cmp(struct key *, struct key *);
+void key_insert(unsigned int, KeySym, enum keyfuncid, const char *);
+struct key *key_lookup(unsigned int, KeySym);
+void key_remove(struct key *);
+void key_replace(struct key *, unsigned int, KeySym, enum keyfuncid,
+ const char *);
+void kill_refs(struct ws_win *);
#ifdef SWM_DEBUG
void leavenotify(xcb_leave_notify_event_t *);
#endif
void mapnotify(xcb_map_notify_event_t *);
void mappingnotify(xcb_mapping_notify_event_t *);
void maprequest(xcb_map_request_event_t *);
+void move(struct ws_win *, union arg *);
+void move_step(struct swm_region *, union arg *);
+uint32_t name_to_pixel(const char *);
+void name_workspace(struct swm_region *, union arg *);
void new_region(struct swm_screen *, int, int, int, int);
+int parsekeys(char *, unsigned int, unsigned int *, KeySym *);
+int parsequirks(char *, unsigned long *);
int parse_rgb(const char *, uint16_t *, uint16_t *, uint16_t *);
+void pressbutton(struct swm_region *, union arg *);
+void priorws(struct swm_region *, union arg *);
+#ifdef SWM_DEBUG
+void print_win_geom(xcb_window_t);
+#endif
void propertynotify(xcb_property_notify_event_t *);
-void spawn_select(struct swm_region *, union arg *, char *, int *);
+void quirk_insert(const char *, const char *, unsigned long);
+void quirk_remove(struct quirk *);
+void quirk_replace(struct quirk *, const char *, const char *,
+ unsigned long);
+void quit(struct swm_region *, union arg *);
+void raise_toggle(struct swm_region *, union arg *);
+void resize(struct ws_win *, union arg *);
+void resize_step(struct swm_region *, union arg *);
+void restart(struct swm_region *, union arg *);
+struct swm_region *root_to_region(xcb_window_t, int);
void screenchange(xcb_randr_screen_change_notify_event_t *);
+void scan_xrandr(int);
+void search_do_resp(void);
+void search_resp_name_workspace(const char *, unsigned long);
+void search_resp_search_window(const char *);
+void search_resp_search_workspace(const char *);
+void search_resp_uniconify(const char *, unsigned long);
+void search_win(struct swm_region *, union arg *);
+void search_win_cleanup(void);
+void search_workspace(struct swm_region *, union arg *);
+void send_to_ws(struct swm_region *, union arg *);
+int setautorun(char *, char *, int);
+int setconfbinding(char *, char *, int);
+int setconfcolor(char *, char *, int);
+int setconfmodkey(char *, char *, int);
+int setconfquirk(char *, char *, int);
+int setconfregion(char *, char *, int);
+int setconfspawn(char *, char *, int);
+int setconfvalue(char *, char *, int);
+void setkeybinding(unsigned int, KeySym, enum keyfuncid, const char *);
+int setkeymapping(char *, char *, int);
+int setlayout(char *, char *, int);
+void setquirk(const char *, const char *, unsigned long);
+void setscreencolor(char *, int, int);
+void setspawn(const char *, const char *);
+void setup_ewmh(void);
+void setup_globals(void);
+void setup_keys(void);
+void setup_quirks(void);
+void setup_screens(void);
+void setup_spawn(void);
+void set_child_transient(struct ws_win *, xcb_window_t *);
+void set_swm_iconic(struct ws_win *, int);
+void set_win_state(struct ws_win *, uint16_t);
void shutdown_cleanup(void);
+void sighdlr(int);
+void socket_setnonblock(int);
+void sort_windows(struct ws_win_list *);
+void spawn(int, union arg *, int);
+void spawn_custom(struct swm_region *, union arg *, const char *);
+int spawn_expand(struct swm_region *, union arg *, const char *, char ***);
+void spawn_insert(const char *, const char *);
+void spawn_remove(struct spawn_prog *);
+void spawn_replace(struct spawn_prog *, const char *, const char *);
+void spawn_select(struct swm_region *, union arg *, const char *, int *);
+void stack_config(struct swm_region *, union arg *);
+void stack_floater(struct ws_win *, struct swm_region *);
+void stack_master(struct workspace *, struct swm_geometry *, int, int);
void store_float_geom(struct ws_win *, struct swm_region *);
+char * strdupsafe(const char *);
+void swapwin(struct swm_region *, union arg *);
+void switchws(struct swm_region *, union arg *);
+void teardown_ewmh(void);
+void unfocus_win(struct ws_win *);
+void uniconify(struct swm_region *, union arg *);
void unmanage_window(struct ws_win *);
void unmapnotify(xcb_unmap_notify_event_t *);
-void unfocus_win(struct ws_win *);
+void unmap_all(void);
+void unmap_window(struct ws_win *);
+void updatenumlockmask(void);
+void update_modkey(unsigned int);
void update_window(struct ws_win *);
+int validate_win(struct ws_win *);
+int validate_ws(struct workspace *);
/*void visibilitynotify(xcb_visibility_notify_event_t *);*/
+void version(struct swm_region *, union arg *);
+pid_t window_get_pid(xcb_window_t);
+void wkill(struct swm_region *, union arg *);
+void workaround(void);
+void xft_init(struct swm_region *);
+
+RB_PROTOTYPE(key_tree, key, entry, key_cmp);
+RB_GENERATE(key_tree, key, entry, key_cmp);
+struct key_tree keys;
void
cursors_load(void)
}
char *
-expand_tilde(char *s)
+expand_tilde(const char *s)
{
struct passwd *ppwd;
- int i, max;
+ int i;
+ long max;
char *user;
const char *sc = s;
char *result;
kill(bar_pid, SIGTERM);
bar_pid = 0;
}
- strlcpy((char *)bar_ext, "", sizeof bar_ext);
+ strlcpy(bar_ext, "", sizeof bar_ext);
bar_extra = 0;
}
TAILQ_FOREACH(r, &screens[i].rl, entry) {
if (r->bar == NULL)
continue;
+
+ if (r->ws->bar_enabled)
+ xcb_map_window(conn, r->bar->id);
+ else {
+ xcb_unmap_window(conn, r->bar->id);
+ continue;
+ }
+
bar_fmt(fmtexp, fmtnew, r, sizeof fmtnew);
bar_replace(fmtnew, fmtrep, r, sizeof fmtrep);
if (bar_font_legacy)
void
bar_update(void)
{
- size_t len;
- char *b;
+ size_t len;
+ char b[SWM_BAR_MAX];
- if (!bar_enabled)
- return;
- if (bar_extra && bar_extra_running) {
- /* ignore short reads; it'll correct itself */
- while ((b = fgetln(stdin, &len)) != NULL)
- if (b && b[len - 1] == '\n') {
- b[len - 1] = '\0';
- strlcpy((char *)bar_ext, b, sizeof bar_ext);
+ if (bar_enabled && bar_extra && bar_extra_running) {
+ while (fgets(b, sizeof(b), stdin) != NULL) {
+ len = strlen(b);
+ if (b[len - 1] == '\n') {
+ /* Remove newline. */
+ b[--len] = '\0';
+
+ /* "Clear" bar_ext. */
+ bar_ext[0] = '\0';
+
+ /* Flush buffered output. */
+ strlcpy(bar_ext, bar_ext_buf, sizeof(bar_ext));
+ bar_ext_buf[0] = '\0';
+
+ /* Append new output to bar. */
+ strlcat(bar_ext, b, sizeof(bar_ext));
+ } else {
+ /* Buffer output. */
+ strlcat(bar_ext_buf, b, sizeof(bar_ext_buf));
}
- if (b == NULL && errno != EAGAIN) {
+ }
+
+ if (errno != EAGAIN) {
warn("bar_update: bar_extra failed");
bar_extra_stop();
}
- } else
- strlcpy((char *)bar_ext, "", sizeof bar_ext);
+ } else {
+ /*
+ * Attempt to drain stdin, so it doesn't cause the main loop to
+ * call us as fast as it can.
+ */
+ fgets(b, sizeof(b), stdin);
- bar_fmt_print();
- alarm(bar_delay);
-}
+ if (!bar_enabled)
+ return;
-void
-bar_signal(int sig)
-{
- /* suppress unused warning since var is needed */
- (void)sig;
+ bar_ext[0] = '\0';
+ }
- bar_alarm = 1;
+ bar_fmt_print();
}
void
DNPRINTF(SWM_D_BAR, "bar_toggle\n");
- num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
- if (bar_enabled) {
- for (i = 0; i < num_screens; i++)
- TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
- if (tmpr->bar)
- xcb_unmap_window(conn, tmpr->bar->id);
- } else {
- for (i = 0; i < num_screens; i++)
- TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
- if (tmpr->bar)
- xcb_map_window(conn, tmpr->bar->id);
+ switch (args->id) {
+ case SWM_ARG_ID_BAR_TOGGLE_WS:
+ /* Only change if master switch is enabled. */
+ if (bar_enabled)
+ r->ws->bar_enabled = !r->ws->bar_enabled;
+ else
+ bar_enabled = r->ws->bar_enabled = 1;
+ break;
+ case SWM_ARG_ID_BAR_TOGGLE:
+ bar_enabled = !bar_enabled;
+ break;
}
- bar_enabled = !bar_enabled;
+ /* update bars as necessary */
+ num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+ for (i = 0; i < num_screens; i++)
+ TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
+ if (tmpr->bar) {
+ if (bar_enabled && tmpr->ws->bar_enabled)
+ xcb_map_window(conn, tmpr->bar->id);
+ else
+ xcb_unmap_window(conn, tmpr->bar->id);
+ }
stack();
err(1, "pipe error");
socket_setnonblock(bar_pipe[0]);
socket_setnonblock(bar_pipe[1]); /* XXX hmmm, really? */
+
+ /* Set stdin to read from the pipe. */
if (dup2(bar_pipe[0], 0) == -1)
err(1, "dup2");
+
+ /* Set stdout to write to the pipe. */
if (dup2(bar_pipe[1], 1) == -1)
err(1, "dup2");
+
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
err(1, "could not disable SIGPIPE");
switch (bar_pid = fork()) {
xcb_change_window_attributes(conn, r->bar->id,
XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL, wa);
}
+
bar_update();
+ xcb_flush(conn);
}
int
}
void
-fontset_init()
+fontset_init(void)
{
char *default_string;
char **missing_charsets;
if (!XftColorAllocValue(display, DefaultVisual(display, r->s->idx),
DefaultColormap(display, r->s->idx), &color, &bar_font_color))
- warn("unable to allocate Xft color");
+ warn("Xft error: unable to allocate color.");
bar_height = bar_font->height + 2 * bar_border_width;
"%d x %d\n", WINID(r->bar), X(r->bar), Y(r->bar), WIDTH(r->bar),
HEIGHT(r->bar));
- if (signal(SIGALRM, bar_signal) == SIG_ERR)
- err(1, "could not install bar_signal");
bar_refresh();
}
} else {
DNPRINTF(SWM_D_EVENT, "get_pointer_win: none.\n");
}
+ free(r);
}
return win;
kill_refs(win->ws->focus);
win->ws->focus = NULL;
}
+
if (validate_win(win->ws->focus_prev)) {
kill_refs(win->ws->focus_prev);
win->ws->focus_prev = NULL;
g = r->g;
g.w -= 2 * border_width;
g.h -= 2 * border_width;
- if (bar_enabled) {
+ if (bar_enabled && r->ws->bar_enabled) {
if (!bar_at_bottom)
g.y += bar_height;
g.h -= bar_height;
else
win_g.y += last_h + 2 * border_width;
- if (disable_border && !bar_enabled && winno == 1){
+ if (disable_border && !(bar_enabled && ws->bar_enabled) &&
+ winno == 1){
bordered = 0;
win_g.w += 2 * border_width;
win_g.h += 2 * border_width;
if (X(w) != gg.x || Y(w) != gg.y || WIDTH(w) != gg.w ||
HEIGHT(w) != gg.h) {
w->g = gg;
- if (bar_enabled){
+ if (bar_enabled && ws->bar_enabled){
w->bordered = 1;
} else {
w->bordered = 0;
XCB_GET_PROPERTY_TYPE_ANY, 0, UINT_MAX);
r = xcb_get_property_reply(conn, c, NULL);
- if (!r || r->type == XCB_NONE) {
- free(r);
- /* Use WM_NAME instead; no UTF-8. */
- c = xcb_get_property(conn, 0, win, XCB_ATOM_WM_NAME,
- XCB_GET_PROPERTY_TYPE_ANY, 0, UINT_MAX);
- r = xcb_get_property_reply(conn, c, NULL);
-
- if(!r || r->type == XCB_NONE) {
+ if (r) {
+ if (r->type == XCB_NONE) {
free(r);
- return NULL;
+ /* Use WM_NAME instead; no UTF-8. */
+ c = xcb_get_property(conn, 0, win, XCB_ATOM_WM_NAME,
+ XCB_GET_PROPERTY_TYPE_ANY, 0, UINT_MAX);
+ r = xcb_get_property_reply(conn, c, NULL);
+
+ if (!r)
+ return (NULL);
+ if (r->type == XCB_NONE) {
+ free(r);
+ return (NULL);
+ }
}
- }
+ if (r->length > 0)
+ name = strndup(xcb_get_property_value(r),
+ xcb_get_property_value_length(r));
- if (r->length > 0)
- name = strndup(xcb_get_property_value(r),
- xcb_get_property_value_length(r));
+ free(r);
+ }
- free(r);
- return name;
+ return (name);
}
void
}
void
-search_resp_uniconify(char *resp, unsigned long len)
+search_resp_uniconify(const char *resp, unsigned long len)
{
char *name;
struct ws_win *win;
}
void
-search_resp_name_workspace(char *resp, unsigned long len)
+search_resp_name_workspace(const char *resp, unsigned long len)
{
struct workspace *ws;
}
void
-search_resp_search_workspace(char *resp)
+search_resp_search_workspace(const char *resp)
{
char *p, *q;
int ws_idx;
}
void
-search_resp_search_window(char *resp)
+search_resp_search_window(const char *resp)
{
char *s;
int idx;
{
xcb_timestamp_t timestamp = 0;
struct swm_region *r = NULL;
- int resize_step = 0;
+ int resize_stp = 0;
struct swm_geometry g;
int top = 0, left = 0, resizing;
int dx, dy;
switch (args->id) {
case SWM_ARG_ID_WIDTHSHRINK:
WIDTH(win) -= SWM_RESIZE_STEPS;
- resize_step = 1;
+ resize_stp = 1;
break;
case SWM_ARG_ID_WIDTHGROW:
WIDTH(win) += SWM_RESIZE_STEPS;
- resize_step = 1;
+ resize_stp = 1;
break;
case SWM_ARG_ID_HEIGHTSHRINK:
HEIGHT(win) -= SWM_RESIZE_STEPS;
- resize_step = 1;
+ resize_stp = 1;
break;
case SWM_ARG_ID_HEIGHTGROW:
HEIGHT(win) += SWM_RESIZE_STEPS;
- resize_step = 1;
+ resize_stp = 1;
break;
default:
break;
}
- if (resize_step) {
+ if (resize_stp) {
constrain_window(win, r, 1);
update_window(win);
store_float_geom(win,r);
move(struct ws_win *win, union arg *args)
{
xcb_timestamp_t timestamp = 0;
- int move_step = 0, moving;
+ int move_stp = 0, moving;
struct swm_region *r = NULL;
xcb_query_pointer_reply_t *qpr;
xcb_generic_event_t *evt;
focus_flush();
- move_step = 0;
+ move_stp = 0;
switch (args->id) {
case SWM_ARG_ID_MOVELEFT:
X(win) -= (SWM_MOVE_STEPS - border_width);
- move_step = 1;
+ move_stp = 1;
break;
case SWM_ARG_ID_MOVERIGHT:
X(win) += (SWM_MOVE_STEPS - border_width);
- move_step = 1;
+ move_stp = 1;
break;
case SWM_ARG_ID_MOVEUP:
Y(win) -= (SWM_MOVE_STEPS - border_width);
- move_step = 1;
+ move_stp = 1;
break;
case SWM_ARG_ID_MOVEDOWN:
Y(win) += (SWM_MOVE_STEPS - border_width);
- move_step = 1;
+ move_stp = 1;
break;
default:
break;
}
- if (move_step) {
+ if (move_stp) {
constrain_window(win, r, 0);
update_window(win);
store_float_geom(win, r);
focus_flush();
}
-/* user/key callable function IDs */
-enum keyfuncid {
- KF_BAR_TOGGLE,
- KF_BUTTON2,
- KF_CYCLE_LAYOUT,
- KF_FLIP_LAYOUT,
- KF_FLOAT_TOGGLE,
- KF_FOCUS_MAIN,
- KF_FOCUS_NEXT,
- KF_FOCUS_PREV,
- KF_HEIGHT_GROW,
- KF_HEIGHT_SHRINK,
- KF_ICONIFY,
- KF_MASTER_SHRINK,
- KF_MASTER_GROW,
- KF_MASTER_ADD,
- KF_MASTER_DEL,
- KF_MOVE_DOWN,
- KF_MOVE_LEFT,
- KF_MOVE_RIGHT,
- KF_MOVE_UP,
- KF_MVWS_1,
- KF_MVWS_2,
- KF_MVWS_3,
- KF_MVWS_4,
- KF_MVWS_5,
- KF_MVWS_6,
- KF_MVWS_7,
- KF_MVWS_8,
- KF_MVWS_9,
- KF_MVWS_10,
- KF_MVWS_11,
- KF_MVWS_12,
- KF_MVWS_13,
- KF_MVWS_14,
- KF_MVWS_15,
- KF_MVWS_16,
- KF_MVWS_17,
- KF_MVWS_18,
- KF_MVWS_19,
- KF_MVWS_20,
- KF_MVWS_21,
- KF_MVWS_22,
- KF_NAME_WORKSPACE,
- KF_QUIT,
- KF_RAISE_TOGGLE,
- KF_RESTART,
- KF_SCREEN_NEXT,
- KF_SCREEN_PREV,
- KF_SEARCH_WIN,
- KF_SEARCH_WORKSPACE,
- KF_SPAWN_CUSTOM,
- KF_STACK_INC,
- KF_STACK_DEC,
- KF_STACK_RESET,
- KF_SWAP_MAIN,
- KF_SWAP_NEXT,
- KF_SWAP_PREV,
- KF_UNICONIFY,
- KF_VERSION,
- KF_WIDTH_GROW,
- KF_WIDTH_SHRINK,
- KF_WIND_DEL,
- KF_WIND_KILL,
- KF_WS_1,
- KF_WS_2,
- KF_WS_3,
- KF_WS_4,
- KF_WS_5,
- KF_WS_6,
- KF_WS_7,
- KF_WS_8,
- KF_WS_9,
- KF_WS_10,
- KF_WS_11,
- KF_WS_12,
- KF_WS_13,
- KF_WS_14,
- KF_WS_15,
- KF_WS_16,
- KF_WS_17,
- KF_WS_18,
- KF_WS_19,
- KF_WS_20,
- KF_WS_21,
- KF_WS_22,
- KF_WS_NEXT,
- KF_WS_NEXT_ALL,
- KF_WS_PREV,
- KF_WS_PREV_ALL,
- KF_WS_PRIOR,
- KF_DUMPWINS, /* MUST BE LAST */
- KF_INVALID
-};
-
/* key definitions */
struct keyfunc {
char name[SWM_FUNCNAME_LEN];
union arg args;
} keyfuncs[KF_INVALID + 1] = {
/* name function argument */
- { "bar_toggle", bar_toggle, {0} },
+ { "bar_toggle", bar_toggle, {.id = SWM_ARG_ID_BAR_TOGGLE} },
+ { "bar_toggle_ws", bar_toggle, {.id = SWM_ARG_ID_BAR_TOGGLE_WS} },
{ "button2", pressbutton, {2} },
{ "cycle_layout", cycle_layout, {0} },
{ "flip_layout", stack_config, {.id = SWM_ARG_ID_FLIPLAYOUT} },
{ "dumpwins", dumpwins, {0} }, /* MUST BE LAST */
{ "invalid key func", NULL, {0} },
};
-struct key {
- RB_ENTRY(key) entry;
- unsigned int mod;
- KeySym keysym;
- enum keyfuncid funcid;
- char *spawn_name;
-};
-RB_HEAD(key_tree, key);
int
key_cmp(struct key *kp1, struct key *kp2)
return (0);
}
-RB_GENERATE(key_tree, key, entry, key_cmp);
-struct key_tree keys;
-
/* mouse */
enum { client_click, root_click };
struct button {
buttons[i].mask = mod;
}
-/* spawn */
-struct spawn_prog {
- TAILQ_ENTRY(spawn_prog) entry;
- char *name;
- int argc;
- char **argv;
-};
-TAILQ_HEAD(spawn_list, spawn_prog);
-struct spawn_list spawns = TAILQ_HEAD_INITIALIZER(spawns);
-
int
-spawn_expand(struct swm_region *r, union arg *args, char *spawn_name,
+spawn_expand(struct swm_region *r, union arg *args, const char *spawn_name,
char ***ret_args)
{
struct spawn_prog *prog = NULL;
}
void
-spawn_custom(struct swm_region *r, union arg *args, char *spawn_name)
+spawn_custom(struct swm_region *r, union arg *args, const char *spawn_name)
{
union arg a;
char **real_args;
}
void
-spawn_select(struct swm_region *r, union arg *args, char *spawn_name, int *pid)
+spawn_select(struct swm_region *r, union arg *args, const char *spawn_name,
+ int *pid)
{
union arg a;
char **real_args;
}
void
-spawn_insert(char *name, char *args)
+spawn_insert(const char *name, const char *args)
{
char *arg, *cp, *ptr;
struct spawn_prog *sp;
}
void
-spawn_replace(struct spawn_prog *sp, char *name, char *args)
+spawn_replace(struct spawn_prog *sp, const char *name, const char *args)
{
DNPRINTF(SWM_D_SPAWN, "spawn_replace: %s [%s]\n", sp->name, name);
}
void
-setspawn(char *name, char *args)
+setspawn(const char *name, const char *args)
{
struct spawn_prog *sp;
}
char *
-strdupsafe(char *str)
+strdupsafe(const char *str)
{
if (str == NULL)
return (NULL);
}
void
-key_insert(unsigned int mod, KeySym ks, enum keyfuncid kfid, char *spawn_name)
+key_insert(unsigned int mod, KeySym ks, enum keyfuncid kfid,
+ const char *spawn_name)
{
struct key *kp;
void
key_replace(struct key *kp, unsigned int mod, KeySym ks, enum keyfuncid kfid,
- char *spawn_name)
+ const char *spawn_name)
{
DNPRINTF(SWM_D_KEY, "key_replace: %s [%s]\n", keyfuncs[kp->funcid].name,
spawn_name);
void
setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid,
- char *spawn_name)
+ const char *spawn_name)
{
struct key *kp;
return;
}
if (kfid == KF_INVALID) {
- warnx("error: setkeybinding: cannot find mod/key combination");
+ warnx("bind: Key combination already unbound.");
DNPRINTF(SWM_D_KEY, "setkeybinding: leave\n");
return;
}
setkeybinding(MODKEY_SHIFT, XK_F11, KF_MVWS_21, NULL);
setkeybinding(MODKEY_SHIFT, XK_F12, KF_MVWS_22, NULL);
setkeybinding(MODKEY, XK_b, KF_BAR_TOGGLE, NULL);
+ setkeybinding(MODKEY_SHIFT, XK_b, KF_BAR_TOGGLE_WS,NULL);
setkeybinding(MODKEY, XK_Tab, KF_FOCUS_NEXT, NULL);
setkeybinding(MODKEY_SHIFT, XK_Tab, KF_FOCUS_PREV, NULL);
setkeybinding(MODKEY_SHIFT, XK_x, KF_WIND_KILL, NULL);
{
struct key *kp;
int num_screens, k, j;
- unsigned int modifiers[3];
+ unsigned int modifiers[4];
xcb_keycode_t *code;
DNPRINTF(SWM_D_MISC, "grabkeys\n");
modifiers[0] = 0;
modifiers[1] = numlockmask;
- modifiers[2] = numlockmask | XCB_MOD_MASK_LOCK;
+ modifiers[2] = XCB_MOD_MASK_LOCK;
+ modifiers[3] = numlockmask | XCB_MOD_MASK_LOCK;
num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
for (k = 0; k < num_screens; k++) {
void
grabbuttons(struct ws_win *win)
{
- int i;
+ unsigned int modifiers[4];
+ int i, j;
DNPRINTF(SWM_D_MOUSE, "grabbuttons: win 0x%x\n", win->id);
+ updatenumlockmask();
+
+ modifiers[0] = 0;
+ modifiers[1] = numlockmask;
+ modifiers[2] = XCB_MOD_MASK_LOCK;
+ modifiers[3] = numlockmask | XCB_MOD_MASK_LOCK;
for (i = 0; i < LENGTH(buttons); i++)
if (buttons[i].action == client_click)
- xcb_grab_button(conn, 0, win->id, BUTTONMASK,
- XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC,
- XCB_WINDOW_NONE, XCB_CURSOR_NONE,
- buttons[i].button, buttons[i].mask);
+ for (j = 0; j < LENGTH(modifiers); ++j)
+ xcb_grab_button(conn, 0, win->id, BUTTONMASK,
+ XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC,
+ XCB_WINDOW_NONE, XCB_CURSOR_NONE,
+ buttons[i].button, buttons[i].mask |
+ modifiers[j]);
}
const char *quirkname[] = {
DNPRINTF(SWM_D_QUIRK, "setquirk: enter %s:%s [%lu]\n", class, name,
quirk);
+ /* Remove/replace existing quirk. */
TAILQ_FOREACH(qp, &quirks, entry) {
if (!strcmp(qp->class, class) && !strcmp(qp->name, name)) {
if (!quirk)
return;
}
}
- if (!quirk) {
- warnx("error: setquirk: cannot find class/name combination");
- return;
- }
- quirk_insert(class, name, quirk);
+ /* Only insert if quirk is not NONE. */
+ if (quirk)
+ quirk_insert(class, name, quirk);
+
DNPRINTF(SWM_D_QUIRK, "setquirk: leave\n");
}
SWM_S_BAR_BORDER_WIDTH,
SWM_S_BAR_DELAY,
SWM_S_BAR_ENABLED,
+ SWM_S_BAR_ENABLED_WS,
SWM_S_BAR_FONT,
SWM_S_BAR_FORMAT,
SWM_S_BAR_JUSTIFY,
int
setconfvalue(char *selector, char *value, int flags)
{
- int i;
- char *b;
+ struct workspace *ws;
+ int i, ws_id, num_screens;
+ char *b;
/* suppress unused warning since var is needed */
(void)selector;
bar_border_width = 0;
break;
case SWM_S_BAR_DELAY:
- bar_delay = atoi(value);
+ /* No longer needed; leave to not break old conf files. */
break;
case SWM_S_BAR_ENABLED:
bar_enabled = atoi(value);
break;
+ case SWM_S_BAR_ENABLED_WS:
+ ws_id = atoi(selector) - 1;
+ if (ws_id < 0 || ws_id >= workspace_limit)
+ errx(1, "setconfvalue: bar_enabled_ws: invalid "
+ "workspace %d.", ws_id + 1);
+
+ num_screens = xcb_setup_roots_length(xcb_get_setup(conn));
+ for (i = 0; i < num_screens; i++) {
+ ws = (struct workspace *)&screens[i].ws;
+ ws[ws_id].bar_enabled = atoi(value);
+ }
+ break;
case SWM_S_BAR_FONT:
b = bar_fonts;
if (asprintf(&bar_fonts, "%s,%s", value, bar_fonts) == -1)
setconfspawn("spawn_term", value, 0);
break;
case SWM_S_SS_APP:
+ /* No longer needed; leave to not break old conf files. */
break;
case SWM_S_SS_ENABLED:
- ss_enabled = atoi(value);
+ /* No longer needed; leave to not break old conf files. */
break;
case SWM_S_STACK_ENABLED:
stack_enabled = atoi(value);
{
int ws_id;
char s[1024];
- char *ap, *sp = s;
+ char *ap, *sp;
union arg a;
int argc = 0;
pid_t pid;
if (ws_id < 0 || ws_id >= workspace_limit)
errx(1, "autorun: invalid workspace %d", ws_id + 1);
+ sp = expand_tilde((char *)&s);
+
/*
* This is a little intricate
*
err(1, "setautorun: realloc");
a.argv[argc - 1] = ap;
}
+ free(sp);
if ((a.argv = realloc(a.argv, (argc + 1) * sizeof(char *))) == NULL)
err(1, "setautorun: realloc");
};
struct config_option configopt[] = {
{ "bar_enabled", setconfvalue, SWM_S_BAR_ENABLED },
+ { "bar_enabled_ws", setconfvalue, SWM_S_BAR_ENABLED_WS },
{ "bar_at_bottom", setconfvalue, SWM_S_BAR_AT_BOTTOM },
{ "bar_border", setconfcolor, SWM_S_COLOR_BAR_BORDER },
{ "bar_border_width", setconfvalue, SWM_S_BAR_BORDER_WIDTH },
};
int
-conf_load(char *filename, int keymapping)
+conf_load(const char *filename, int keymapping)
{
FILE *config;
char *line, *cp, *optsub, *optval;
/* Focus on empty region */
/* If no windows on region if its empty. */
r = root_to_region(e->root, SWM_CK_POINTER);
- if (r && TAILQ_EMPTY(&r->ws->winlist)) {
+ if (r == NULL) {
+ DNPRINTF(SWM_D_EVENT, "buttonpress: "
+ "NULL region; ignoring.\n");
+ goto out;
+ }
+
+ if (TAILQ_EMPTY(&r->ws->winlist)) {
old_r = root_to_region(e->root, SWM_CK_FOCUS);
if (old_r && old_r != r)
unfocus_win(old_r->ws->focus);
}
if (win == NULL)
- return;
+ goto out;
last_event_time = e->time;
WIDTH(win) = win->g_float.w;
HEIGHT(win) = win->g_float.h;
- stack_floater(win, win->ws->r);
-
- focus_flush();
+ if (r) {
+ stack_floater(win, r);
+ focus_flush();
+ }
} else {
config_win(win, e);
xcb_flush(conn);
if (e->event == e->root) {
/* If no windows on pointer region, then focus root. */
r = root_to_region(e->root, SWM_CK_POINTER);
+ if (r == NULL) {
+ DNPRINTF(SWM_D_EVENT, "enterntoify: "
+ "NULL region; ignoring.\n");
+ return;
+ }
+
if (TAILQ_EMPTY(&r->ws->winlist)) {
old_r = root_to_region(e->root, SWM_CK_FOCUS);
if (old_r && old_r != r)
}
#endif
-/* lets us use one switch statement for arbitrary mode/detail combinations */
-#define MERGE_MEMBERS(a,b) (((a & 0xffff) << 16) | (b & 0xffff))
-
void
mapnotify(xcb_map_notify_event_t *e)
{
xcb_randr_crtc_t *crtc;
xcb_screen_t *screen;
+ DNPRINTF(SWM_D_MISC, "scan_xrandr: screen: %d\n", i);
+
if ((screen = get_screen(i)) == NULL)
errx(1, "ERROR: can't get screen %d.", i);
new_region(&screens[i], 0, 0,
screen->width_in_pixels,
screen->height_in_pixels);
- return;
+ goto out;
} else
ncrtc = srr->num_crtcs;
free(cir);
}
free(srr);
- } else
+ }
#endif /* SWM_XRR_HAS_CRTC */
- {
+
+ /* If detection failed, create a single region that spans the screen. */
+ if (TAILQ_EMPTY(&screens[i].rl))
new_region(&screens[i], 0, 0, screen->width_in_pixels,
screen->height_in_pixels);
- }
+
+out:
+ DNPRINTF(SWM_D_MISC, "scan_xrandr: done.\n");
}
void
ws = &screens[i].ws[j];
ws->idx = j;
ws->name = NULL;
+ ws->bar_enabled = 1;
ws->focus = NULL;
ws->focus_prev = NULL;
ws->focus_pending = NULL;
xcb_generic_event_t *evt;
struct timeval tv;
fd_set rd;
+ int rd_max;
+ int do_bar_update = 0;
+ int num_readable;
/* suppress unused warning since var is needed */
(void)argc;
xcb_ungrab_server(conn);
xcb_flush(conn);
+ rd_max = xfd > STDIN_FILENO ? xfd : STDIN_FILENO;
+
while (running) {
while ((evt = xcb_poll_for_event(conn))) {
if (!running)
}
FD_ZERO(&rd);
+ FD_SET(STDIN_FILENO, &rd);
FD_SET(xfd, &rd);
tv.tv_sec = 1;
tv.tv_usec = 0;
- if (select(xfd + 1, &rd, NULL, NULL, &tv) == -1)
- if (errno != EINTR) {
- DNPRINTF(SWM_D_MISC, "select failed");
- }
+ 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))
+ do_bar_update = 1;
+
if (restart_wm)
restart(NULL, NULL);
+
if (search_resp)
search_do_resp();
+
if (!running)
goto done;
- if (bar_alarm) {
- bar_alarm = 0;
+
+ if (do_bar_update) {
+ do_bar_update = 0;
bar_update();
+ xcb_flush(conn);
}
}
done: