X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=3719d0d965a27ca9364eafe7074e4997f94e43d2;hb=332906d454ef06919ddcdb82e8b67e11050897c4;hp=62afbb09e1070ef8857fca162dd6979819955d29;hpb=3a8ade46f6bcd5e051de1a99c3ad32108092d935;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index 62afbb0..3719d0d 100644 --- a/spectrwm.c +++ b/spectrwm.c @@ -5,7 +5,7 @@ * Copyright (c) 2009 Pierre-Yves Ritschard * Copyright (c) 2010 Tuukka Kataja * Copyright (c) 2011 Jason L. Wright - * Copyright (c) 2011-2013 Reginald Kennedy + * Copyright (c) 2011-2014 Reginald Kennedy * Copyright (c) 2011-2012 Lawrence Teo * Copyright (c) 2011-2012 Tiago Cunha * Copyright (c) 2012-2013 David Hill @@ -425,6 +425,7 @@ XftFont *bar_font; int bar_font_legacy = 1; char *bar_fonts; XftColor bar_font_color; +XftColor search_font_color; struct passwd *pwd; char *startup_exception; unsigned int nr_exceptions = 0; @@ -669,6 +670,7 @@ struct quirk { #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. */ }; TAILQ_HEAD(quirk_list, quirk); struct quirk_list quirks = TAILQ_HEAD_INITIALIZER(quirks); @@ -1028,6 +1030,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); @@ -1900,24 +1903,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 @@ -2724,6 +2716,12 @@ xft_init(struct swm_region *r) 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) @@ -2771,6 +2769,13 @@ bar_setup(struct swm_region *r) 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)); @@ -3593,13 +3598,15 @@ 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); } + if (cfw != win) + /* Update window border even if workspace is hidden. */ + update_window_color(win); + out: bar_draw(); @@ -3819,7 +3826,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); @@ -3829,7 +3836,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; @@ -3838,7 +3845,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; @@ -3856,7 +3863,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); @@ -4493,6 +4500,8 @@ update_floater(struct ws_win *win) DNPRINTF(SWM_D_MISC, "update_floater: win %#x\n", win->id); + win->bordered = 1; + if (FULLSCREEN(win)) { /* _NET_WM_FULLSCREEN: fullscreen without border. */ if (!win->g_floatvalid) @@ -4508,14 +4517,11 @@ update_floater(struct ws_win *win) 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; } if (win->bordered) { @@ -4961,8 +4967,7 @@ max_stack(struct workspace *ws, struct swm_geometry *g) } } - if (TRANS(win)) { - parent = find_window(win->transient); + if (TRANS(win) && (parent = find_window(win->transient))) { raise_window(parent); TAILQ_FOREACH(w, &ws->stack, stack_entry) @@ -5047,10 +5052,14 @@ send_to_ws(struct swm_region *r, union arg *args) win_to_ws(win, wsid, 1); - /* 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, " @@ -5062,7 +5071,7 @@ send_to_ws(struct swm_region *r, union arg *args) 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); @@ -5379,7 +5388,8 @@ search_win(struct swm_region *r, union arg *args) 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; @@ -5400,6 +5410,9 @@ search_win(struct swm_region *r, union arg *args) 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; @@ -5423,6 +5436,7 @@ search_win(struct swm_region *r, union arg *args) 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); @@ -5435,10 +5449,10 @@ search_win(struct swm_region *r, union arg *args) 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); @@ -5463,7 +5477,7 @@ search_win(struct swm_region *r, union arg *args) 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); @@ -5554,7 +5568,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."); @@ -5637,7 +5651,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."); @@ -5672,7 +5686,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."); @@ -6858,7 +6872,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); @@ -6871,7 +6885,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. */ @@ -6885,7 +6899,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; @@ -7519,6 +7533,7 @@ const char *quirkname[] = { "FOCUSPREV", "NOFOCUSONMAP", "FOCUSONMAP_SINGLE", + "OBEYAPPFOCUSREQ", }; /* SWM_Q_WS: retain '|' for back compat for now (2009-08-11) */ @@ -8102,34 +8117,40 @@ setconfmodkey(const char *selector, const char *value, int flags) int setconfcolor(const char *selector, const char *value, int flags) { - int sid, i, num_screens; + int first, last, i = 0, num_screens; - sid = (selector == NULL || strlen(selector) == 0) ? -1 : atoi(selector); + num_screens = get_screen_count(); - /* - * When setting focus/unfocus colors, we need to also - * set maximize colors to match if they haven't been customized. - */ - i = sid < 0 ? 0 : sid; - if (flags == SWM_S_COLOR_FOCUS && - !screens[i].c[SWM_S_COLOR_FOCUS_MAXIMIZED].manual) - setscreencolor(value, sid, SWM_S_COLOR_FOCUS_MAXIMIZED); - else if (flags == SWM_S_COLOR_UNFOCUS && - !screens[i].c[SWM_S_COLOR_UNFOCUS_MAXIMIZED].manual) - setscreencolor(value, sid, SWM_S_COLOR_UNFOCUS_MAXIMIZED); + /* 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); + } - setscreencolor(value, sid, flags); + 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); - /* Track override of color. */ - num_screens = get_screen_count(); - if (sid > 0 && sid <= num_screens) { screens[i].c[flags].manual = 1; - } else if (sid == -1) { - for (i = 0; i < num_screens; ++i) - screens[i].c[flags].manual = 1; - } else { - errx(1, "invalid screen index: %d out of bounds (maximum %d)", - sid, num_screens); } return (0); @@ -9426,6 +9447,13 @@ enternotify(xcb_enter_notify_event_t *e) 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)); } @@ -9742,6 +9770,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) { @@ -9768,8 +9820,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(); @@ -9791,11 +9842,22 @@ 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 || + 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) @@ -10338,15 +10400,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("red", i + 1, SWM_S_COLOR_FOCUS_MAXIMIZED); - setscreencolor("rgb:88/88/88", i + 1, SWM_S_COLOR_UNFOCUS_MAXIMIZED); + 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); @@ -10437,9 +10500,12 @@ shutdown_cleanup(void) 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)