X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=0863b6240f178a5ca34e6c614e06d54b4d2cf3a7;hb=32edf2c5ac6cbd7b967dd9448228b0fd36f30702;hp=cc016532c19a1eba4c532ffb4c719f9d98aa3108;hpb=cd107085f1b63edf9afaac7bd512d27f64ce89e0;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index cc01653..0863b62 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -132,6 +132,7 @@ u_int32_t swm_debug = 0 #define Y(r) (r)->g.y #define WIDTH(r) (r)->g.w #define HEIGHT(r) (r)->g.h +#define SWM_MAX_FONT_STEPS (3) #ifndef SWM_LIB #define SWM_LIB "/usr/X11R6/lib/swmhack.so" @@ -151,6 +152,8 @@ Display *display; int cycle_empty = 0; int cycle_visible = 0; +int term_width = 0; +int font_adjusted = 0; /* dialog windows */ double dialog_ratio = .6; @@ -222,6 +225,9 @@ struct ws_win { int floating; int transient; int manual; + int font_size_boundary[SWM_MAX_FONT_STEPS]; + int font_steps; + int last_inc; unsigned long quirks; struct workspace *ws; /* always valid */ struct swm_screen *s; /* always valid, never changes */ @@ -261,6 +267,7 @@ struct workspace { int restack; /* restack on switch */ struct layout *cur_layout; /* current layout handlers */ struct ws_win *focus; /* may be NULL */ + struct ws_win *focus_prev; /* may be NULL */ struct swm_region *r; /* may be NULL */ struct ws_win_list winlist; /* list of windows in ws */ @@ -334,12 +341,14 @@ struct quirk { #define SWM_Q_FLOAT (1<<0) /* float this window */ #define SWM_Q_TRANSSZ (1<<1) /* transiend window size too small */ #define SWM_Q_ANYWHERE (1<<2) /* don't position this window */ +#define SWM_Q_XTERM_FONTADJ (1<<3) /* adjust xterm fonts when resizing */ } quirks[] = { { "MPlayer", "xv", SWM_Q_FLOAT }, { "OpenOffice.org 2.4", "VCLSalFrame", SWM_Q_FLOAT }, { "OpenOffice.org 3.0", "VCLSalFrame", SWM_Q_FLOAT }, { "Firefox-bin", "firefox-bin", SWM_Q_TRANSSZ}, { "Gimp", "gimp", SWM_Q_FLOAT | SWM_Q_ANYWHERE}, + { "XTerm", "xterm", SWM_Q_XTERM_FONTADJ}, { NULL, NULL, 0}, }; @@ -561,13 +570,23 @@ conf_load(char *filename) case 's': if (!strncmp(var, "spawn_term", strlen("spawn_term"))) asprintf(&spawn_term[0], "%s", val); - if (!strncmp(var, "screenshot_enabled", + else if (!strncmp(var, "screenshot_enabled", strlen("screenshot_enabled"))) ss_enabled = atoi(val); - if (!strncmp(var, "screenshot_app", + else if (!strncmp(var, "screenshot_app", strlen("screenshot_app"))) asprintf(&spawn_screenshot[0], "%s", val); + else + goto bad; + break; + + case 't': + if (!strncmp(var, "term_width", strlen("term_width"))) + term_width = atoi(val); + else + goto bad; break; + default: goto bad; } @@ -631,7 +650,6 @@ bar_update(void) if (bar_enabled == 0) return; - if (bar_extra && bar_extra_running) { /* ignore short reads; it'll correct itself */ while ((b = fgetln(stdin, &len)) != NULL) @@ -686,16 +704,13 @@ bar_toggle(struct swm_region *r, union arg *args) XMapRaised(display, tmpr->bar_window); } bar_enabled = !bar_enabled; - XSync(display, False); for (i = 0; i < sc; i++) for (j = 0; j < SWM_WS_MAX; j++) screens[i].ws[j].restack = 1; stack(); /* must be after stack */ - for (i = 0; i < sc; i++) - TAILQ_FOREACH(tmpr, &screens[i].rl, entry) - bar_update(); + bar_update(); } void @@ -849,6 +864,34 @@ unmap_all(void) } void +fake_keypress(struct ws_win *win, int keysym, int modifiers) +{ + XKeyEvent event; + + event.display = display; /* Ignored, but what the hell */ + event.window = win->id; + event.root = win->s->root; + event.subwindow = None; + event.time = CurrentTime; + event.x = win->g.x; + event.y = win->g.y; + event.x_root = 1; + event.y_root = 1; + event.same_screen = True; + event.keycode = XKeysymToKeycode(display, keysym); + event.state = modifiers; + + event.type = KeyPress; + XSendEvent(event.display, event.window, True, + KeyPressMask, (XEvent *)&event); + + event.type = KeyRelease; + XSendEvent(event.display, event.window, True, + KeyPressMask, (XEvent *)&event); + +} + +void restart(struct swm_region *r, union arg *args) { DNPRINTF(SWM_D_MISC, "restart: %s\n", start_argv[0]); @@ -950,6 +993,16 @@ spawn(struct swm_region *r, union arg *args) } void +spawnterm(struct swm_region *r, union arg *args) +{ + DNPRINTF(SWM_D_MISC, "spawnterm\n"); + + if (term_width) + setenv("_SWM_XTERM_FONTADJ", "", 1); + spawn(r, args); +} + +void spawnmenu(struct swm_region *r, union arg *args) { DNPRINTF(SWM_D_MISC, "spawnmenu\n"); @@ -993,6 +1046,9 @@ focus_win(struct ws_win *win) if (win == NULL) return; + if (win->ws->focus != win && win->ws->focus != NULL) + win->ws->focus_prev = win->ws->focus; + unfocus_all(); win->ws->focus = win; if (win->ws->r != NULL) { @@ -1122,7 +1178,7 @@ cyclescr(struct swm_region *r, union arg *args) void swapwin(struct swm_region *r, union arg *args) { - struct ws_win *target; + struct ws_win *target, *source; struct ws_win_list *wl; @@ -1132,40 +1188,48 @@ swapwin(struct swm_region *r, union arg *args) if (cur_focus == NULL) return; - wl = &cur_focus->ws->winlist; + source = cur_focus; + wl = &source->ws->winlist; switch (args->id) { case SWM_ARG_ID_SWAPPREV: - target = TAILQ_PREV(cur_focus, ws_win_list, entry); + target = TAILQ_PREV(source, ws_win_list, entry); TAILQ_REMOVE(wl, cur_focus, entry); if (target == NULL) - TAILQ_INSERT_TAIL(wl, cur_focus, entry); + TAILQ_INSERT_TAIL(wl, source, entry); else - TAILQ_INSERT_BEFORE(target, cur_focus, entry); + TAILQ_INSERT_BEFORE(target, source, entry); break; case SWM_ARG_ID_SWAPNEXT: - target = TAILQ_NEXT(cur_focus, entry); - TAILQ_REMOVE(wl, cur_focus, entry); + target = TAILQ_NEXT(source, entry); + TAILQ_REMOVE(wl, source, entry); if (target == NULL) - TAILQ_INSERT_HEAD(wl, cur_focus, entry); + TAILQ_INSERT_HEAD(wl, source, entry); else - TAILQ_INSERT_AFTER(wl, target, cur_focus, entry); + TAILQ_INSERT_AFTER(wl, target, source, entry); break; case SWM_ARG_ID_SWAPMAIN: target = TAILQ_FIRST(wl); - if (target == cur_focus) - return; + if (target == source) { + if (source->ws->focus_prev != NULL && + source->ws->focus_prev != target) + + source = source->ws->focus_prev; + else + return; + } + source->ws->focus_prev = target; TAILQ_REMOVE(wl, target, entry); - TAILQ_INSERT_BEFORE(cur_focus, target, entry); - TAILQ_REMOVE(wl, cur_focus, entry); - TAILQ_INSERT_HEAD(wl, cur_focus, entry); + TAILQ_INSERT_BEFORE(source, target, entry); + TAILQ_REMOVE(wl, source, entry); + TAILQ_INSERT_HEAD(wl, source, entry); break; default: DNPRINTF(SWM_D_MOVE, "invalid id: %d\n", args->id); return; } - ignore_enter = 2; + ignore_enter = 1; stack(); } @@ -1268,6 +1332,8 @@ stack(void) { r->ws->cur_layout->l_stack(r->ws, &g); } } + if (font_adjusted) + font_adjusted--; XSync(display, False); } @@ -1300,6 +1366,35 @@ stack_floater(struct ws_win *win, struct swm_region *r) XConfigureWindow(display, win->id, mask, &wc); } +/* + * Send keystrokes to terminal to decrease/increase the font size as the + * window size changes. + */ +void +adjust_font(struct ws_win *win) +{ + if (!(win->quirks & SWM_Q_XTERM_FONTADJ) || + win->floating || win->transient) + return; + + if (win->sh.width_inc && win->last_inc != win->sh.width_inc && + win->g.w / win->sh.width_inc < term_width && + win->font_steps < SWM_MAX_FONT_STEPS) { + win->font_size_boundary[win->font_steps] = + (win->sh.width_inc * term_width) + win->sh.base_width; + win->font_steps++; + font_adjusted++; + win->last_inc = win->sh.width_inc; + fake_keypress(win, XK_KP_Subtract, ShiftMask); + } else if (win->font_steps && win->last_inc != win->sh.width_inc && + win->g.w > win->font_size_boundary[win->font_steps - 1]) { + win->font_steps--; + font_adjusted++; + win->last_inc = win->sh.width_inc; + fake_keypress(win, XK_KP_Add, ShiftMask); + } +} + #define SWAPXY(g) do { \ int tmp; \ tmp = (g)->y; (g)->y = (g)->x; (g)->x = tmp; \ @@ -1311,8 +1406,9 @@ 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, s, w_inc, h_inc, w_base, h_base, stacks; - int hrh, extra, h_slice, last_h = 0; + int i, j, s, stacks; + int w_inc = 1, h_inc, w_base = 1, h_base; + int hrh, extra = 0, h_slice, last_h = 0; int split, colno, winno, mwin, msize, mscale; int remain, missing, v_slice;; unsigned int mask; @@ -1327,7 +1423,13 @@ 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); + TAILQ_FOREACH(win, &ws->winlist, entry) + if (win->transient == 0 && win->floating == 0) + break; + + if (win == NULL) + goto notiles; + if (rot) { w_inc = win->sh.width_inc; w_base = win->sh.base_width; @@ -1361,14 +1463,8 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) /* 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 -= remain; + extra += remain; } msize = win_g.w; @@ -1449,6 +1545,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) win->g.w = wc.width = win_g.w; win->g.h = wc.height = win_g.h; } + adjust_font(win); mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; XConfigureWindow(display, win->id, mask, &wc); XMapRaised(display, win->id); @@ -1458,6 +1555,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) j++; } + notiles: /* now, stack all the floaters and transients */ TAILQ_FOREACH(win, &ws->winlist, entry) { if (win->transient == 0 && win->floating == 0) @@ -1727,7 +1825,7 @@ struct key { { MODKEY, XK_k, focus, {.id = SWM_ARG_ID_FOCUSPREV} }, { MODKEY | ShiftMask, XK_j, swapwin, {.id = SWM_ARG_ID_SWAPNEXT} }, { MODKEY | ShiftMask, XK_k, swapwin, {.id = SWM_ARG_ID_SWAPPREV} }, - { MODKEY | ShiftMask, XK_Return, spawn, {.argv = spawn_term} }, + { MODKEY | ShiftMask, XK_Return, spawnterm, {.argv = spawn_term} }, { MODKEY, XK_p, spawnmenu, {.argv = spawn_menu} }, { MODKEY | ShiftMask, XK_q, quit, {0} }, { MODKEY, XK_q, restart, {0} }, @@ -2212,6 +2310,8 @@ unmanage_window(struct ws_win *win) unfocus_all(); } else focus_win(ws->focus); + if (ws->focus_prev == win) + ws->focus_prev = NULL; TAILQ_REMOVE(&win->ws->winlist, win, entry); set_win_state(win, WithdrawnState); @@ -2284,8 +2384,19 @@ configurerequest(XEvent *e) void configurenotify(XEvent *e) { + struct ws_win *win; + long mask; + DNPRINTF(SWM_D_EVENT, "configurenotify: window: %lu\n", e->xconfigure.window); + + win = find_window(e->xconfigure.window); + XMapWindow(display, win->id); + XGetWMNormalHints(display, win->id, &win->sh, &mask); + adjust_font(win); + XMapWindow(display, win->id); + if (font_adjusted) + stack(); } void @@ -2538,7 +2649,6 @@ new_region(struct swm_screen *s, int x, int y, int w, int h) r->ws = ws; ws->r = r; TAILQ_INSERT_TAIL(&s->rl, r, entry); - bar_setup(r); } void @@ -2728,10 +2838,11 @@ int main(int argc, char *argv[]) { struct passwd *pwd; + struct swm_region *r; char conf[PATH_MAX], *cfile = NULL; struct stat sb; XEvent e; - int xfd; + int xfd, i; fd_set rd; start_argv = argv; @@ -2768,7 +2879,11 @@ main(int argc, char *argv[]) } if (cfile) conf_load(cfile); - bar_refresh(); + + /* setup all bars */ + for (i = 0; i < ScreenCount(display); i++) + TAILQ_FOREACH(r, &screens[i].rl, entry) + bar_setup(r); /* ws[0].focus = TAILQ_FIRST(&ws[0].winlist); */