#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"
int cycle_empty = 0;
int cycle_visible = 0;
+int term_width = 0;
+int font_adjusted = 0;
/* dialog windows */
double dialog_ratio = .6;
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 */
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 */
#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},
};
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;
}
}
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]);
}
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");
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) {
void
swapwin(struct swm_region *r, union arg *args)
{
- struct ws_win *target;
+ struct ws_win *target, *source;
struct ws_win_list *wl;
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();
}
r->ws->cur_layout->l_stack(r->ws, &g);
}
}
+ if (font_adjusted)
+ font_adjusted--;
XSync(display, False);
}
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; \
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;
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;
/* 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;
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);
j++;
}
+ notiles:
/* now, stack all the floaters and transients */
TAILQ_FOREACH(win, &ws->winlist, entry) {
if (win->transient == 0 && win->floating == 0)
{ 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} },
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);
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