X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=dbcd5f6a14aa0ee9b5288eab889df503657c9bfc;hb=refs%2Fheads%2Fjason;hp=5fc8877587acf17aecf5261a8142119486ebf0bf;hpb=56313f2dcc507dc9c7d2387debe869fcd87a812e;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index 5fc8877..dbcd5f6 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -368,7 +368,7 @@ enum { /* dialog windows */ double dialog_ratio = 0.6; /* status bar */ -#define SWM_BAR_MAX (256) +#define SWM_BAR_MAX (356) #define SWM_BAR_JUSTIFY_LEFT (0) #define SWM_BAR_JUSTIFY_CENTER (1) #define SWM_BAR_JUSTIFY_RIGHT (2) @@ -402,6 +402,9 @@ 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; bool urgent_collapse = false; char *clock_format = NULL; bool window_class_enabled = false; @@ -519,7 +522,7 @@ struct layout { } layouts[] = { /* stack, configure */ { vertical_stack, vertical_config, 0, plain_stacker }, - { horizontal_stack, horizontal_config, 0, plain_stacker }, +// { horizontal_stack, horizontal_config, 0, plain_stacker }, { max_stack, NULL, SWM_L_MAPONFOCUS | SWM_L_FOCUSPREV, plain_stacker }, { NULL, NULL, 0, NULL }, @@ -528,7 +531,7 @@ struct layout { /* position of max_stack mode in the layouts array, index into layouts! */ #define SWM_V_STACK (0) #define SWM_H_STACK (1) -#define SWM_MAX_STACK (2) +#define SWM_MAX_STACK (1) #define SWM_H_SLICE (32) #define SWM_V_SLICE (32) @@ -713,6 +716,7 @@ enum { _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, @@ -756,6 +760,7 @@ struct ewmh_hint { {"_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}, @@ -1041,6 +1046,7 @@ char *get_source_type_label(uint32_t); char *get_stack_mode_name(uint8_t); #endif int32_t get_swm_ws(xcb_window_t); +bool get_urgent(struct ws_win *); char *get_win_name(xcb_window_t); uint8_t get_win_state(xcb_window_t); void get_wm_protocols(struct ws_win *); @@ -1133,6 +1139,7 @@ void setup_quirks(void); 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); @@ -2168,6 +2175,22 @@ bar_window_name(char *s, size_t sz, struct swm_region *r) free(title); } +bool +get_urgent(struct ws_win *win) +{ + xcb_icccm_wm_hints_t hints; + xcb_get_property_cookie_t c; + bool urgent = false; + + if (win) { + c = xcb_icccm_get_wm_hints(conn, win->id); + if (xcb_icccm_get_wm_hints_reply(conn, c, &hints, NULL)) + urgent = xcb_icccm_wm_hints_get_urgency(&hints); + } + + return urgent; +} + void bar_urgent(char *s, size_t sz) { @@ -2175,8 +2198,6 @@ bar_urgent(char *s, size_t sz) int i, j, num_screens; 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] = false; @@ -2184,14 +2205,8 @@ bar_urgent(char *s, size_t sz) num_screens = get_screen_count(); for (i = 0; i < num_screens; i++) for (j = 0; j < workspace_limit; j++) - TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) { - c = xcb_icccm_get_wm_hints(conn, win->id); - if (xcb_icccm_get_wm_hints_reply(conn, c, - &hints, NULL) == 0) - continue; - if (hints.flags & XCB_ICCCM_WM_HINT_X_URGENCY) - urgent[j] = true; - } + TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) + urgent[j] = get_urgent(win); for (i = 0; i < workspace_limit; i++) { if (urgent[i]) { @@ -3461,6 +3476,19 @@ validate_ws(struct workspace *testws) 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) { @@ -3548,6 +3576,10 @@ focus_win(struct ws_win *win) &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); } @@ -4270,7 +4302,6 @@ focus(struct swm_region *r, union arg *args) struct workspace *ws = NULL; union arg a; int i; - xcb_icccm_wm_hints_t hints; if (!(r && r->ws)) goto out; @@ -4331,7 +4362,7 @@ focus(struct swm_region *r, union arg *args) winfocus = TAILQ_FIRST(wl); if (winfocus == cur_focus) - winfocus = cur_focus->ws->focus_prev; + return; break; case SWM_ARG_ID_FOCUSURGENT: /* Search forward for the next urgent window. */ @@ -4343,27 +4374,26 @@ focus(struct swm_region *r, union arg *args) head = TAILQ_FIRST(&r->s->ws[(ws->idx + i) % workspace_limit].winlist); - while (head != NULL && - (head = TAILQ_NEXT(head, entry)) != NULL) { + while (head) { if (head == cur_focus) { - winfocus = cur_focus; - break; - } - if (xcb_icccm_get_wm_hints_reply(conn, - xcb_icccm_get_wm_hints(conn, head->id), - &hints, NULL) != 0 && - xcb_icccm_wm_hints_get_urgency(&hints)) { + if (i > 0) { + winfocus = cur_focus; + break; + } + } else if (get_urgent(head)) { winfocus = head; break; } + + head = TAILQ_NEXT(head, entry); } - if (winfocus != NULL) + if (winfocus) break; } /* Switch ws if new focus is on a different ws. */ - if (winfocus != NULL && winfocus->ws != ws) { + if (winfocus && winfocus->ws != ws) { a.id = winfocus->ws->idx; switchws(r, &a); } @@ -4790,7 +4820,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, bool flip) win_g.y += last_h + 2 * border_width + tile_gap; if (disable_border && !(bar_enabled && ws->bar_enabled) && - winno == 1){ + winno == 1) { bordered = false; win_g.w += 2 * border_width; win_g.h += 2 * border_width; @@ -5003,12 +5033,13 @@ max_stack(struct workspace *ws, struct swm_geometry *g) if (X(w) != gg.x || Y(w) != gg.y || WIDTH(w) != gg.w || HEIGHT(w) != gg.h) { w->g = gg; - if (bar_enabled && ws->bar_enabled){ - w->bordered = true; - } else { + + if (disable_border && !(bar_enabled && ws->bar_enabled)) { w->bordered = false; WIDTH(w) += 2 * border_width; HEIGHT(w) += 2 * border_width; + } else { + w->bordered = true; } update_window(w); @@ -6083,15 +6114,22 @@ update_window_color(struct ws_win *win) { uint32_t *pixel; - if (WS_FOCUSED(win->ws) && win->ws->focus == win) + 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; - else + + 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); } @@ -7899,6 +7937,7 @@ enum { 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, @@ -7909,6 +7948,8 @@ enum { 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, @@ -8126,6 +8167,23 @@ setconfvalue(const char *selector, const char *value, int flags) case SWM_S_URGENT_ENABLED: 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) != 0); for (i = 0; layouts[i].l_stack != NULL; i++) { @@ -8443,6 +8501,7 @@ struct config_option configopt[] = { { "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 }, @@ -8456,6 +8515,8 @@ struct config_option configopt[] = { { "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 }, @@ -8856,6 +8917,9 @@ manage_window(xcb_window_t id, int spawn_pos, bool mapped) 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),