X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=51f73cf00ec237da33e155704e11d304dc214744;hb=541344a40ab0857de33f1c8bab5889ff3a8bc801;hp=40a7fa30dd213ccfda7b238c726d48489123e8ef;hpb=f92c9ed0722e69ac05da2af5ffc0cef2ee112641;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index 40a7fa3..51f73cf 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -48,7 +48,7 @@ * DEALINGS IN THE SOFTWARE. */ -#define SWM_VERSION "0.5" +#define SWM_VERSION "0.6" #include #include @@ -175,7 +175,7 @@ char *bar_fonts[] = { /* terminal + args */ char *spawn_term[] = { "xterm", NULL }; -char *spawn_screenshot[] = { "scrot", NULL, NULL }; /* XXX get from conf */ +char *spawn_screenshot[] = { "screenshot.sh", NULL, NULL }; char *spawn_menu[] = { "dmenu_run", "-fn", NULL, "-nb", NULL, "-nf", NULL, "-sb", NULL, "-sf", NULL, NULL }; @@ -216,6 +216,7 @@ struct ws_win { struct workspace *ws; /* always valid */ struct swm_screen *s; /* always valid, never changes */ XWindowAttributes wa; + XSizeHints sh; }; TAILQ_HEAD(ws_win_list, ws_win); @@ -301,6 +302,8 @@ union arg { #define SWM_ARG_ID_STACKINIT (11) #define SWM_ARG_ID_CYCLEWS_UP (12) #define SWM_ARG_ID_CYCLEWS_DOWN (13) +#define SWM_ARG_ID_CYCLESC_UP (14) +#define SWM_ARG_ID_CYCLESC_DOWN (15) #define SWM_ARG_ID_SS_ALL (0) #define SWM_ARG_ID_SS_WINDOW (1) char **argv; @@ -456,10 +459,13 @@ conf_load(char *filename) case 's': if (!strncmp(var, "spawn_term", strlen("spawn_term"))) - asprintf(&spawn_term[0], "%s", val); /* XXX args? */ + asprintf(&spawn_term[0], "%s", val); if (!strncmp(var, "screenshot_enabled", strlen("screenshot_enabled"))) ss_enabled = atoi(val); + if (!strncmp(var, "screenshot_app", + strlen("screenshot_app"))) + asprintf(&spawn_screenshot[0], "%s", val); break; default: goto bad; @@ -719,6 +725,18 @@ quit(struct swm_region *r, union arg *args) } void +unmap_all(void) +{ + struct ws_win *win; + int i, j; + + for (i = 0; i < ScreenCount(display); i++) + for (j = 0; j < SWM_WS_MAX; j++) + TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) + XUnmapWindow(display, win->id); +} + +void restart(struct swm_region *r, union arg *args) { DNPRINTF(SWM_D_MISC, "restart: %s\n", start_argv[0]); @@ -730,6 +748,7 @@ restart(struct swm_region *r, union arg *args) bar_extra_stop(); bar_extra = 1; + unmap_all(); XCloseDisplay(display); execvp(start_argv[0], start_argv); fprintf(stderr, "execvp failed\n"); @@ -784,6 +803,8 @@ find_window(Window id) void spawn(struct swm_region *r, union arg *args) { + char *ret; + DNPRINTF(SWM_D_MISC, "spawn: %s\n", args->argv[0]); /* * The double-fork construct avoids zombie processes and keeps the code @@ -791,14 +812,17 @@ spawn(struct swm_region *r, union arg *args) */ if (fork() == 0) { if (fork() == 0) { - char *ret; if (display) close(ConnectionNumber(display)); setenv("LD_PRELOAD", SWM_LIB, 1); - if (asprintf(&ret, "%d", r->ws->idx)) + if (asprintf(&ret, "%d", r->ws->idx)) { setenv("_SWM_WS", ret, 1); - if (asprintf(&ret, "%d", getpid())) + free(ret); + } + if (asprintf(&ret, "%d", getpid())) { setenv("_SWM_PID", ret, 1); + free(ret); + } setsid(); execvp(args->argv[0], args->argv); fprintf(stderr, "execvp failed\n"); @@ -896,7 +920,6 @@ switchws(struct swm_region *r, union arg *args) TAILQ_FOREACH(win, &old_ws->winlist, entry) XUnmapWindow(display, win->id); - old_ws->r = NULL; old_ws->restack = 1; } else { @@ -925,7 +948,6 @@ cyclews(struct swm_region *r, union arg *args) r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx); a.id = r->ws->idx; - do { switch (args->id) { case SWM_ARG_ID_CYCLEWS_UP: @@ -954,6 +976,33 @@ cyclews(struct swm_region *r, union arg *args) } void +cyclescr(struct swm_region *r, union arg *args) +{ + struct swm_region *rr; + int i; + + i = r->s->idx; + switch (args->id) { + case SWM_ARG_ID_CYCLESC_UP: + rr = TAILQ_NEXT(r, entry); + if (rr == NULL) + rr = TAILQ_FIRST(&screens[i].rl); + break; + case SWM_ARG_ID_CYCLESC_DOWN: + rr = TAILQ_PREV(r, swm_region_list, entry); + if (rr == NULL) + rr = TAILQ_LAST(&screens[i].rl, swm_region_list); + break; + default: + return; + }; + unfocus_all(); + XSetInputFocus(display, PointerRoot, RevertToPointerRoot, CurrentTime); + XWarpPointer(display, None, rr->s[i].root, 0, 0, 0, 0, rr->g.x, + rr->g.y + bar_enabled ? bar_height : 0); +} + +void swapwin(struct swm_region *r, union arg *args) { struct ws_win *target; @@ -1038,7 +1087,7 @@ focus(struct swm_region *r, union arg *args) return; } - if (winfocus == winlostfocus) + if (winfocus == winlostfocus || winfocus == NULL) return; XMapRaised(display, winfocus->id); @@ -1057,7 +1106,6 @@ cycle_layout(struct swm_region *r, union arg *args) if (ws->cur_layout->l_stack == NULL) ws->cur_layout = &layouts[0]; ignore_enter = 1; - stack(); } @@ -1134,15 +1182,17 @@ stack_floater(struct ws_win *win, struct swm_region *r) int tmp; \ tmp = (g)->y; (g)->y = (g)->x; (g)->x = tmp; \ tmp = (g)->h; (g)->h = (g)->w; (g)->w = tmp; \ -} while (0); +} while (0) void stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) { XWindowChanges wc; struct swm_geometry win_g, r_g = *g; struct ws_win *win, *winfocus; - int i, j; - int split, colno, hrh, winno, mwin, msize, mscale; + int i, j, w_inc, h_inc, w_base, h_base; + int hrh, extra, h_slice, last_h = 0; + int split, colno, winno, mwin, msize, mscale; + int remain, missing, v_slice;; unsigned int mask; DNPRINTF(SWM_D_STACK, "stack_master: workspace: %d\n rot=%s flip=%s", @@ -1155,26 +1205,52 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) ws->focus = TAILQ_FIRST(&ws->winlist); winfocus = cur_focus ? cur_focus : ws->focus; + win = TAILQ_FIRST(&ws->winlist); if (rot) { + w_inc = win->sh.width_inc; + w_base = win->sh.base_width; mwin = ws->l_state.horizontal_mwin; mscale = ws->l_state.horizontal_msize; SWAPXY(&r_g); } else { + w_inc = win->sh.height_inc; + w_base = win->sh.base_height; mwin = ws->l_state.vertical_mwin; mscale = ws->l_state.vertical_msize; } win_g = r_g; + h_slice = r_g.h / SWM_H_SLICE; if (mwin && winno > mwin) { + v_slice = r_g.w / SWM_V_SLICE; + split = mwin; colno = split; - msize = (r_g.w / SWM_V_SLICE) * mscale; + msize = v_slice * mscale; + + if (w_inc > 1 && w_inc < v_slice) { + /* adjust for window's requested size increment */ + remain = (win_g.w - w_base) % w_inc; + missing = w_inc - remain; + + if (missing <= extra || j == 0) { + extra -= missing; + win_g.w += missing; + } else { + win_g.w -= remain; + extra += remain; + } + } + win_g.w = msize; + if (flip) + win_g.x += r_g.w - msize; } else { colno = winno; split = 0; } hrh = r_g.h / colno; + extra = r_g.h - (colno * hrh); win_g.h = hrh - 2; i = j = 0; @@ -1182,19 +1258,42 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) if (split && i == split) { colno = winno - split; hrh = (r_g.h / colno); - win_g.x += msize + 2; + extra = r_g.h - (colno * hrh); + if (flip) + win_g.x = r_g.x; + else + win_g.x += msize + 2; win_g.w = r_g.w - (msize + 2); - win_g.h = hrh - 2; j = 0; } - if (j == colno - 1) - win_g.h = (hrh + (r_g.h - (colno * hrh))); + win_g.h = hrh - 2; + if (rot) { + h_inc = win->sh.width_inc; + h_base = win->sh.base_width; + } else { + h_inc = win->sh.height_inc; + h_base = win->sh.base_height; + } + if (j == colno - 1) { + win_g.h = hrh + extra; + } else if (h_inc > 1 && h_inc < h_slice) { + /* adjust for window's requested size increment */ + remain = (win_g.h - h_base) % h_inc; + missing = h_inc - remain; + + if (missing <= extra || j == 0) { + extra -= missing; + win_g.h += missing; + } else { + win_g.h -= remain; + extra += remain; + } + } if (j == 0) win_g.y = r_g.y; else - win_g.y += hrh; - + win_g.y += last_h + 2; if (win->transient != 0 || win->floating != 0) stack_floater(win, ws->r); @@ -1220,6 +1319,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) } XMapRaised(display, win->id); + last_h = win_g.h; i++; j++; } @@ -1418,10 +1518,10 @@ screenshot(struct swm_region *r, union arg *args) switch (args->id) { case SWM_ARG_ID_SS_ALL: - spawn_screenshot[1] = "-m"; + spawn_screenshot[1] = "full"; break; case SWM_ARG_ID_SS_WINDOW: - spawn_screenshot[1] = "-s"; /* XXX doesn't work with scrot */ + spawn_screenshot[1] = "window"; break; default: return; @@ -1466,6 +1566,8 @@ struct key { { MODKEY, XK_0, switchws, {.id = 9} }, { MODKEY, XK_Right, cyclews, {.id = SWM_ARG_ID_CYCLEWS_UP} }, { MODKEY, XK_Left, cyclews, {.id = SWM_ARG_ID_CYCLEWS_DOWN} }, + { MODKEY | ShiftMask, XK_Right, cyclescr, {.id = SWM_ARG_ID_CYCLESC_UP} }, + { MODKEY | ShiftMask, XK_Left, cyclescr, {.id = SWM_ARG_ID_CYCLESC_DOWN} }, { MODKEY | ShiftMask, XK_1, send_to_ws, {.id = 0} }, { MODKEY | ShiftMask, XK_2, send_to_ws, {.id = 1} }, { MODKEY | ShiftMask, XK_3, send_to_ws, {.id = 2} }, @@ -1654,6 +1756,9 @@ manage_window(Window id) Atom ws_idx_atom = 0, type; unsigned char ws_idx_str[SWM_PROPLEN], *prop = NULL; struct swm_region *r; + long mask; + int ws_idx; + const char *errstr; if ((win = find_window(id)) != NULL) return (win); /* already being managed */ @@ -1670,9 +1775,6 @@ manage_window(Window id) r = root_to_region(win->wa.root); /* If the window was managed before, put it in the same workspace */ if (prop) { - int ws_idx; - const char *errstr; - DNPRINTF(SWM_D_PROP, "got property _SWM_WS=%s\n", prop); ws_idx = strtonum(prop, 0, 9, &errstr); if (errstr) @@ -1701,6 +1803,8 @@ manage_window(Window id) win->g.x = win->wa.x; win->g.y = win->wa.y; + XGetWMNormalHints(display, win->id, &win->sh, &mask); + if (ws_idx_atom && prop == NULL && snprintf(ws_idx_str, SWM_PROPLEN, "%d", ws->idx) < SWM_PROPLEN) { DNPRINTF(SWM_D_PROP, "setting property _SWM_WS to %s\n", @@ -1824,16 +1928,16 @@ destroynotify(XEvent *e) ws->focus = TAILQ_PREV(win, ws_win_list, entry); if (ws->focus == NULL) ws->focus = TAILQ_FIRST(&ws->winlist); - if (ws->focus == win) + if (ws->focus == NULL || ws->focus == win) { ws->focus = NULL; - if (cur_focus == win) + unfocus_all(); + } else focus_win(ws->focus); - TAILQ_REMOVE(&ws->winlist, win, entry); set_win_state(win, WithdrawnState); free(win); + stack(); } - stack(); } void