* 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-2013 Reginald Kennedy <rk@rejii.com>
+ * Copyright (c) 2011-2014 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>
#include <pwd.h>
#include <regex.h>
#include <signal.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char *buildstr = SPECTRWM_VERSION;
#endif
-#if !defined(__CYGWIN__) /* cygwin chokes on xrandr stuff */
+#if !defined(__CYGWIN__) /* cygwin chokes on randr stuff */
# if RANDR_MAJOR < 1
-# error XRandR versions less than 1.0 are not supported
+# error RandR versions less than 1.0 are not supported
#endif
# if RANDR_MAJOR >= 1
volatile sig_atomic_t restart_wm = 0;
xcb_timestamp_t last_event_time = 0;
int outputs = 0;
-int other_wm;
-int xrandr_support;
-int xrandr_eventbase;
+bool randr_support;
+int randr_eventbase;
unsigned int numlockmask = 0;
Display *display;
xcb_key_symbols_t *syms;
int boundary_width = 50;
-int cycle_empty = 0;
-int cycle_visible = 0;
+bool cycle_empty = false;
+bool cycle_visible = false;
int term_width = 0;
int font_adjusted = 0;
unsigned int mod_key = MODKEY;
char bar_ext[SWM_BAR_MAX];
char bar_ext_buf[SWM_BAR_MAX];
char bar_vertext[SWM_BAR_MAX];
-int bar_version = 0;
-int bar_enabled = 1;
+bool bar_version = false;
+bool bar_enabled = true;
int bar_border_width = 1;
-int bar_at_bottom = 0;
-int bar_extra = 0;
-int bar_verbose = 1;
+bool bar_at_bottom = false;
+bool bar_extra = false;
int bar_height = 0;
int bar_justify = SWM_BAR_JUSTIFY_LEFT;
char *bar_format = NULL;
-int stack_enabled = 1;
-int clock_enabled = 1;
-int iconic_enabled = 0;
-int urgent_enabled = 0;
+bool stack_enabled = true;
+bool clock_enabled = true;
+bool iconic_enabled = false;
+bool urgent_enabled = false;
+int composite_enabled = 0;
+double opacity_focus = 1.0;
+double opacity_unfocus = 0.6;
char *clock_format = NULL;
-int window_class_enabled = 0;
-int window_instance_enabled = 0;
-int window_name_enabled = 0;
+bool window_class_enabled = false;
+bool window_instance_enabled = false;
+bool window_name_enabled = false;
int focus_mode = SWM_FOCUS_DEFAULT;
int focus_close = SWM_STACK_BELOW;
-int focus_close_wrap = 1;
+bool focus_close_wrap = true;
int focus_default = SWM_STACK_TOP;
int spawn_position = SWM_STACK_TOP;
-int disable_border = 0;
+bool disable_border = false;
int border_width = 1;
int region_padding = 0;
int tile_gap = 0;
-int java_workaround = 1;
-int verbose_layout = 0;
+bool java_workaround = true;
+bool verbose_layout = false;
+#ifdef SWM_DEBUG
time_t time_started;
+#endif
pid_t bar_pid;
XFontSet bar_fs;
XFontSetExtents *bar_fs_extents;
XftFont *bar_font;
-int bar_font_legacy = 1;
+bool bar_font_legacy = true;
char *bar_fonts;
XftColor bar_font_color;
+XftColor search_font_color;
struct passwd *pwd;
char *startup_exception;
unsigned int nr_exceptions = 0;
struct ws_win *focus_child; /* focus on child transient */
struct swm_geometry g; /* current geometry */
struct swm_geometry g_float; /* region coordinates */
- int g_floatvalid; /* g_float geometry validity */
- int mapped;
- int bordered;
+ bool g_floatvalid; /* g_float geometry validity */
+ bool mapped;
+ bool bordered;
uint32_t ewmh_flags;
int font_size_boundary[SWM_MAX_FONT_STEPS];
int font_steps;
int last_inc;
- int can_delete;
- int take_focus;
- int java;
+ bool can_delete;
+ bool take_focus;
+ bool java;
unsigned long quirks;
struct workspace *ws; /* always valid */
struct swm_screen *s; /* always valid, never changes */
struct workspace {
int idx; /* workspace index */
char *name; /* workspace name */
- int always_raise; /* raise windows on focus */
- int bar_enabled; /* bar visibility */
+ bool always_raise; /* raise windows on focus */
+ bool 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 */
int horizontal_msize;
int horizontal_mwin;
int horizontal_stacks;
- int horizontal_flip;
+ bool horizontal_flip;
int vertical_msize;
int vertical_mwin;
int vertical_stacks;
- int vertical_flip;
+ bool vertical_flip;
} l_state;
};
SWM_S_COLOR_BAR_BORDER_UNFOCUS,
SWM_S_COLOR_BAR_FONT,
SWM_S_COLOR_FOCUS,
+ SWM_S_COLOR_FOCUS_MAXIMIZED,
SWM_S_COLOR_UNFOCUS,
+ SWM_S_COLOR_UNFOCUS_MAXIMIZED,
SWM_S_COLOR_MAX
};
struct {
uint32_t pixel;
char *name;
+ int manual;
} c[SWM_S_COLOR_MAX];
xcb_gcontext_t bar_gc;
#define SWM_Q_FOCUSPREV (1<<5) /* focus on caller */
#define SWM_Q_NOFOCUSONMAP (1<<6) /* Don't focus on window when mapped. */
#define SWM_Q_FOCUSONMAP_SINGLE (1<<7) /* Only focus if single win of type. */
+#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. */
};
TAILQ_HEAD(quirk_list, quirk);
struct quirk_list quirks = TAILQ_HEAD_INITIALIZER(quirks);
_NET_WM_STATE_MAXIMIZED_HORZ,
_NET_WM_STATE_SKIP_PAGER,
_NET_WM_STATE_SKIP_TASKBAR,
+ _NET_WM_WINDOW_OPACITY,
_NET_WM_WINDOW_TYPE,
_NET_WM_WINDOW_TYPE_DIALOG,
_NET_WM_WINDOW_TYPE_DOCK,
{"_NET_WM_STATE_MAXIMIZED_HORZ", XCB_ATOM_NONE},
{"_NET_WM_STATE_SKIP_PAGER", XCB_ATOM_NONE},
{"_NET_WM_STATE_SKIP_TASKBAR", XCB_ATOM_NONE},
+ {"_NET_WM_WINDOW_OPACITY", XCB_ATOM_NONE},
{"_NET_WM_WINDOW_TYPE", XCB_ATOM_NONE},
{"_NET_WM_WINDOW_TYPE_DIALOG", XCB_ATOM_NONE},
{"_NET_WM_WINDOW_TYPE_DOCK", XCB_ATOM_NONE},
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_geometry *, int *);
-int count_win(struct workspace *, int);
+int count_win(struct workspace *, bool);
void cursors_cleanup(void);
void cursors_load(void);
void custom_region(const char *);
xcb_screen_t *get_screen(int);
int get_screen_count(void);
#ifdef SWM_DEBUG
+char *get_source_type_label(uint32_t);
char *get_stack_mode_name(uint8_t);
#endif
int32_t get_swm_ws(xcb_window_t);
char *get_win_name(xcb_window_t);
uint8_t get_win_state(xcb_window_t);
void get_wm_protocols(struct ws_win *);
-int get_ws_idx(xcb_window_t);
+int get_ws_idx(struct ws_win *);
void grabbuttons(struct ws_win *);
void grabkeys(void);
void grab_windows(void);
void iconify(struct swm_region *, union arg *);
-int isxlfd(char *);
+bool 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 *);
void leavenotify(xcb_leave_notify_event_t *);
#endif
void load_float_geom(struct ws_win *);
-struct ws_win *manage_window(xcb_window_t, int);
+struct ws_win *manage_window(xcb_window_t, int, bool);
void map_window(struct ws_win *);
void mapnotify(xcb_map_notify_event_t *);
void mappingnotify(xcb_mapping_notify_event_t *);
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 scan_randr(int);
void search_do_resp(void);
void search_resp_name_workspace(const char *, size_t);
void search_resp_search_window(const char *);
void setup_screens(void);
void setup_spawn(void);
void set_child_transient(struct ws_win *, xcb_window_t *);
+void set_opacity(struct ws_win *, uint32_t);
void set_win_state(struct ws_win *, uint8_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(int, union arg *, bool);
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 *, int);
void spawn_replace(struct spawn_prog *, const char *, const char *, int);
void spawn_select(struct swm_region *, union arg *, const char *, int *);
void stack_config(struct swm_region *, union arg *);
-void stack_master(struct workspace *, struct swm_geometry *, int, int);
+void stack_master(struct workspace *, struct swm_geometry *, int, bool);
void store_float_geom(struct ws_win *);
char *strdupsafe(const char *);
void swapwin(struct swm_region *, union arg *);
void update_modkey(unsigned int);
void update_win_stacking(struct ws_win *);
void update_window(struct ws_win *);
+void update_window_color(struct ws_win *);
void update_wm_state(struct ws_win *win);
void validate_spawns(void);
int validate_win(struct ws_win *);
int validate_ws(struct workspace *);
void version(struct swm_region *, union arg *);
-void win_to_ws(struct ws_win *, int, int);
+void win_to_ws(struct ws_win *, int, bool);
pid_t window_get_pid(xcb_window_t);
void wkill(struct swm_region *, union arg *);
void update_ws_stack(struct workspace *);
&wpr, NULL)) {
for (i = 0; i < (int)wpr.atoms_len; i++) {
if (wpr.atoms[i] == a_takefocus)
- win->take_focus = 1;
+ win->take_focus = true;
if (wpr.atoms[i] == a_delete)
- win->can_delete = 1;
+ win->can_delete = true;
}
xcb_icccm_get_wm_protocols_reply_wipe(&wpr);
}
ws->focus_pending = win;
}
}
+
+ update_window_color(win);
raise_window(win);
}
void
setscreencolor(const char *val, int i, int c)
{
- int num_screens;
+ if (i < 0 || i >= get_screen_count())
+ return;
- num_screens = get_screen_count();
- if (i > 0 && i <= num_screens) {
- screens[i - 1].c[c].pixel = name_to_pixel(i - 1, val);
- free(screens[i - 1].c[c].name);
- if ((screens[i - 1].c[c].name = strdup(val)) == NULL)
- err(1, "strdup");
- } else if (i == -1) {
- for (i = 0; i < num_screens; i++) {
- screens[i].c[c].pixel = name_to_pixel(0, val);
- free(screens[i].c[c].name);
- if ((screens[i].c[c].name = strdup(val)) == NULL)
- err(1, "strdup");
- }
- } else
- errx(1, "invalid screen index: %d out of bounds (maximum %d)",
- i, num_screens);
+ screens[i].c[c].pixel = name_to_pixel(i, val);
+ free(screens[i].c[c].name);
+ if ((screens[i].c[c].name = strdup(val)) == NULL)
+ err(1, "strdup");
}
void
bar_pid = 0;
}
strlcpy(bar_ext, "", sizeof bar_ext);
- bar_extra = 0;
+ bar_extra = false;
}
void
{
struct ws_win *win;
int i, j, num_screens;
- int urgent[SWM_WS_MAX];
+ bool urgent[SWM_WS_MAX];
char b[8];
xcb_get_property_cookie_t c;
xcb_icccm_wm_hints_t hints;
for (i = 0; i < workspace_limit; i++)
- urgent[i] = 0;
+ urgent[i] = false;
num_screens = get_screen_count();
for (i = 0; i < num_screens; i++)
&hints, NULL) == 0)
continue;
if (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY)
- urgent[j] = 1;
+ urgent[j] = true;
}
for (i = 0; i < workspace_limit; i++) {
{
size_t len;
char b[SWM_BAR_MAX];
- int changed = 0;
+ bool changed = false;
if (!bar_extra)
return changed;
/* Append new output to bar. */
strlcat(bar_ext, b, sizeof(bar_ext));
- changed = 1;
+ changed = true;
} else {
/* Buffer output. */
strlcat(bar_ext_buf, b, sizeof(bar_ext_buf));
if (errno != EAGAIN) {
warn("bar_action failed");
bar_extra_stop();
- changed = 1;
+ changed = true;
}
return changed;
if (bar_enabled)
r->ws->bar_enabled = !r->ws->bar_enabled;
else
- bar_enabled = r->ws->bar_enabled = 1;
+ bar_enabled = r->ws->bar_enabled = true;
break;
case SWM_ARG_ID_BAR_TOGGLE:
bar_enabled = !bar_enabled;
/* do this here because the conf file is in memory */
if (!bar_extra && bar_argv[0]) {
/* launch external status app */
- bar_extra = 1;
+ bar_extra = true;
if (pipe(bar_pipe) == -1)
err(1, "pipe error");
socket_setnonblock(bar_pipe[0]);
kill(bar_pid, SIGTERM);
}
-int
+bool
isxlfd(char *s)
{
int count = 0;
DefaultColormap(display, r->s->idx), &color, &bar_font_color))
warn("Xft error: unable to allocate color.");
+ PIXEL_TO_XRENDERCOLOR(r->s->c[SWM_S_COLOR_BAR].pixel, color);
+
+ if (!XftColorAllocValue(display, DefaultVisual(display, r->s->idx),
+ DefaultColormap(display, r->s->idx), &color, &search_font_color))
+ warn("Xft error: unable to allocate color.");
+
bar_height = bar_font->height + 2 * bar_border_width;
if (bar_height < 1)
XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL
| XCB_CW_EVENT_MASK, wa);
+ /* Stack bar window above region window to start. */
+ wa[0] = r->id;
+ wa[1] = XCB_STACK_MODE_ABOVE;
+
+ xcb_configure_window(conn, r->bar->id, XCB_CONFIG_WINDOW_SIBLING |
+ XCB_CONFIG_WINDOW_STACK_MODE, wa);
+
r->bar->buffer = xcb_generate_id(conn);
xcb_create_pixmap(conn, screen->root_depth, r->bar->buffer, r->bar->id,
WIDTH(r->bar), HEIGHT(r->bar));
- if (xrandr_support)
+ if (randr_support)
xcb_randr_select_input(conn, r->bar->id,
XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE);
}
int
-count_win(struct workspace *ws, int count_transient)
+count_win(struct workspace *ws, bool count_transient)
{
struct ws_win *win;
int count = 0;
xcb_map_window(conn, win->id);
set_win_state(win, XCB_ICCCM_WM_STATE_NORMAL);
- win->mapped = 1;
+ win->mapped = true;
}
void
xcb_unmap_window(conn, win->id);
set_win_state(win, XCB_ICCCM_WM_STATE_ICONIC);
- win->mapped = 0;
+ win->mapped = false;
}
void
}
void
-spawn(int ws_idx, union arg *args, int close_fd)
+spawn(int ws_idx, union arg *args, bool close_fd)
{
int fd;
char *ret = NULL;
return (1);
}
+#define OPAQUE 0xffffffff
+void
+set_opacity(struct ws_win *win, uint32_t opacity)
+{
+ if (opacity != OPAQUE)
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id,
+ ewmh[_NET_WM_WINDOW_OPACITY].atom, XCB_ATOM_CARDINAL, 32, 1,
+ &opacity);
+ else
+ xcb_delete_property(conn, win->id,
+ ewmh[_NET_WM_WINDOW_OPACITY].atom);
+}
+
void
unfocus_win(struct ws_win *win)
{
win->ws->focus_prev = NULL;
}
- xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL,
- &win->s->c[SWM_S_COLOR_UNFOCUS].pixel);
+ update_window_color(win);
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root,
ewmh[_NET_ACTIVE_WINDOW].atom, XCB_ATOM_WINDOW, 32, 1, &none);
void
focus_win(struct ws_win *win)
{
- struct ws_win *cfw = NULL, *parent = NULL, *w;
+ struct ws_win *cfw = NULL, *parent = NULL, *w, *tmpw;
struct workspace *ws;
xcb_get_input_focus_reply_t *gifr;
DNPRINTF(SWM_D_FOCUS, "focus_win: win %#x\n", WINID(win));
- if (win == NULL)
- goto out;
-
- if (win->ws == NULL)
- goto out;
-
- if (!win->mapped)
+ if (win == NULL || win->ws == NULL || !win->mapped)
goto out;
ws = win->ws;
/* Change border to unfocused color. */
xcb_change_window_attributes(conn, cfw->id,
XCB_CW_BORDER_PIXEL,
- &cfw->s->c[SWM_S_COLOR_UNFOCUS].pixel);
+ &cfw->s->c[(MAXIMIZED(cfw) ?
+ SWM_S_COLOR_UNFOCUS_MAXIMIZED :
+ SWM_S_COLOR_UNFOCUS)].pixel);
+
+ if (composite_enabled)
+ set_opacity(cfw,
+ opacity_unfocus * OPAQUE);
} else {
unfocus_win(cfw);
}
client_msg(win, a_takefocus, last_event_time);
}
- xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL,
- &win->s->c[SWM_S_COLOR_FOCUS].pixel);
-
if (ws->cur_layout->flags & SWM_L_MAPONFOCUS ||
ws->always_raise) {
/* If a parent exists, map it first. */
map_window(parent);
/* Map siblings next. */
- TAILQ_FOREACH(w, &ws->winlist, entry)
+ TAILQ_FOREACH_SAFE(w, &ws->stack, stack_entry,
+ tmpw)
if (w != win && !ICONIC(w) &&
- win->transient == parent->id)
+ w->transient == parent->id) {
+ raise_window(w);
map_window(w);
+ }
}
/* Map focused window. */
raise_window(win);
map_window(win);
- /* Finally, map children of focus window. */
- TAILQ_FOREACH(w, &ws->winlist, entry)
- if (w->transient == win->id && !ICONIC(w))
+ /* Stack any children of focus window. */
+ TAILQ_FOREACH_SAFE(w, &ws->stack, stack_entry, tmpw)
+ if (w->transient == win->id && !ICONIC(w)) {
+ raise_window(w);
map_window(w);
+ }
} else if (tile_gap < 0 && !ABOVE(win)) {
/*
* Windows overlap in the layout.
&win->id);
}
+ if (cfw != win)
+ /* Update window border even if workspace is hidden. */
+ update_window_color(win);
+
out:
bar_draw();
struct ws_win *win;
struct workspace *new_ws, *old_ws;
xcb_window_t none = XCB_WINDOW_NONE;
- int wsid = args->id, unmap_old = 0;
+ int wsid = args->id;
+ bool unmap_old = false;
if (!(r && r->s))
return;
return;
if ((win = old_ws->focus) != NULL) {
- xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL,
- &win->s->c[SWM_S_COLOR_UNFOCUS].pixel);
+ update_window_color(win);
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->s->root,
ewmh[_NET_ACTIVE_WINDOW].atom, XCB_ATOM_WINDOW, 32, 1,
if (other_r == NULL) {
/* the other workspace is hidden, hide this one */
old_ws->r = NULL;
- unmap_old = 1;
+ unmap_old = true;
} else {
/* the other ws is visible in another region, exchange them */
other_r->ws_prior = new_ws;
{
union arg a;
struct swm_screen *s = r->s;
- int cycle_all = 0;
- int move = 0;
+ bool cycle_all = false, mv = false;
DNPRINTF(SWM_D_WS, "cyclews: id: %d, screen[%d]:%dx%d+%d+%d, ws: %d\n",
args->id, r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx);
do {
switch (args->id) {
case SWM_ARG_ID_CYCLEWS_MOVE_UP:
- move = 1;
+ mv = true;
/* FALLTHROUGH */
case SWM_ARG_ID_CYCLEWS_UP_ALL:
- cycle_all = 1;
+ cycle_all = true;
/* FALLTHROUGH */
case SWM_ARG_ID_CYCLEWS_UP:
a.id = (a.id < workspace_limit - 1) ? a.id + 1 : 0;
break;
case SWM_ARG_ID_CYCLEWS_MOVE_DOWN:
- move = 1;
+ mv = true;
/* FALLTHROUGH */
case SWM_ARG_ID_CYCLEWS_DOWN_ALL:
- cycle_all = 1;
+ cycle_all = true;
/* FALLTHROUGH */
case SWM_ARG_ID_CYCLEWS_DOWN:
a.id = (a.id > 0) ? a.id - 1 : workspace_limit - 1;
if (!cycle_visible && s->ws[a.id].r != NULL)
continue;
- if (move)
+ if (mv)
send_to_ws(r, &a);
switchws(r, &a);
if (!(r && r->ws))
goto out;
- DNPRINTF(SWM_D_FOCUS, "focus: id: %d\n", args->id);
-
cur_focus = r->ws->focus;
ws = r->ws;
wl = &ws->winlist;
+ DNPRINTF(SWM_D_FOCUS, "focus: id: %d, cur_focus: %#x\n", args->id,
+ WINID(cur_focus));
+
/* Make sure an uniconified window has focus, if one exists. */
if (cur_focus == NULL) {
cur_focus = TAILQ_FIRST(wl);
while (cur_focus != NULL && ICONIC(cur_focus))
cur_focus = TAILQ_NEXT(cur_focus, entry);
+
+ DNPRINTF(SWM_D_FOCUS, "focus: new cur_focus: %#x\n",
+ WINID(cur_focus));
}
switch (args->id) {
winfocus = TAILQ_LAST(wl, ws_win_list);
if (winfocus == cur_focus)
break;
- } while (winfocus != NULL &&
- (ICONIC(winfocus) || winfocus->id == cur_focus->transient));
+ } while (winfocus && (ICONIC(winfocus) ||
+ winfocus->id == cur_focus->transient ||
+ (cur_focus->transient != XCB_WINDOW_NONE &&
+ winfocus->transient == cur_focus->transient)));
break;
case SWM_ARG_ID_FOCUSNEXT:
if (cur_focus == NULL)
winfocus = TAILQ_FIRST(wl);
if (winfocus == cur_focus)
break;
- } while (winfocus != NULL &&
- (ICONIC(winfocus) || winfocus->id == cur_focus->transient));
+ } while (winfocus && (ICONIC(winfocus) ||
+ winfocus->id == cur_focus->transient ||
+ (cur_focus->transient != XCB_WINDOW_NONE &&
+ winfocus->transient == cur_focus->transient)));
break;
case SWM_ARG_ID_FOCUSMAIN:
if (cur_focus == NULL)
win->g_float = win->g;
win->g_float.x -= X(win->ws->r);
win->g_float.y -= Y(win->ws->r);
- win->g_floatvalid = 1;
+ win->g_floatvalid = true;
DNPRINTF(SWM_D_MISC, "store_float_geom: win %#x, g: (%d,%d)"
" %d x %d, g_float: (%d,%d) %d x %d\n", win->id, X(win), Y(win),
WIDTH(win), HEIGHT(win), win->g_float.x, win->g_float.y,
DNPRINTF(SWM_D_MISC, "update_floater: win %#x\n", win->id);
+ win->bordered = true;
+
if (FULLSCREEN(win)) {
/* _NET_WM_FULLSCREEN: fullscreen without border. */
if (!win->g_floatvalid)
store_float_geom(win);
win->g = r->g;
- win->bordered = 0;
+ win->bordered = false;
} else if (MAXIMIZED(win)) {
/* Maximize: like a single stacked window. */
if (!win->g_floatvalid)
win->g = r->g;
if (bar_enabled && ws->bar_enabled) {
- win->bordered = 1;
if (!bar_at_bottom)
Y(win) += bar_height;
HEIGHT(win) -= bar_height;
} else if (disable_border) {
- win->bordered = 0;
- } else {
- win->bordered = 1;
+ win->bordered = false;
}
if (win->bordered) {
if ((win->quirks & SWM_Q_FULLSCREEN) &&
WIDTH(win) >= WIDTH(r) && HEIGHT(win) >= HEIGHT(r)) {
/* Remove border for FULLSCREEN quirk. */
- win->bordered = 0;
+ win->bordered = false;
} else if (!MANUAL(win)) {
if (TRANS(win) && (win->quirks & SWM_Q_TRANSSZ)) {
/* Adjust size on TRANSSZ quirk. */
tmp = (g)->h; (g)->h = (g)->w; (g)->w = tmp; \
} while (0)
void
-stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip)
+stack_master(struct workspace *ws, struct swm_geometry *g, int rot, bool flip)
{
struct swm_geometry win_g, r_g = *g;
struct ws_win *win;
int w_inc = 1, h_inc, w_base = 1, h_base;
int hrh, extra = 0, h_slice, last_h = 0;
int split, colno, winno, mwin, msize, mscale;
- int remain, missing, v_slice, reconfigure = 0;
- int bordered = 1;
+ int remain, missing, v_slice;
+ bool bordered = true, reconfigure = false;
DNPRINTF(SWM_D_STACK, "stack_master: workspace: %d, rot: %s, "
"flip: %s\n", ws->idx, YESNO(rot), YESNO(flip));
/* Prepare tiling variables, if needed. */
- if ((winno = count_win(ws, 0)) > 0) {
+ if ((winno = count_win(ws, false)) > 0) {
/* Find first tiled window. */
TAILQ_FOREACH(win, &ws->winlist, entry)
if (!FLOATING(win) && !ICONIC(win))
if (disable_border && !(bar_enabled && ws->bar_enabled) &&
winno == 1){
- bordered = 0;
+ bordered = false;
win_g.w += 2 * border_width;
win_g.h += 2 * border_width;
} else {
- bordered = 1;
+ bordered = true;
}
if (rot) {
if (X(win) != win_g.y || Y(win) != win_g.x ||
WIDTH(win) != win_g.h || HEIGHT(win) != win_g.w) {
- reconfigure = 1;
+ reconfigure = true;
X(win) = win_g.y;
Y(win) = win_g.x;
WIDTH(win) = win_g.h;
} else {
if (X(win) != win_g.x || Y(win) != win_g.y ||
WIDTH(win) != win_g.w || HEIGHT(win) != win_g.h) {
- reconfigure = 1;
+ reconfigure = true;
X(win) = win_g.x;
Y(win) = win_g.y;
WIDTH(win) = win_g.w;
}
if (bordered != win->bordered) {
- reconfigure = 1;
+ reconfigure = true;
win->bordered = bordered;
}
max_stack(struct workspace *ws, struct swm_geometry *g)
{
struct swm_geometry gg = *g;
- struct ws_win *w, *win = NULL, *parent = NULL;
+ struct ws_win *w, *win = NULL, *parent = NULL, *tmpw;
int winno;
DNPRINTF(SWM_D_STACK, "max_stack: workspace: %d\n", ws->idx);
if (ws == NULL)
return;
- winno = count_win(ws, 0);
- if (winno == 0 && count_win(ws, 1) == 0)
+ winno = count_win(ws, false);
+ if (winno == 0 && count_win(ws, true) == 0)
return;
/* Figure out which top level window should be visible. */
HEIGHT(w) != gg.h) {
w->g = gg;
if (bar_enabled && ws->bar_enabled){
- w->bordered = 1;
+ w->bordered = true;
} else {
- w->bordered = 0;
+ w->bordered = false;
WIDTH(w) += 2 * border_width;
HEIGHT(w) += 2 * border_width;
}
}
}
- if (TRANS(win)) {
- parent = find_window(win->transient);
+ /* If transient, stack parent and its children. */
+ if (TRANS(win) && (parent = find_window(win->transient))) {
raise_window(parent);
- TAILQ_FOREACH(w, &ws->stack, stack_entry)
+ TAILQ_FOREACH_SAFE(w, &ws->stack, stack_entry, tmpw)
if (w->transient == parent->id)
raise_window(w);
}
+ /* Make sure focus window is on top. */
raise_window(win);
- TAILQ_FOREACH(w, &ws->stack, stack_entry)
+ /* Stack any children of focus window. */
+ TAILQ_FOREACH_SAFE(w, &ws->stack, stack_entry, tmpw)
if (w->transient == win->id)
raise_window(w);
if (win->ws->idx == wsid)
return;
- win_to_ws(win, wsid, 1);
+ win_to_ws(win, wsid, true);
- /* Set window to be focus on target ws. */
+ /* Set new focus on target ws. */
if (focus_mode != SWM_FOCUS_FOLLOW) {
+ win->ws->focus_prev = win->ws->focus;
win->ws->focus = win;
win->ws->focus_pending = NULL;
+
+ if (win->ws->focus_prev)
+ update_window_color(win->ws->focus_prev);
}
DNPRINTF(SWM_D_STACK, "send_to_ws: focus_pending: %#x, focus: %#x, "
ewmh_apply_flags(win, win->ewmh_flags & ~EWMH_F_MAXIMIZED);
ewmh_update_wm_state(win);
- /* Restack and set new focus. */
+ /* Restack and set new focus on current ws. */
if (FLOATING(win))
load_float_geom(win);
}
void
-win_to_ws(struct ws_win *win, int wsid, int unfocus)
+win_to_ws(struct ws_win *win, int wsid, bool unfocus)
{
struct ws_win *parent;
struct workspace *ws, *nws, *pws;
struct ws_win *win = NULL;
struct search_window *sw = NULL;
xcb_window_t w;
- uint32_t wa[2];
+ uint32_t wa[3];
+ xcb_screen_t *screen;
int i, width, height;
char s[8];
FILE *lfile;
if ((lfile = fdopen(select_list_pipe[1], "w")) == NULL)
return;
+ if ((screen = get_screen(r->s->idx)) == NULL)
+ errx(1, "ERROR: can't get screen %d.", r->s->idx);
+
TAILQ_INIT(&search_wl);
i = 1;
w = xcb_generate_id(conn);
wa[0] = r->s->c[SWM_S_COLOR_FOCUS].pixel;
wa[1] = r->s->c[SWM_S_COLOR_UNFOCUS].pixel;
+ wa[2] = screen->default_colormap;
if (bar_font_legacy) {
XmbTextExtents(bar_fs, s, len, &l_ibox, &l_lbox);
height = bar_font->height + 4;
}
- xcb_create_window(conn, XCB_COPY_FROM_PARENT, w, win->id, 0, 0,
+ xcb_create_window(conn, screen->root_depth, w, win->id, 0, 0,
width, height, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT,
- XCB_COPY_FROM_PARENT, XCB_CW_BACK_PIXEL |
- XCB_CW_BORDER_PIXEL, wa);
+ screen->root_visual, XCB_CW_BACK_PIXEL |
+ XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP, wa);
xcb_map_window(conn, w);
DefaultVisual(display, r->s->idx),
DefaultColormap(display, r->s->idx));
- XftDrawStringUtf8(draw, &bar_font_color, bar_font, 2,
+ XftDrawStringUtf8(draw, &search_font_color, bar_font, 2,
(HEIGHT(r->bar) + bar_font->height) / 2 -
bar_font->descent, (FcChar8 *)s, len);
++len;
}
- if((name_list = calloc(sizeof(char *), len)) == NULL)
+ if((name_list = calloc(len, sizeof(char))) == NULL)
err(1, "update_desktop_names: calloc: failed to "
"allocate memory.");
if (count == 0)
continue;
- wins = calloc(sizeof(xcb_window_t), count);
+ wins = calloc(count, sizeof(xcb_window_t));
if (wins == NULL)
err(1, "ewmh_update_client_list: calloc: failed to "
"allocate memory.");
int num_screens, i, j;
uint32_t *vals;
- vals = calloc(sizeof(uint32_t), workspace_limit * 2);
+ vals = calloc(workspace_limit * 2, sizeof(uint32_t));
if (vals == NULL)
err(1, "ewmh_update_desktops: calloc: failed to allocate "
"memory.");
}
void
+update_window_color(struct ws_win *win)
+{
+ uint32_t *pixel;
+
+ if (WS_FOCUSED(win->ws) && win->ws->focus == win) {
+ pixel = MAXIMIZED(win) ?
+ &win->s->c[SWM_S_COLOR_FOCUS_MAXIMIZED].pixel :
+ &win->s->c[SWM_S_COLOR_FOCUS].pixel;
+
+ if (composite_enabled)
+ set_opacity(win, opacity_focus * OPAQUE);
+ } else {
+ pixel = MAXIMIZED(win) ?
+ &win->s->c[SWM_S_COLOR_UNFOCUS_MAXIMIZED].pixel :
+ &win->s->c[SWM_S_COLOR_UNFOCUS].pixel;
+
+ if (composite_enabled)
+ set_opacity(win, opacity_unfocus * OPAQUE);
+ }
+
+ xcb_change_window_attributes(conn, win->id,
+ XCB_CW_BORDER_PIXEL, pixel);
+}
+
+void
update_window(struct ws_win *win)
{
uint16_t mask;
struct swm_region *r = NULL;
struct swm_geometry g;
int resize_stp = 0;
- int top = 0, left = 0, resizing;
+ int top = 0, left = 0;
int dx, dy;
xcb_cursor_t cursor;
xcb_query_pointer_reply_t *xpr = NULL;
xcb_generic_event_t *evt;
xcb_motion_notify_event_t *mne;
+ bool resizing;
if (win == NULL)
return;
XCB_CURRENT_TIME),
xcb_flush(conn);
- resizing = 1;
+ resizing = true;
while (resizing && (evt = xcb_wait_for_event(conn))) {
switch (XCB_EVENT_RESPONSE_TYPE(evt)) {
case XCB_BUTTON_RELEASE:
DNPRINTF(SWM_D_EVENT, "resize: BUTTON_RELEASE\n");
- resizing = 0;
+ resizing = false;
break;
case XCB_MOTION_NOTIFY:
mne = (xcb_motion_notify_event_t *)evt;
if (clear_maximized(r->ws) > 0)
stack();
- win_to_ws(win, r->ws->idx, 0);
+ win_to_ws(win, r->ws->idx, false);
/* Set focus on new ws. */
unfocus_win(r->ws->focus);
{
struct swm_region *r;
xcb_timestamp_t timestamp = 0;
- int move_stp = 0, moving, restack = 0;
+ int move_stp = 0;
xcb_query_pointer_reply_t *qpr = NULL;
xcb_generic_event_t *evt;
xcb_motion_notify_event_t *mne;
+ bool moving, restack = false;
if (win == NULL)
return;
if (!(ABOVE(win) || TRANS(win)) || MAXIMIZED(win)) {
store_float_geom(win);
- restack = 1;
+ restack = true;
}
ewmh_apply_flags(win, (win->ewmh_flags | SWM_F_MANUAL | EWMH_F_ABOVE) &
SWM_CW_SOFTBOUNDARY);
update_window(win);
xcb_flush(conn);
- moving = 1;
+ moving = true;
while (moving && (evt = xcb_wait_for_event(conn))) {
switch (XCB_EVENT_RESPONSE_TYPE(evt)) {
case XCB_BUTTON_RELEASE:
DNPRINTF(SWM_D_EVENT, "move: BUTTON_RELEASE\n");
- moving = 0;
+ moving = false;
break;
case XCB_MOTION_NOTIFY:
mne = (xcb_motion_notify_event_t *)evt;
strdup(r->s->c[SWM_S_COLOR_FOCUS].name))
== NULL)
err(1, "spawn_custom color focus");
+ } else if (strcasecmp(ap, "$color_focus_maximized") == 0) {
+ if ((real_args[c] =
+ strdup(r->s->c[SWM_S_COLOR_FOCUS_MAXIMIZED].name))
+ == NULL)
+ err(1, "spawn_custom color focus maximized");
} else if (strcasecmp(ap, "$color_unfocus") == 0) {
if ((real_args[c] =
strdup(r->s->c[SWM_S_COLOR_UNFOCUS].name))
== NULL)
err(1, "spawn_custom color unfocus");
+ } else if (strcasecmp(ap, "$color_unfocus_maximized") == 0) {
+ if ((real_args[c] =
+ strdup(r->s->c[SWM_S_COLOR_UNFOCUS_MAXIMIZED].name))
+ == NULL)
+ err(1, "spawn_custom color unfocus maximized");
} else if (strcasecmp(ap, "$region_index") == 0) {
if (asprintf(&real_args[c], "%d",
get_region_index(r) + 1) < 1)
return;
a.argv = real_args;
if (fork() == 0)
- spawn(r->ws->idx, &a, 1);
+ spawn(r->ws->idx, &a, true);
for (i = 0; i < spawn_argc; i++)
free(real_args[i]);
err(1, "dup2");
close(select_list_pipe[1]);
close(select_resp_pipe[0]);
- spawn(r->ws->idx, &a, 0);
+ spawn(r->ws->idx, &a, false);
break;
default: /* parent */
close(select_list_pipe[0]);
/* Argument tokenizer. */
char *
argsep(char **sp) {
- int single_quoted = 0, double_quoted = 0;
char *arg, *cp, *next;
+ bool single_quoted = false, double_quoted = false;
if (*sp == NULL)
return NULL;
spawn_insert(const char *name, const char *args, int flags)
{
struct spawn_prog *sp;
- char *arg, *dup, *ptr;
+ char *arg, *cp, *ptr;
DNPRINTF(SWM_D_SPAWN, "spawn_insert: %s[%s]\n", name, args);
err(1, "spawn_insert: strdup");
/* Convert the arguments to an argument list. */
- if ((ptr = dup = strdup(args)) == NULL)
+ if ((ptr = cp = strdup(args)) == NULL)
err(1, "spawn_insert: strdup");
while ((arg = argsep(&ptr)) != NULL) {
/* Null argument; skip it. */
if ((sp->argv[sp->argc - 1] = strdup(arg)) == NULL)
err(1, "spawn_insert: strdup");
}
- free(dup);
+ free(cp);
sp->flags = flags;
"FOCUSPREV",
"NOFOCUSONMAP",
"FOCUSONMAP_SINGLE",
+ "OBEYAPPFOCUSREQ",
+ "IGNOREPID",
+ "IGNORESPAWNWS",
};
/* SWM_Q_WS: retain '|' for back compat for now (2009-08-11) */
unsigned long quirk)
{
struct quirk *qp;
- int failed = 0;
char *str;
+ bool failed = false;
DNPRINTF(SWM_D_QUIRK, "quirk_insert: class: %s, instance: %s, name: %s,"
" value: %lu\n", class, instance, name, quirk);
if (regcomp(&qp->regex_class, str, REG_EXTENDED | REG_NOSUB)) {
add_startup_exception("regex failed to compile quirk 'class' "
"field: %s", class);
- failed = 1;
+ failed = true;
}
DNPRINTF(SWM_D_QUIRK, "quirk_insert: compiled: %s\n", str);
free(str);
if (regcomp(&qp->regex_instance, str, REG_EXTENDED | REG_NOSUB)) {
add_startup_exception("regex failed to compile quirk 'instance'"
" field: %s", instance);
- failed = 1;
+ failed = true;
}
DNPRINTF(SWM_D_QUIRK, "quirk_insert: compiled: %s\n", str);
free(str);
if (regcomp(&qp->regex_name, str, REG_EXTENDED | REG_NOSUB)) {
add_startup_exception("regex failed to compile quirk 'name' "
"field: %s", name);
- failed = 1;
+ failed = true;
}
DNPRINTF(SWM_D_QUIRK, "quirk_insert: compiled: %s\n", str);
free(str);
SWM_S_BOUNDARY_WIDTH,
SWM_S_CLOCK_ENABLED,
SWM_S_CLOCK_FORMAT,
+ SWM_S_COMPOSITE_ENABLED,
SWM_S_CYCLE_EMPTY,
SWM_S_CYCLE_VISIBLE,
SWM_S_DIALOG_RATIO,
SWM_S_FOCUS_DEFAULT,
SWM_S_FOCUS_MODE,
SWM_S_ICONIC_ENABLED,
+ SWM_S_JAVA_WORKAROUND,
+ SWM_S_OPACITY_FOCUS,
+ SWM_S_OPACITY_UNFOCUS,
SWM_S_REGION_PADDING,
SWM_S_SPAWN_ORDER,
SWM_S_SPAWN_TERM,
err(1, "setconfvalue: bar_action");
break;
case SWM_S_BAR_AT_BOTTOM:
- bar_at_bottom = atoi(value);
+ bar_at_bottom = (atoi(value) != 0);
break;
case SWM_S_BAR_BORDER_WIDTH:
bar_border_width = atoi(value);
/* No longer needed; leave to not break old conf files. */
break;
case SWM_S_BAR_ENABLED:
- bar_enabled = atoi(value);
+ bar_enabled = (atoi(value) != 0);
break;
case SWM_S_BAR_ENABLED_WS:
ws_id = atoi(selector) - 1;
num_screens = get_screen_count();
for (i = 0; i < num_screens; i++) {
ws = (struct workspace *)&screens[i].ws;
- ws[ws_id].bar_enabled = atoi(value);
+ ws[ws_id].bar_enabled = (atoi(value) != 0);
}
break;
case SWM_S_BAR_FONT:
if (*b == '\0')
continue;
if (!isxlfd(b)) {
- bar_font_legacy = 0;
+ bar_font_legacy = false;
break;
}
}
boundary_width = 0;
break;
case SWM_S_CLOCK_ENABLED:
- clock_enabled = atoi(value);
+ clock_enabled = (atoi(value) != 0);
break;
case SWM_S_CLOCK_FORMAT:
#ifndef SWM_DENY_CLOCK_FORMAT
#endif
break;
case SWM_S_CYCLE_EMPTY:
- cycle_empty = atoi(value);
+ cycle_empty = (atoi(value) != 0);
break;
case SWM_S_CYCLE_VISIBLE:
- cycle_visible = atoi(value);
+ cycle_visible = (atoi(value) != 0);
break;
case SWM_S_DIALOG_RATIO:
dialog_ratio = atof(value);
dialog_ratio = .6;
break;
case SWM_S_DISABLE_BORDER:
- disable_border = atoi(value);
+ disable_border = (atoi(value) != 0);
break;
case SWM_S_FOCUS_CLOSE:
if (strcmp(value, "first") == 0)
errx(1, "focus_close");
break;
case SWM_S_FOCUS_CLOSE_WRAP:
- focus_close_wrap = atoi(value);
+ focus_close_wrap = (atoi(value) != 0);
break;
case SWM_S_FOCUS_DEFAULT:
if (strcmp(value, "last") == 0)
errx(1, "focus_mode");
break;
case SWM_S_ICONIC_ENABLED:
- iconic_enabled = atoi(value);
+ iconic_enabled = (atoi(value) != 0);
+ break;
+ case SWM_S_JAVA_WORKAROUND:
+ java_workaround = (atoi(value) != 0);
break;
case SWM_S_REGION_PADDING:
region_padding = atoi(value);
/* No longer needed; leave to not break old conf files. */
break;
case SWM_S_STACK_ENABLED:
- stack_enabled = atoi(value);
+ stack_enabled = (atoi(value) != 0);
break;
case SWM_S_TERM_WIDTH:
term_width = atoi(value);
tile_gap = atoi(value);
break;
case SWM_S_URGENT_ENABLED:
- urgent_enabled = atoi(value);
+ urgent_enabled = (atoi(value) != 0);
+ break;
+ case SWM_S_COMPOSITE_ENABLED:
+ composite_enabled = atoi(value);
+ break;
+ case SWM_S_OPACITY_FOCUS:
+ opacity_focus = atof(value);
+ if (opacity_focus > 1.0)
+ opacity_focus = 1.0;
+ else if (opacity_focus < 0.0)
+ opacity_focus = 0.0;
+ break;
+ case SWM_S_OPACITY_UNFOCUS:
+ opacity_unfocus = atof(value);
+ if (opacity_unfocus > 1.0)
+ opacity_unfocus = 1.0;
+ else if (opacity_unfocus < 0.0)
+ opacity_unfocus = 0.0;
break;
case SWM_S_VERBOSE_LAYOUT:
- verbose_layout = atoi(value);
+ verbose_layout = (atoi(value) != 0);
for (i = 0; layouts[i].l_stack != NULL; i++) {
if (verbose_layout)
layouts[i].l_string = fancy_stacker;
}
break;
case SWM_S_WINDOW_CLASS_ENABLED:
- window_class_enabled = atoi(value);
+ window_class_enabled = (atoi(value) != 0);
break;
case SWM_S_WINDOW_INSTANCE_ENABLED:
- window_instance_enabled = atoi(value);
+ window_instance_enabled = (atoi(value) != 0);
break;
case SWM_S_WINDOW_NAME_ENABLED:
- window_name_enabled = atoi(value);
+ window_name_enabled = (atoi(value) != 0);
break;
case SWM_S_WORKSPACE_LIMIT:
workspace_limit = atoi(value);
int
setconfcolor(const char *selector, const char *value, int flags)
{
- setscreencolor(value,
- (selector == NULL || strlen(selector) == 0) ? -1 : atoi(selector),
- flags);
+ int first, last, i = 0, num_screens;
+
+ num_screens = get_screen_count();
+
+ /* conf screen indices begin at 1; treat vals <= 0 as 'all screens.' */
+ if (selector == NULL || strlen(selector) == 0 ||
+ (last = atoi(selector) - 1) < 0) {
+ first = 0;
+ last = num_screens - 1;
+ } else {
+ first = last;
+ }
+
+ if (last >= num_screens) {
+ add_startup_exception("invalid screen index: %d out of bounds "
+ "(maximum %d)", last + 1, num_screens);
+ return (1);
+ }
+
+ for (i = first; i <= last; ++i) {
+ setscreencolor(value, i, flags);
+
+ /*
+ * When setting focus/unfocus colors, we need to also
+ * set maximize colors to match if they haven't been customized.
+ */
+ if (flags == SWM_S_COLOR_FOCUS &&
+ !screens[i].c[SWM_S_COLOR_FOCUS_MAXIMIZED].manual)
+ setscreencolor(value, i, SWM_S_COLOR_FOCUS_MAXIMIZED);
+ else if (flags == SWM_S_COLOR_UNFOCUS &&
+ !screens[i].c[SWM_S_COLOR_UNFOCUS_MAXIMIZED].manual)
+ setscreencolor(value, i, SWM_S_COLOR_UNFOCUS_MAXIMIZED);
+
+ screens[i].c[flags].manual = 1;
+ }
+
return (0);
}
a.argv[argc] = NULL;
if ((pid = fork()) == 0) {
- spawn(ws_id, &a, 1);
+ spawn(ws_id, &a, true);
/* NOTREACHED */
_exit(1);
}
int
setlayout(const char *selector, const char *value, int flags)
{
- int ws_id, i, x, mg, ma, si, ar, f = 0;
+ struct workspace *ws;
+ int ws_id, i, x, mg, ma, si, ar;
int st = SWM_V_STACK, num_screens;
char s[1024];
- struct workspace *ws;
+ bool f = false;
/* suppress unused warnings since vars are needed */
(void)selector;
st = SWM_V_STACK;
else if (strcasecmp(s, "vertical_flip") == 0) {
st = SWM_V_STACK;
- f = 1;
+ f = true;
} else if (strcasecmp(s, "horizontal") == 0)
st = SWM_H_STACK;
else if (strcasecmp(s, "horizontal_flip") == 0) {
st = SWM_H_STACK;
- f = 1;
+ f = true;
} else if (strcasecmp(s, "fullscreen") == 0)
st = SWM_MAX_STACK;
else
ws = (struct workspace *)&screens[i].ws;
ws[ws_id].cur_layout = &layouts[st];
- ws[ws_id].always_raise = ar;
+ ws[ws_id].always_raise = (ar != 0);
if (st == SWM_MAX_STACK)
continue;
ws[ws_id].cur_layout->l_config(&ws[ws_id],
mg >= 0 ? SWM_ARG_ID_MASTERGROW :
SWM_ARG_ID_MASTERSHRINK);
- stack();
}
/* master add */
for (x = 0; x < abs(ma); x++) {
ws[ws_id].cur_layout->l_config(&ws[ws_id],
ma >= 0 ? SWM_ARG_ID_MASTERADD :
SWM_ARG_ID_MASTERDEL);
- stack();
}
/* stack inc */
for (x = 0; x < abs(si); x++) {
ws[ws_id].cur_layout->l_config(&ws[ws_id],
si >= 0 ? SWM_ARG_ID_STACKINC :
SWM_ARG_ID_STACKDEC);
- stack();
}
/* Apply flip */
if (f) {
ws[ws_id].cur_layout->l_config(&ws[ws_id],
SWM_ARG_ID_FLIPLAYOUT);
- stack();
}
}
- focus_flush();
-
return (0);
}
{ "clock_enabled", setconfvalue, SWM_S_CLOCK_ENABLED },
{ "clock_format", setconfvalue, SWM_S_CLOCK_FORMAT },
{ "color_focus", setconfcolor, SWM_S_COLOR_FOCUS },
+ { "color_focus_maximized", setconfcolor, SWM_S_COLOR_FOCUS_MAXIMIZED },
{ "color_unfocus", setconfcolor, SWM_S_COLOR_UNFOCUS },
+ { "color_unfocus_maximized", setconfcolor, SWM_S_COLOR_UNFOCUS_MAXIMIZED },
+ { "composite_enabled", setconfvalue, SWM_S_COMPOSITE_ENABLED },
{ "cycle_empty", setconfvalue, SWM_S_CYCLE_EMPTY },
{ "cycle_visible", setconfvalue, SWM_S_CYCLE_VISIBLE },
{ "dialog_ratio", setconfvalue, SWM_S_DIALOG_RATIO },
{ "focus_default", setconfvalue, SWM_S_FOCUS_DEFAULT },
{ "focus_mode", setconfvalue, SWM_S_FOCUS_MODE },
{ "iconic_enabled", setconfvalue, SWM_S_ICONIC_ENABLED },
+ { "java_workaround", setconfvalue, SWM_S_JAVA_WORKAROUND },
{ "keyboard_mapping", setkeymapping, 0 },
{ "layout", setlayout, 0 },
{ "modkey", setconfmodkey, 0 },
+ { "opacity_focus", setconfvalue, SWM_S_OPACITY_FOCUS },
+ { "opacity_unfocus", setconfvalue, SWM_S_OPACITY_UNFOCUS },
{ "program", setconfspawn, 0 },
{ "quirk", setconfquirk, 0 },
{ "region", setconfregion, 0 },
return;
/* force bar to be enabled due to exception */
- bar_enabled = 1;
+ bar_enabled = true;
va_start(ap, fmt);
_add_startup_exception(fmt, ap);
}
int
-get_ws_idx(xcb_window_t id)
+get_ws_idx(struct ws_win *win)
{
xcb_get_property_reply_t *gpr;
int ws_idx = -1;
+ if (win == NULL)
+ return -1;
+
gpr = xcb_get_property_reply(conn,
- xcb_get_property(conn, 0, id, ewmh[_NET_WM_DESKTOP].atom,
+ xcb_get_property(conn, 0, win->id, ewmh[_NET_WM_DESKTOP].atom,
XCB_ATOM_CARDINAL, 0, 1),
NULL);
if (gpr) {
free(gpr);
}
- if (ws_idx == -1)
- if ((ws_idx = get_swm_ws(id)) != -1)
- xcb_delete_property(conn, id, a_swm_ws);
+ if (ws_idx == -1 && !(win->quirks & SWM_Q_IGNORESPAWNWS))
+ ws_idx = get_swm_ws(win->id);
if (ws_idx > workspace_limit - 1 || ws_idx < -1)
ws_idx = -1;
- DNPRINTF(SWM_D_PROP, "get_ws_idx: win %#x, ws_idx: %d\n", id, ws_idx);
+ DNPRINTF(SWM_D_PROP, "get_ws_idx: win %#x, ws_idx: %d\n", win->id,
+ ws_idx);
return ws_idx;
}
struct ws_win *
-manage_window(xcb_window_t id, int mapped)
+manage_window(xcb_window_t id, int spawn_pos, bool mapped)
{
struct ws_win *win, *ww;
struct swm_region *r;
HEIGHT(win) = gr->height;
X(win) = gr->x + gr->border_width - border_width;
Y(win) = gr->y + gr->border_width - border_width;
- win->bordered = 1;
+ win->bordered = true;
win->mapped = mapped;
win->s = r->s; /* this never changes */
xcb_change_window_attributes(conn, win->id, XCB_CW_BORDER_PIXEL |
XCB_CW_EVENT_MASK, wa);
+ if (composite_enabled)
+ set_opacity(win, opacity_unfocus * OPAQUE);
+
/* Get WM_SIZE_HINTS. */
xcb_icccm_get_wm_normal_hints_reply(conn,
xcb_icccm_get_wm_normal_hints(conn, win->id),
/* Get WM_PROTOCOLS. */
get_wm_protocols(win);
- /* Figure out which workspace the window belongs to. */
- if ((p = find_pid(window_get_pid(win->id))) != NULL) {
- win->ws = &r->s->ws[p->ws];
- TAILQ_REMOVE(&pidlist, p, entry);
- free(p);
- p = NULL;
- } else if ((ws_idx = get_ws_idx(win->id)) != -1 &&
- !TRANS(win)) {
- /* _SWM_WS is set; use that. */
- win->ws = &r->s->ws[ws_idx];
- } else if (trans && (ww = find_window(trans)) != NULL) {
- /* Launch transients in the same ws as parent. */
- win->ws = ww->ws;
- } else {
- win->ws = r->ws;
- }
-
- /* Set the _NET_WM_DESKTOP atom. */
- DNPRINTF(SWM_D_PROP, "manage_window: set _NET_WM_DESKTOP: %d\n",
- win->ws->idx);
- xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id,
- ewmh[_NET_WM_DESKTOP].atom, XCB_ATOM_CARDINAL, 32, 1, &win->ws->idx);
-
- /* WS must already be set for this to work. */
- store_float_geom(win);
-
/* Set initial quirks based on EWMH. */
ewmh_autoquirk(win);
/* java is retarded so treat it special */
if (strstr(instance, "sun-awt")) {
DNPRINTF(SWM_D_CLASS, "manage_window: java window detected.\n");
- win->java = 1;
+ win->java = true;
}
TAILQ_FOREACH(qp, &quirks, entry) {
fake_keypress(win, XK_KP_Add, XCB_MOD_MASK_SHIFT);
}
+ /* Figure out which workspace the window belongs to. */
+ if (!(win->quirks & SWM_Q_IGNOREPID) &&
+ (p = find_pid(window_get_pid(win->id))) != NULL) {
+ win->ws = &r->s->ws[p->ws];
+ TAILQ_REMOVE(&pidlist, p, entry);
+ free(p);
+ p = NULL;
+ } else if ((ws_idx = get_ws_idx(win)) != -1 &&
+ !TRANS(win)) {
+ /* _SWM_WS is set; use that. */
+ win->ws = &r->s->ws[ws_idx];
+ } else if (trans && (ww = find_window(trans)) != NULL) {
+ /* Launch transients in the same ws as parent. */
+ win->ws = ww->ws;
+ } else {
+ win->ws = r->ws;
+ }
+
+ /* Set the _NET_WM_DESKTOP atom. */
+ DNPRINTF(SWM_D_PROP, "manage_window: set _NET_WM_DESKTOP: %d\n",
+ win->ws->idx);
+ xcb_change_property(conn, XCB_PROP_MODE_REPLACE, win->id,
+ ewmh[_NET_WM_DESKTOP].atom, XCB_ATOM_CARDINAL, 32, 1, &win->ws->idx);
+
+ /* Remove any _SWM_WS now that we set _NET_WM_DESKTOP. */
+ xcb_delete_property(conn, win->id, a_swm_ws);
+
+ /* WS must already be set for this to work. */
+ store_float_geom(win);
+
/* Make sure window is positioned inside its region, if its active. */
if (win->ws->r) {
region_containment(win, r, SWM_CW_ALLSIDES |
/* Figure out where to stack the window in the workspace. */
if (trans && (ww = find_window(trans)))
TAILQ_INSERT_AFTER(&win->ws->winlist, ww, win, entry);
- else if (win->ws->focus && spawn_position == SWM_STACK_ABOVE)
+ else if (win->ws->focus && spawn_pos == SWM_STACK_ABOVE)
TAILQ_INSERT_AFTER(&win->ws->winlist, win->ws->focus, win,
entry);
- else if (win->ws->focus && spawn_position == SWM_STACK_BELOW)
+ else if (win->ws->focus && spawn_pos == SWM_STACK_BELOW)
TAILQ_INSERT_BEFORE(win->ws->focus, win, entry);
- else switch (spawn_position) {
+ else switch (spawn_pos) {
default:
case SWM_STACK_TOP:
case SWM_STACK_ABOVE:
struct ws_win *win = NULL;
struct swm_region *r, *old_r;
int i;
- int handled = 0;
+ bool handled = false;
DNPRINTF(SWM_D_EVENT, "buttonpress: win (x,y): %#x (%d,%d), "
"detail: %u, time: %u, root (x,y): %#x (%d,%d), child: %#x, "
/* Clear bar since empty. */
bar_draw();
- handled = 1;
+ handled = true;
goto out;
}
}
buttons[i].button == e->detail &&
CLEANMASK(buttons[i].mask) == CLEANMASK(e->state)) {
buttons[i].func(win, &buttons[i].args);
- handled = 1;
+ handled = true;
}
out:
{
struct ws_win *win;
struct swm_region *r = NULL;
- int new = 0, i = 0;
- uint16_t mask = 0;
+ int i = 0;
uint32_t wc[7] = {0};
+ uint16_t mask = 0;
+ bool new = false;
if ((win = find_window(e->window)) == NULL)
if ((win = find_unmanaged_window(e->window)) == NULL)
- new = 1;
+ new = true;
#ifdef SWM_DEBUG
if (swm_debug & SWM_D_EVENT) {
if (e->value_mask & XCB_CONFIG_WINDOW_HEIGHT)
win->g_float.h = e->height;
- win->g_floatvalid = 1;
+ win->g_floatvalid = true;
if (!MAXIMIZED(win) && !FULLSCREEN(win) &&
(TRANS(win) || (ABOVE(win) &&
return;
}
} else {
+ if (e->mode == XCB_NOTIFY_MODE_NORMAL &&
+ e->detail == XCB_NOTIFY_DETAIL_INFERIOR) {
+ DNPRINTF(SWM_D_EVENT, "enternotify: entering from "
+ "inferior; ignoring\n");
+ return;
+ }
+
focus_win(get_focus_magic(win));
}
DNPRINTF(SWM_D_EVENT, "mapnotify: win %#x\n", e->window);
- if ((win = manage_window(e->window, 1)) == NULL)
+ if ((win = manage_window(e->window, spawn_position, true)) == NULL)
return;
ws = win->ws;
stack();
}
- win->mapped = 1;
+ win->mapped = true;
set_win_state(win, XCB_ICCCM_WM_STATE_NORMAL);
if (focus_mode != SWM_FOCUS_FOLLOW && WS_FOCUSED(win->ws)) {
goto out;
}
- win = manage_window(e->window,
+ win = manage_window(e->window, spawn_position,
(war->map_state == XCB_MAP_STATE_VIEWABLE));
if (win == NULL)
goto out;
return;
ws = win->ws;
- win->mapped = 0;
+ win->mapped = false;
/* If win was focused, make sure to focus on something else. */
if (win == ws->focus) {
focus_flush();
}
+#ifdef SWM_DEBUG
+char *
+get_source_type_label(uint32_t type)
+{
+ char *label;
+
+ switch (type) {
+ case EWMH_SOURCE_TYPE_NONE:
+ label = "None";
+ break;
+ case EWMH_SOURCE_TYPE_NORMAL:
+ label = "Normal";
+ break;
+ case EWMH_SOURCE_TYPE_OTHER:
+ label = "Other";
+ break;
+ default:
+ label = "Invalid";
+ }
+
+ return label;
+}
+#endif
+
void
clientmessage(xcb_client_message_event_t *e)
{
break;
}
- if (r && e->data.data32[0] <
- (uint32_t)workspace_limit) {
+ if (r && e->data.data32[0] < (uint32_t)workspace_limit) {
a.id = e->data.data32[0];
switchws(r, &a);
focus_flush();
}
if (e->type == ewmh[_NET_ACTIVE_WINDOW].atom) {
- DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_ACTIVE_WINDOW\n");
- if (WS_FOCUSED(win->ws))
- focus_win(win);
- else
- win->ws->focus_pending = win;
+ DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_ACTIVE_WINDOW, "
+ "source_type: %s(%d)\n",
+ get_source_type_label(e->data.data32[0]),
+ e->data.data32[0]);
+
+ /*
+ * Allow focus changes that are a result of direct user
+ * action and from applications that use the old EWMH spec.
+ */
+ if (e->data.data32[0] != EWMH_SOURCE_TYPE_NORMAL ||
+ win->quirks & SWM_Q_OBEYAPPFOCUSREQ) {
+ if (WS_FOCUSED(win->ws))
+ focus_win(win);
+ else
+ win->ws->focus_pending = win;
+ }
} else if (e->type == ewmh[_NET_CLOSE_WINDOW].atom) {
DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_CLOSE_WINDOW\n");
if (win->can_delete)
DNPRINTF(SWM_D_EVENT, "clientmessage: _NET_WM_DESKTOP\n");
r = win->ws->r;
- win_to_ws(win, e->data.data32[0], 1);
+ win_to_ws(win, e->data.data32[0], true);
/* Restack if either the source or destination ws is mapped. */
if (r != NULL || win->ws->r != NULL) {
}
void
-scan_xrandr(int i)
+scan_randr(int idx)
{
#ifdef SWM_XRR_HAS_CRTC
int c;
xcb_randr_crtc_t *crtc;
xcb_screen_t *screen;
- DNPRINTF(SWM_D_MISC, "scan_xrandr: screen: %d\n", i);
+ DNPRINTF(SWM_D_MISC, "scan_randr: screen: %d\n", idx);
- if ((screen = get_screen(i)) == NULL)
- errx(1, "ERROR: can't get screen %d.", i);
+ if ((screen = get_screen(idx)) == NULL)
+ errx(1, "ERROR: can't get screen %d.", idx);
num_screens = get_screen_count();
- if (i >= num_screens)
- errx(1, "scan_xrandr: invalid screen");
+ if (idx >= num_screens)
+ errx(1, "scan_randr: invalid screen");
/* remove any old regions */
- while ((r = TAILQ_FIRST(&screens[i].rl)) != NULL) {
+ while ((r = TAILQ_FIRST(&screens[idx].rl)) != NULL) {
r->ws->old_r = r->ws->r = NULL;
bar_cleanup(r);
xcb_destroy_window(conn, r->id);
- TAILQ_REMOVE(&screens[i].rl, r, entry);
- TAILQ_INSERT_TAIL(&screens[i].orl, r, entry);
+ TAILQ_REMOVE(&screens[idx].rl, r, entry);
+ TAILQ_INSERT_TAIL(&screens[idx].orl, r, entry);
}
outputs = 0;
/* map virtual screens onto physical screens */
#ifdef SWM_XRR_HAS_CRTC
- if (xrandr_support) {
+ if (randr_support) {
src = xcb_randr_get_screen_resources_current(conn,
- screens[i].root);
+ screens[idx].root);
srr = xcb_randr_get_screen_resources_current_reply(conn, src,
NULL);
if (srr == NULL) {
- new_region(&screens[i], 0, 0,
+ new_region(&screens[idx], 0, 0,
screen->width_in_pixels,
screen->height_in_pixels);
goto out;
}
if (cir->mode == 0)
- new_region(&screens[i], 0, 0,
+ new_region(&screens[idx], 0, 0,
screen->width_in_pixels,
screen->height_in_pixels);
else
- new_region(&screens[i],
+ new_region(&screens[idx],
cir->x, cir->y, cir->width, cir->height);
free(cir);
}
#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,
+ if (TAILQ_EMPTY(&screens[idx].rl))
+ new_region(&screens[idx], 0, 0, screen->width_in_pixels,
screen->height_in_pixels);
out:
/* Cleanup unused previously visible workspaces. */
- TAILQ_FOREACH(r, &screens[i].orl, entry) {
+ TAILQ_FOREACH(r, &screens[idx].orl, entry) {
TAILQ_FOREACH(win, &r->ws->winlist, entry)
unmap_window(win);
r->ws->state = SWM_WS_STATE_HIDDEN;
/* The screen shouldn't focus on an unused region. */
- if (screens[i].r_focus == r)
- screens[i].r_focus = NULL;
+ if (screens[idx].r_focus == r)
+ screens[idx].r_focus = NULL;
}
- DNPRINTF(SWM_D_MISC, "scan_xrandr: done.\n");
+ DNPRINTF(SWM_D_MISC, "scan_randr: done.\n");
}
void
errx(1, "screenchange: screen not found");
/* brute force for now, just re-enumerate the regions */
- scan_xrandr(i);
+ scan_randr(i);
#ifdef SWM_DEBUG
print_win_geom(e->root);
{
struct swm_region *r = NULL;
xcb_window_t *wins = NULL, trans, *cwins = NULL;
- int i, j, k, n, no, num_screens, manage, mapped;
+ int i, j, k, n, no, num_screens;
uint8_t state;
+ bool manage, mapped;
xcb_query_tree_cookie_t qtc;
xcb_query_tree_reply_t *qtr;
manage = state != XCB_ICCCM_WM_STATE_WITHDRAWN;
mapped = gar->map_state == XCB_MAP_STATE_VIEWABLE;
if (mapped || manage)
- manage_window(wins[j], mapped);
+ manage_window(wins[j], SWM_STACK_TOP, mapped);
free(gar);
}
/* transient windows */
pc = xcb_icccm_get_wm_transient_for(conn, wins[j]);
if (xcb_icccm_get_wm_transient_for_reply(conn, pc,
&trans, NULL) && manage)
- manage_window(wins[j], mapped);
+ manage_window(wins[j], SWM_STACK_TOP, mapped);
free(gar);
}
free(qtr);
err(1, "setup_screens: calloc: failed to allocate memory for "
"screens");
- /* initial Xrandr setup */
- xrandr_support = 0;
+ /* Initial RandR setup. */
+ randr_support = false;
qep = xcb_get_extension_data(conn, &xcb_randr_id);
if (qep->present) {
c = xcb_randr_query_version(conn, 1, 1);
r = xcb_randr_query_version_reply(conn, c, NULL);
if (r) {
if (r->major_version >= 1) {
- xrandr_support = 1;
- xrandr_eventbase = qep->first_event;
+ randr_support = true;
+ randr_eventbase = qep->first_event;
}
free(r);
}
screens[i].root = screen->root;
/* set default colors */
- setscreencolor("red", i + 1, SWM_S_COLOR_FOCUS);
- setscreencolor("rgb:88/88/88", i + 1, SWM_S_COLOR_UNFOCUS);
- setscreencolor("rgb:00/80/80", i + 1, SWM_S_COLOR_BAR_BORDER);
- setscreencolor("rgb:00/40/40", i + 1,
+ setscreencolor("red", i, SWM_S_COLOR_FOCUS);
+ setscreencolor("rgb:88/88/88", i, SWM_S_COLOR_UNFOCUS);
+ setscreencolor("rgb:00/80/80", i, SWM_S_COLOR_BAR_BORDER);
+ setscreencolor("rgb:00/40/40", i,
SWM_S_COLOR_BAR_BORDER_UNFOCUS);
- setscreencolor("black", i + 1, SWM_S_COLOR_BAR);
- setscreencolor("rgb:a0/a0/a0", i + 1, SWM_S_COLOR_BAR_FONT);
+ setscreencolor("black", i, SWM_S_COLOR_BAR);
+ setscreencolor("rgb:a0/a0/a0", i, SWM_S_COLOR_BAR_FONT);
+ setscreencolor("red", i, SWM_S_COLOR_FOCUS_MAXIMIZED);
+ setscreencolor("rgb:88/88/88", i,
+ SWM_S_COLOR_UNFOCUS_MAXIMIZED);
/* create graphics context on screen */
screens[i].bar_gc = xcb_generate_id(conn);
ws = &screens[i].ws[j];
ws->idx = j;
ws->name = NULL;
- ws->bar_enabled = 1;
+ ws->bar_enabled = true;
ws->focus = NULL;
ws->focus_prev = NULL;
ws->focus_pending = NULL;
ws->cur_layout->l_string(ws);
}
- scan_xrandr(i);
+ scan_randr(i);
- if (xrandr_support)
+ if (randr_support)
xcb_randr_select_input(conn, screens[i].root,
XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE);
}
void
shutdown_cleanup(void)
{
- int i, num_screens;
+ int i, num_screens;
/* disable alarm because the following code may not be interrupted */
alarm(0);
if (screens[i].bar_gc != XCB_NONE)
xcb_free_gc(conn, screens[i].bar_gc);
- if (!bar_font_legacy)
+ if (!bar_font_legacy) {
XftColorFree(display, DefaultVisual(display, i),
DefaultColormap(display, i), &bar_font_color);
+ XftColorFree(display, DefaultVisual(display, i),
+ DefaultColormap(display, i), &search_font_color);
+ }
}
if (bar_font_legacy)
void
event_handle(xcb_generic_event_t *evt)
{
- uint8_t type = XCB_EVENT_RESPONSE_TYPE(evt);
+ uint8_t type = XCB_EVENT_RESPONSE_TYPE(evt);
DNPRINTF(SWM_D_EVENT, "XCB Event: %s(%d), seq %u\n",
xcb_event_get_label(XCB_EVENT_RESPONSE_TYPE(evt)),
/*EVENT(XCB_VISIBILITY_NOTIFY, );*/
#undef EVENT
}
- if (type - xrandr_eventbase == XCB_RANDR_SCREEN_CHANGE_NOTIFY)
+ if (type - randr_eventbase == XCB_RANDR_SCREEN_CHANGE_NOTIFY)
screenchange((void *)evt);
}
struct swm_region *r;
char conf[PATH_MAX], *cfile = NULL;
struct stat sb;
- int xfd, i, num_screens, startup = 1;
+ int xfd, i, num_screens;
struct sigaction sact;
xcb_generic_event_t *evt;
struct timeval tv;
fd_set rd;
int rd_max;
- int stdin_ready = 0;
int num_readable;
+ bool stdin_ready = false, startup = true;
/* suppress unused warning since var is needed */
(void)argc;
+#ifdef SWM_DEBUG
time_started = time(NULL);
+#endif
start_argv = argv;
warnx("Welcome to spectrwm V%s Build: %s", SPECTRWM_VERSION, buildstr);
/* If just (re)started, set default focus if needed. */
if (startup) {
- startup = 0;
+ startup = false;
if (focus_mode != SWM_FOCUS_FOLLOW) {
r = TAILQ_FIRST(&screens[0].rl);
if (num_readable == -1 && errno != EINTR) {
DNPRINTF(SWM_D_MISC, "select failed");
} else if (num_readable > 0 && FD_ISSET(STDIN_FILENO, &rd)) {
- stdin_ready = 1;
+ stdin_ready = true;
}
if (restart_wm)
goto done;
if (stdin_ready) {
- stdin_ready = 0;
+ stdin_ready = false;
bar_extra_update();
}