X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=spectrwm.c;h=317d4b74587551294bc92d14e70941c3a932d099;hb=2c9a693ca97da72f469f22fd8e9502f7d6c18f31;hp=a90eb31625d276818efcddbed79b6e9c85f1a5cd;hpb=a6032ff131d030ef4db5bde55519ae8cfa524c67;p=spectrwm.git diff --git a/spectrwm.c b/spectrwm.c index a90eb31..317d4b7 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; @@ -2715,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) @@ -2762,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)); @@ -3476,7 +3490,7 @@ unfocus_win(struct ws_win *win) 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; @@ -3559,20 +3573,25 @@ focus_win(struct ws_win *win) 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. @@ -3584,13 +3603,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(); @@ -4222,17 +4243,21 @@ focus(struct swm_region *r, union arg *args) 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) { @@ -4247,8 +4272,10 @@ focus(struct swm_region *r, union arg *args) 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) @@ -4261,8 +4288,10 @@ focus(struct swm_region *r, union arg *args) 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) @@ -4484,6 +4513,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) @@ -4499,14 +4530,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) { @@ -4889,7 +4917,7 @@ void 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); @@ -4952,18 +4980,20 @@ max_stack(struct workspace *ws, struct swm_geometry *g) } } - 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); @@ -5038,10 +5068,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, " @@ -5053,7 +5087,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); @@ -5370,7 +5404,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; @@ -5391,6 +5426,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; @@ -5414,6 +5452,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); @@ -5426,10 +5465,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); @@ -5454,7 +5493,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); @@ -8272,32 +8311,26 @@ setlayout(const char *selector, const char *value, int flags) 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); } @@ -9424,6 +9457,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)); } @@ -10470,9 +10510,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)