X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=fa8ac2e101d8b0c85f89f742e6e67a177d90cd00;hb=9c6fb4c472e592a5a122b1abfd75d8d4d862b472;hp=83b31a0ebc46c4995f6b3105f52ee47c0c3c38e6;hpb=80b6156fc1d5c45c65f9c7987acaaf53846b2984;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index 83b31a0..fa8ac2e 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -572,7 +572,9 @@ enum { 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 }; @@ -592,6 +594,7 @@ struct swm_screen { struct { uint32_t pixel; char *name; + int manual; } c[SWM_S_COLOR_MAX]; xcb_gcontext_t bar_gc; @@ -1025,6 +1028,7 @@ int get_region_index(struct swm_region *); 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); @@ -1152,6 +1156,7 @@ void update_floater(struct ws_win *); 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 *); @@ -1632,6 +1637,8 @@ ewmh_apply_flags(struct ws_win *win, uint32_t pending) ws->focus_pending = win; } } + + update_window_color(win); raise_window(win); } @@ -1894,24 +1901,13 @@ name_to_pixel(int sidx, const char *colorname) 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 @@ -3468,8 +3464,7 @@ 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); @@ -3486,13 +3481,7 @@ focus_win(struct ws_win *win) 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; @@ -3513,7 +3502,9 @@ focus_win(struct ws_win *win) /* 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); } else { unfocus_win(cfw); } @@ -3559,9 +3550,6 @@ focus_win(struct ws_win *win) 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. */ @@ -3595,6 +3583,8 @@ focus_win(struct ws_win *win) set_region(ws->r); + 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, &win->id); @@ -3750,8 +3740,7 @@ switchws(struct swm_region *r, union arg *args) 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, @@ -3820,7 +3809,7 @@ cyclews(struct swm_region *r, union arg *args) union arg a; struct swm_screen *s = r->s; int cycle_all = 0; - int move = 0; + int mv = 0; 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); @@ -3830,7 +3819,7 @@ cyclews(struct swm_region *r, union arg *args) do { switch (args->id) { case SWM_ARG_ID_CYCLEWS_MOVE_UP: - move = 1; + mv = 1; /* FALLTHROUGH */ case SWM_ARG_ID_CYCLEWS_UP_ALL: cycle_all = 1; @@ -3839,7 +3828,7 @@ cyclews(struct swm_region *r, union arg *args) a.id = (a.id < workspace_limit - 1) ? a.id + 1 : 0; break; case SWM_ARG_ID_CYCLEWS_MOVE_DOWN: - move = 1; + mv = 1; /* FALLTHROUGH */ case SWM_ARG_ID_CYCLEWS_DOWN_ALL: cycle_all = 1; @@ -3857,7 +3846,7 @@ cyclews(struct swm_region *r, union arg *args) if (!cycle_visible && s->ws[a.id].r != NULL) continue; - if (move) + if (mv) send_to_ws(r, &a); switchws(r, &a); @@ -5555,7 +5544,7 @@ ewmh_update_desktop_names(void) ++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."); @@ -5638,7 +5627,7 @@ ewmh_update_client_list(void) 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."); @@ -5673,7 +5662,7 @@ ewmh_update_desktops(void) 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."); @@ -6012,6 +6001,24 @@ constrain_window(struct ws_win *win, struct swm_geometry *b, int *opts) } 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; + else + pixel = MAXIMIZED(win) ? + &win->s->c[SWM_S_COLOR_UNFOCUS_MAXIMIZED].pixel : + &win->s->c[SWM_S_COLOR_UNFOCUS].pixel; + + xcb_change_window_attributes(conn, win->id, + XCB_CW_BORDER_PIXEL, pixel); +} + +void update_window(struct ws_win *win) { uint16_t mask; @@ -6683,11 +6690,21 @@ spawn_expand(struct swm_region *r, union arg *args, const char *spawn_name, 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) @@ -6831,7 +6848,7 @@ void 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); @@ -6844,7 +6861,7 @@ spawn_insert(const char *name, const char *args, int flags) 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. */ @@ -6858,7 +6875,7 @@ spawn_insert(const char *name, const char *args, int flags) if ((sp->argv[sp->argc - 1] = strdup(arg)) == NULL) err(1, "spawn_insert: strdup"); } - free(dup); + free(cp); sp->flags = flags; @@ -8075,9 +8092,42 @@ setconfmodkey(const char *selector, const char *value, int flags) 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); } @@ -8276,7 +8326,9 @@ struct config_option configopt[] = { { "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 }, { "cycle_empty", setconfvalue, SWM_S_CYCLE_EMPTY }, { "cycle_visible", setconfvalue, SWM_S_CYCLE_VISIBLE }, { "dialog_ratio", setconfvalue, SWM_S_DIALOG_RATIO }, @@ -9686,6 +9738,30 @@ unmapnotify(xcb_unmap_notify_event_t *e) 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) { @@ -9712,8 +9788,7 @@ 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(); @@ -9735,11 +9810,21 @@ clientmessage(xcb_client_message_event_t *e) } 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) { + 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) @@ -10282,13 +10367,16 @@ setup_screens(void) 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);