X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=f42432a9fac37071a5d7420139ffb27170be5776;hb=9b55b66ab52e3f8ec45663b07cf6b80095e2c14c;hp=86c2afaac35005999cfa54d86e490e5af3d01638;hpb=99119d86977bc0f0d023f56d1dba269dcdff2706;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index 86c2afa..f42432a 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -62,10 +63,12 @@ #include #include +#include #include #include #include #include +#include #include #include @@ -131,12 +134,14 @@ Display *display; /* dialog windows */ double dialog_ratio = .6; /* status bar */ +#define SWM_BAR_MAX (128) +sig_atomic_t bar_alarm = 0; int bar_enabled = 1; +int bar_verbose = 1; int bar_height = 0; GC bar_gc; XGCValues bar_gcv; XFontStruct *bar_fs; -char bar_text[128]; char *bar_fonts[] = { "-*-terminus-*-*-*-*-*-*-*-*-*-*-*-*", "-*-times-medium-r-*-*-*-*-*-*-*-*-*-*", @@ -240,6 +245,7 @@ struct swm_screen { unsigned long bar_font_color; unsigned long color_focus; /* XXX should this be per ws? */ unsigned long color_unfocus; + char bar_text[SWM_BAR_MAX]; }; struct swm_screen *screens; int num_screens; @@ -384,44 +390,55 @@ bad: } void -bar_print(struct swm_region *r) +bar_print(struct swm_region *r, char *s, int erase) +{ + if (erase) { + XSetForeground(display, bar_gc, r->s->bar_color); + XDrawString(display, r->bar_window, bar_gc, 4, bar_fs->ascent, + r->s->bar_text, strlen(r->s->bar_text)); + } + + strlcpy(r->s->bar_text, s, sizeof r->s->bar_text); + XSetForeground(display, bar_gc, r->s->bar_font_color); + XDrawString(display, r->bar_window, bar_gc, 4, bar_fs->ascent, + r->s->bar_text, strlen(r->s->bar_text)); +} + +void +bar_update(void) { time_t tmt; struct tm tm; - + struct swm_region *r; + int i; + char s[SWM_BAR_MAX]; + if (bar_enabled == 0) return; - /* clear old text */ - XSetForeground(display, bar_gc, r->s->bar_color); - XDrawString(display, r->bar_window, - bar_gc, 4, bar_fs->ascent, bar_text, strlen(bar_text)); - /* draw new text */ time(&tmt); localtime_r(&tmt, &tm); - strftime(bar_text, sizeof bar_text, "%a %b %d %R %Z %Y", &tm); - XSetForeground(display, bar_gc, r->s->bar_font_color); - XDrawString(display, r->bar_window, bar_gc, 4, - bar_fs->ascent, bar_text, strlen(bar_text)); - XSync(display, False); + strftime(s, sizeof s, "%a %b %d %R %Z %Y", &tm); + for (i = 0; i < ScreenCount(display); i++) + TAILQ_FOREACH(r, &screens[i].rl, entry) + bar_print(r, s, 1); + XSync(display, False); alarm(60); } void bar_signal(int sig) { - /* XXX yeah yeah byte me */ - if (cur_focus) - bar_print(cur_focus->ws->r); + bar_alarm = 1; } void bar_toggle(struct swm_region *r, union arg *args) { - struct swm_region *tmpr; - int i, j; + struct swm_region *tmpr; + int i, j; DNPRINTF(SWM_D_MISC, "bar_toggle\n"); @@ -444,7 +461,7 @@ bar_toggle(struct swm_region *r, union arg *args) /* must be after stack */ for (i = 0; i < ScreenCount(display); i++) TAILQ_FOREACH(tmpr, &screens[i].rl, entry) - bar_print(tmpr); + bar_update(); } void @@ -462,7 +479,7 @@ bar_setup(struct swm_region *r) bar_height = bar_fs->ascent + bar_fs->descent + 3; r->bar_window = XCreateSimpleWindow(display, - r->s->root, X(r), Y(r), WIDTH(r), bar_height - 2, + r->s->root, X(r), Y(r), WIDTH(r) - 2, bar_height - 2, 1, r->s->bar_border, r->s->bar_color); bar_gc = XCreateGC(display, r->bar_window, 0, &bar_gcv); XSetFont(display, bar_gc, bar_fs->fid); @@ -473,7 +490,7 @@ bar_setup(struct swm_region *r) if (signal(SIGALRM, bar_signal) == SIG_ERR) err(1, "could not install bar_signal"); - bar_print(r); + bar_update(); } void @@ -527,6 +544,11 @@ restart(struct swm_region *r, union arg *args) { DNPRINTF(SWM_D_MISC, "restart: %s\n", start_argv[0]); + /* disable alarm because the following code may not be interrupted */ + alarm(0); + if (signal(SIGALRM, SIG_IGN) == SIG_ERR) + errx(1, "can't disable alarm"); + XCloseDisplay(display); execvp(start_argv[0], start_argv); fprintf(stderr, "execvp failed\n"); @@ -538,7 +560,9 @@ struct swm_region * root_to_region(Window root) { struct swm_region *r; - int i; + Window rr, cr; + int i, x, y, wx, wy; + unsigned int mask; for (i = 0; i < ScreenCount(display); i++) if (screens[i].root == root) @@ -548,19 +572,14 @@ root_to_region(Window root) cur_focus && cur_focus->ws->r && cur_focus->s == &screens[i]) r = cur_focus->ws->r; else { - Window rr, cr; - int x, y, wx, wy; - unsigned int mask; - if (XQueryPointer(display, screens[i].root, &rr, &cr, &x, &y, &wx, &wy, &mask) == False) { r = TAILQ_FIRST(&screens[i].rl); } else { TAILQ_FOREACH(r, &screens[i].rl, entry) { if (x > X(r) && x < X(r) + WIDTH(r) && - y > Y(r) && y < Y(r) + HEIGHT(r)) { + y > Y(r) && y < Y(r) + HEIGHT(r)) break; - } } if (r == NULL) @@ -573,8 +592,8 @@ root_to_region(Window root) struct ws_win * find_window(Window id) { - struct ws_win *win; - int i, j; + struct ws_win *win; + int i, j; for (i = 0; i < ScreenCount(display); i++) for (j = 0; j < SWM_WS_MAX; j++) @@ -663,8 +682,7 @@ switchws(struct swm_region *r, union arg *args) other_r = new_ws->r; if (!other_r) { - /* if the other region is hidden, switch windows */ - + /* if the other workspace is hidden, switch windows */ /* map new window first to prevent ugly blinking */ TAILQ_FOREACH(win, &new_ws->winlist, entry) XMapRaised(display, win->id); @@ -783,7 +801,7 @@ focus(struct swm_region *r, union arg *args) void cycle_layout(struct swm_region *r, union arg *args) { - struct workspace *ws = r->ws; + struct workspace *ws = r->ws; DNPRINTF(SWM_D_EVENT, "cycle_layout: workspace: %d\n", ws->idx); @@ -822,9 +840,9 @@ stack_reset(struct swm_region *r, union arg *args) void stack(void) { - struct swm_geometry g; - struct swm_region *r; - int i, j; + struct swm_geometry g; + struct swm_region *r; + int i, j; DNPRINTF(SWM_D_STACK, "stack\n"); @@ -1233,9 +1251,9 @@ grabkeys(void) if (TAILQ_EMPTY(&screens[k].rl)) continue; XUngrabKey(display, AnyKey, AnyModifier, screens[k].root); - for(i = 0; i < LENGTH(keys); i++) { - if((code = XKeysymToKeycode(display, keys[i].keysym))) - for(j = 0; j < LENGTH(modifiers); j++) + for (i = 0; i < LENGTH(keys); i++) { + if ((code = XKeysymToKeycode(display, keys[i].keysym))) + for (j = 0; j < LENGTH(modifiers); j++) XGrabKey(display, code, keys[i].mod | modifiers[j], screens[k].root, True, @@ -1462,7 +1480,6 @@ destroynotify(XEvent *e) set_win_state(win, WithdrawnState); free(win); } - stack(); } @@ -1475,7 +1492,7 @@ enternotify(XEvent *e) DNPRINTF(SWM_D_EVENT, "enternotify: window: %lu\n", ev->window); - if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && + if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != ev->root) return; if (ignore_enter) { @@ -1561,14 +1578,16 @@ unmapnotify(XEvent *e) void visibilitynotify(XEvent *e) { - int i; - struct swm_region *r; - DNPRINTF(SWM_D_EVENT, "visibilitynotify: window: %lu\n", e->xvisibility.window); + int i; + struct swm_region *r; + + DNPRINTF(SWM_D_EVENT, "visibilitynotify: window: %lu\n", + e->xvisibility.window); if (e->xvisibility.state == VisibilityUnobscured) for (i = 0; i < ScreenCount(display); i++) TAILQ_FOREACH(r, &screens[i].rl, entry) if (e->xvisibility.window == r->bar_window) - bar_print(r); + bar_update(); } void (*handler[LASTEvent])(XEvent *) = { @@ -1643,7 +1662,7 @@ void new_region(struct swm_screen *s, struct workspace *ws, int x, int y, int w, int h) { - struct swm_region *r; + struct swm_region *r; DNPRINTF(SWM_D_MISC, "new region on screen %d: %dx%d (%d, %d)\n", s->idx, x, y, w, h); @@ -1665,8 +1684,19 @@ new_region(struct swm_screen *s, struct workspace *ws, void setup_screens(void) { - int i; - +#ifdef SWM_XRR_HAS_CRTC + XRRCrtcInfo *ci; + XRRScreenResources *sr; + int c; +#endif /* SWM_XRR_HAS_CRTC */ + Window d1, d2, *wins = NULL; + XWindowAttributes wa; + struct swm_region *r; + unsigned int no; + int errorbase, major, minor; + int ncrtc = 0, w = 0; + int i, j, k; + struct workspace *ws; if ((screens = calloc(ScreenCount(display), sizeof(struct swm_screen))) == NULL) @@ -1674,18 +1704,7 @@ setup_screens(void) /* map physical screens */ for (i = 0; i < ScreenCount(display); i++) { -#ifdef SWM_XRR_HAS_CRTC - XRRCrtcInfo *crtc_info; - XRRScreenResources *res; - int c; -#endif /* SWM_XRR_HAS_CRTC */ - Window d1, d2, *wins = NULL; - XWindowAttributes wa; - struct swm_region *r; - int errorbase, major, minor; - int j, ncrtc, w = 0; - unsigned int num; - + DNPRINTF(SWM_D_WS, "setup_screens: init screen %d\n", i); screens[i].idx = i; TAILQ_INIT(&screens[i].rl); screens[i].root = RootWindow(display, i); @@ -1702,19 +1721,16 @@ setup_screens(void) /* init all workspaces */ for (j = 0; j < SWM_WS_MAX; j++) { - int k; - struct workspace *ws = &screens[i].ws[j]; - + ws = &screens[i].ws[j]; ws->idx = j; ws->restack = 1; ws->focus = NULL; ws->r = NULL; TAILQ_INIT(&ws->winlist); - for (k = 0; layouts[k].l_stack != NULL; k++) { + for (k = 0; layouts[k].l_stack != NULL; k++) if (layouts[k].l_init != NULL) layouts[k].l_init(ws); - } ws->cur_layout = &layouts[0]; } @@ -1734,39 +1750,37 @@ setup_screens(void) #endif /* grab existing windows (before we build the bars)*/ - if (!XQueryTree(display, screens[i].root, - &d1, &d2, &wins, &num)) { - if (wins) /* not sure if this is necessary */ - XFree(wins); + if (!XQueryTree(display, screens[i].root, &d1, &d2, &wins, &no)) continue; - } - #ifdef SWM_XRR_HAS_CRTC - res = XRRGetScreenResources (display, screens[i].root); - if (res == NULL) { - ncrtc = 0; + sr = XRRGetScreenResources(display, screens[i].root); + if (sr == NULL) new_region(&screens[i], &screens[i].ws[w], 0, 0, DisplayWidth(display, i), DisplayHeight(display, i)); - } else - ncrtc = res->ncrtc; + else + ncrtc = sr->ncrtc; for (c = 0; c < ncrtc; c++) { - crtc_info = XRRGetCrtcInfo(display, res, res->crtcs[c]); - if (crtc_info != NULL && crtc_info->mode == None) - new_region(&screens[i], &screens[i].ws[w], - 0, 0, DisplayWidth(display, i), + ci = XRRGetCrtcInfo(display, sr, sr->crtcs[c]); + if (ci->noutput == 0) + continue; + + if (ci != NULL && ci->mode == None) + new_region(&screens[i], &screens[i].ws[w], 0, 0, + DisplayWidth(display, i), DisplayHeight(display, i)); else new_region(&screens[i], &screens[i].ws[w], - crtc_info->x, crtc_info->y, - crtc_info->width, crtc_info->height); + ci->x, ci->y, ci->width, ci->height); w++; } + XRRFreeCrtcInfo(ci); + XRRFreeScreenResources(sr); #else - new_region(&screens[i], &screens[i].ws[w], - 0, 0, DisplayWidth(display, i), + new_region(&screens[i], &screens[i].ws[w], 0, 0, + DisplayWidth(display, i), DisplayHeight(display, i)); #endif /* SWM_XRR_HAS_CRTC */ @@ -1775,27 +1789,31 @@ setup_screens(void) if ((r = TAILQ_FIRST(&screens[i].rl)) == NULL) errx(1, "no regions on screen %d", i); - for (i = 0; i < num; i++) { + for (i = 0; i < no; i++) { XGetWindowAttributes(display, wins[i], &wa); if (!XGetWindowAttributes(display, wins[i], &wa) || wa.override_redirect || XGetTransientForHint(display, wins[i], &d1)) continue; + if (wa.map_state == IsViewable || getstate(wins[i]) == NormalState) manage_window(wins[i], r->ws); } /* transient windows */ - for (i = 0; i < num; i++) { + for (i = 0; i < no; i++) { if (!XGetWindowAttributes(display, wins[i], &wa)) continue; + if (XGetTransientForHint(display, wins[i], &d1) && (wa.map_state == IsViewable || getstate(wins[i]) == NormalState)) manage_window(wins[i], r->ws); } - if (wins) + if (wins) { XFree(wins); + wins = NULL; + } } } @@ -1806,6 +1824,8 @@ main(int argc, char *argv[]) char conf[PATH_MAX], *cfile = NULL; struct stat sb; XEvent e; + int xfd; + fd_set rd; start_argv = argv; fprintf(stderr, "Welcome to scrotwm V%s\n", SWM_VERSION); @@ -1841,15 +1861,26 @@ main(int argc, char *argv[]) setup_screens(); - //ws[0].focus = TAILQ_FIRST(&ws[0].winlist); + /* ws[0].focus = TAILQ_FIRST(&ws[0].winlist); */ grabkeys(); stack(); + xfd = ConnectionNumber(display); while (running) { - XNextEvent(display, &e); - if (handler[e.type]) - handler[e.type](&e); + FD_SET(xfd, &rd); + if (select(xfd + 1, &rd, NULL, NULL, NULL) == -1) + if (errno != EINTR) + errx(1, "select failed"); + if (bar_alarm) { + bar_alarm = 0; + bar_update(); + } + while(XPending(display)) { + XNextEvent(display, &e); + if (handler[e.type]) + handler[e.type](&e); + } } XCloseDisplay(display);