static const char *cvstag = "$scrotwm$";
-#define SWM_VERSION "0.8"
+#define SWM_VERSION "0.9.1"
#include <stdio.h>
#include <stdlib.h>
/* dialog windows */
double dialog_ratio = .6;
/* status bar */
-#define SWM_BAR_MAX (128)
+#define SWM_BAR_MAX (256)
char *bar_argv[] = { NULL, NULL };
int bar_pipe[2];
char bar_ext[SWM_BAR_MAX];
int bar_extra_running = 0;
int bar_verbose = 1;
int bar_height = 0;
+int clock_enabled = 1;
pid_t bar_pid;
GC bar_gc;
XGCValues bar_gcv;
int bar_fidx = 0;
XFontStruct *bar_fs;
char *bar_fonts[] = {
- "-*-terminus-*-*-*-*-*-*-*-*-*-*-*-*",
+ "-*-terminus-medium-*-*-*-*-*-*-*-*-*-*-*",
"-*-times-medium-r-*-*-*-*-*-*-*-*-*-*",
NULL
};
void max_stack(struct workspace *, struct swm_geometry *);
void grabbuttons(struct ws_win *, int);
+void new_region(struct swm_screen *, int, int, int, int);
+void update_modkey(unsigned int);
struct layout {
void (*l_stack)(struct workspace *, struct swm_geometry *);
#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 */
+#define SWM_Q_FULLSCREEN (1<<4) /* remove border */
} quirks[] = {
- { "MPlayer", "xv", SWM_Q_FLOAT },
+ { "MPlayer", "xv", SWM_Q_FLOAT | SWM_Q_FULLSCREEN },
{ "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},
+ { "Firefox-bin", "firefox-bin", SWM_Q_TRANSSZ },
+ { "Firefox", "Dialog", SWM_Q_FLOAT },
+ { "Gimp", "gimp", SWM_Q_FLOAT | SWM_Q_ANYWHERE },
+ { "XTerm", "xterm", SWM_Q_XTERM_FONTADJ },
+ { "xine", "Xine Window", SWM_Q_FLOAT | SWM_Q_ANYWHERE },
+ { "Xitk", "Xitk Combo", SWM_Q_FLOAT | SWM_Q_ANYWHERE },
+ { "xine", "xine Panel", SWM_Q_FLOAT | SWM_Q_ANYWHERE },
+ { "Xitk", "Xine Window", SWM_Q_FLOAT | SWM_Q_ANYWHERE },
+ { "xine", "xine Video Fullscreen Window", SWM_Q_FULLSCREEN | SWM_Q_FLOAT },
+ { "pcb", "pcb", SWM_Q_FLOAT },
{ NULL, NULL, 0},
};
void destroynotify(XEvent *);
void enternotify(XEvent *);
void focusin(XEvent *);
+void focusout(XEvent *);
void mappingnotify(XEvent *);
void maprequest(XEvent *);
void propertynotify(XEvent *);
[DestroyNotify] = destroynotify,
[EnterNotify] = enternotify,
[FocusIn] = focusin,
+ [FocusOut] = focusout,
[MappingNotify] = mappingnotify,
[MapRequest] = maprequest,
[PropertyNotify] = propertynotify,
i, ScreenCount(display));
}
-void new_region(struct swm_screen *, int, int, int, int);
-
void
custom_region(char *val)
{
char *line, *cp, *var, *val;
size_t len, lineno = 0;
int i, sc;
+ unsigned int modkey;
DNPRINTF(SWM_D_MISC, "conf_load: filename %s\n", filename);
break;
case 'c':
- if (!varmatch(var, "color_focus", &i))
+ if (!strncmp(var, "clock_enabled", strlen("clock_enabled")))
+ clock_enabled = atoi(val);
+ else if (!varmatch(var, "color_focus", &i))
setscreencolor(val, i, SWM_S_COLOR_FOCUS);
else if (!varmatch(var, "color_unfocus", &i))
setscreencolor(val, i, SWM_S_COLOR_UNFOCUS);
goto bad;
break;
+ case 'm':
+ if (!strncmp(var, "modkey", strlen("modkey"))) {
+ modkey = MODKEY;
+ if (!strncmp(val, "Mod2", strlen("Mod2")))
+ modkey = Mod2Mask;
+ else if (!strncmp(val, "Mod3", strlen("Mod3")))
+ modkey = Mod3Mask;
+ else if (!strncmp(val, "Mod4", strlen("Mod4")))
+ modkey = Mod4Mask;
+ else
+ modkey = Mod1Mask;
+ update_modkey(modkey);
+ } else
+ goto bad;
+ break;
+
case 'r':
if (!strncmp(var, "region", strlen("region")))
custom_region(val);
} else
strlcpy(bar_ext, "", sizeof bar_ext);
- time(&tmt);
- localtime_r(&tmt, &tm);
- strftime(s, sizeof s, "%a %b %d %R %Z %Y", &tm);
+ if (clock_enabled == 0)
+ strlcpy(s, "", sizeof s);
+ else {
+ time(&tmt);
+ localtime_r(&tmt, &tm);
+ strftime(s, sizeof s, "%a %b %d %R %Z %Y ", &tm);
+ }
for (i = 0; i < ScreenCount(display); i++) {
x = 1;
TAILQ_FOREACH(r, &screens[i].rl, entry) {
- snprintf(loc, sizeof loc, "%s %d:%d %s %s",
- s, x++, r->ws->idx + 1, bar_ext, bar_vertext);
+ snprintf(loc, sizeof loc, "%d:%d %s%s %s",
+ x++, r->ws->idx + 1, s, bar_ext, bar_vertext);
bar_print(r, loc);
}
}
DNPRINTF(SWM_D_MISC, "bar_toggle\n");
- if (bar_enabled) {
+ if (bar_enabled)
for (i = 0; i < sc; i++)
TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
XUnmapWindow(display, tmpr->bar_window);
- } else {
+ else
for (i = 0; i < sc; i++)
TAILQ_FOREACH(tmpr, &screens[i].rl, entry)
XMapRaised(display, tmpr->bar_window);
- }
+
bar_enabled = !bar_enabled;
for (i = 0; i < sc; i++)
for (j = 0; j < SWM_WS_MAX; j++)
}
void
+unfocus_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;
+
+ if (win->ws->r == NULL)
+ return;
+
+ grabbuttons(win, 0);
+ XSetWindowBorder(display, win->id,
+ win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
+ win->got_focus = 0;
+ if (win->ws->focus == win)
+ win->ws->focus = NULL;
+ if (cur_focus == win)
+ cur_focus = NULL;
+}
+
+void
unfocus_all(void)
{
struct ws_win *win;
for (i = 0; i < ScreenCount(display); i++)
for (j = 0; j < SWM_WS_MAX; j++)
- TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry) {
- if (win->ws->r == NULL)
- continue;
- grabbuttons(win, 0);
- XSetWindowBorder(display, win->id,
- win->ws->r->s->c[SWM_S_COLOR_UNFOCUS].color);
- win->got_focus = 0;
- win->ws->focus = NULL;
- cur_focus = NULL;
- }
+ TAILQ_FOREACH(win, &screens[i].ws[j].winlist, entry)
+ unfocus_win(win);
}
void
if (win == NULL)
return;
- if (win->ws->focus != win && win->ws->focus != NULL)
- win->ws->focus_prev = win->ws->focus;
-
- unfocus_all();
+ if (cur_focus)
+ unfocus_win(cur_focus);
+ if (win->ws->focus) {
+ /* probably shouldn't happen due to the previous unfocus_win */
+ DNPRINTF(SWM_D_FOCUS, "unfocusing win->ws->focus: %lu\n",
+ win->ws->focus->id);
+ unfocus_win(win->ws->focus);
+ }
win->ws->focus = win;
if (win->ws->r != NULL) {
cur_focus = win;
ignore_enter = 1;
/* set focus */
+ if (new_ws->focus == NULL)
+ new_ws->focus = TAILQ_FIRST(&new_ws->winlist);
if (new_ws->focus)
focus_win(new_ws->focus);
stack();
case SWM_ARG_ID_FOCUSMAIN:
winfocus = TAILQ_FIRST(wl);
+ if (winfocus == cur_focus)
+ winfocus = cur_focus->ws->focus_prev;
+ if (winfocus == NULL)
+ return;
break;
default:
bzero(&wc, sizeof wc);
mask = CWX | CWY | CWBorderWidth | CWWidth | CWHeight;
- wc.border_width = 1;
+ if ((win->quirks & SWM_Q_FULLSCREEN) && (win->g.w == WIDTH(r)) &&
+ (win->g.h == HEIGHT(r)))
+ wc.border_width = 0;
+ else
+ wc.border_width = 1;
if (win->transient && (win->quirks & SWM_Q_TRANSSZ)) {
win->g.w = (double)WIDTH(r) * dialog_ratio;
win->g.h = (double)HEIGHT(r) * dialog_ratio;
};
void
+update_modkey(unsigned int mod)
+{
+ int i;
+
+ for (i = 0; i < LENGTH(keys); i++)
+ if (keys[i].mod & ShiftMask)
+ keys[i].mod = mod | ShiftMask;
+ else
+ keys[i].mod = mod;
+
+ for (i = 0; i < LENGTH(buttons); i++)
+ if (buttons[i].mask & ShiftMask)
+ buttons[i].mask = mod | ShiftMask;
+ else
+ buttons[i].mask = mod;
+}
+
+void
updatenumlockmask(void)
{
unsigned int i, j;
XConfigureWindow(display, win->id, mask, &wc);
}
+ /* Reset font sizes (the bruteforce way; no default keybinding). */
+ if (win->quirks & SWM_Q_XTERM_FONTADJ) {
+ for (i = 0; i < SWM_MAX_FONT_STEPS; i++)
+ fake_keypress(win, XK_KP_Subtract, ShiftMask);
+ for (i = 0; i < SWM_MAX_FONT_STEPS; i++)
+ fake_keypress(win, XK_KP_Add, ShiftMask);
+ }
+
XSelectInput(display, id, EnterWindowMask | FocusChangeMask |
PropertyChangeMask | StructureNotifyMask);
ws->focus = TAILQ_FIRST(&ws->winlist);
if (ws->focus == NULL || ws->focus == win) {
ws->focus = NULL;
- unfocus_all();
+ unfocus_win(win);
} else
focus_win(ws->focus);
if (ws->focus_prev == win)
if (win->ws->r != NULL) {
/* this seems to be full screen */
if (win->g.w >= WIDTH(win->ws->r)) {
- win->g.x = -1;
+ win->g.x = 0;
win->g.w = WIDTH(win->ws->r);
ev->value_mask |= CWX | CWWidth;
}
if (win->g.h >= HEIGHT(win->ws->r)) {
/* kill border */
- win->g.y = -1;
+ win->g.y = 0;
win->g.h = HEIGHT(win->ws->r);
ev->value_mask |= CWY | CWHeight;
}
DNPRINTF(SWM_D_EVENT, "configurenotify: window: %lu\n",
e->xconfigure.window);
+ XMapWindow(display, 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();
+ if (win) {
+ XGetWMNormalHints(display, win->id, &win->sh, &mask);
+ adjust_font(win);
+ XMapWindow(display, win->id);
+ if (font_adjusted)
+ stack();
+ }
}
void
}
void
+focusout(XEvent *e)
+{
+ DNPRINTF(SWM_D_EVENT, "focusout: window: %lu\n", e->xfocus.window);
+
+ if (cur_focus && cur_focus->ws->r &&
+ cur_focus->id == e->xfocus.window) {
+ struct swm_screen *s = cur_focus->ws->r->s;
+ Window rr, cr;
+ int x, y, wx, wy;
+ unsigned int mask;
+
+ /* Try to detect synergy hiding the cursor. */
+ if (XQueryPointer(display, cur_focus->id,
+ &rr, &cr, &x, &y, &wx, &wy, &mask) != False &&
+ cr == 0 && !mask &&
+ x == DisplayWidth(display, s->idx)/2 &&
+ y == DisplayHeight(display, s->idx)/2) {
+ unfocus_win(cur_focus);
+ }
+ }
+}
+
+void
mappingnotify(XEvent *e)
{
XMappingEvent *ev = &e->xmapping;
unsigned long n, extra;
Atom real;
- astate = XInternAtom(display, "WM_STATE", False);
status = XGetWindowProperty(display, w, astate, 0L, 2L, False, astate,
&real, &format, &n, &extra, (unsigned char **)&p);
if (status != Success)
return (-1);
if (n != 0)
- result = *p;
+ result = *((long *)p);
XFree(p);
return (result);
}
TAILQ_FOREACH(r, &screens[i].rl, entry)
TAILQ_FOREACH(win, &r->ws->winlist, entry)
XUnmapWindow(display, win->id);
+
+ /* add bars to all regions */
+ for (i = 0; i < ScreenCount(display); i++)
+ TAILQ_FOREACH(r, &screens[i].rl, entry)
+ bar_setup(r);
stack();
}
}
}
+void
+workaround(void)
+{
+ int i;
+ Atom netwmcheck, netwmname, utf8_string;
+ Window root;
+
+ /* work around sun jdk bugs, code from wmname */
+ netwmcheck = XInternAtom(display, "_NET_SUPPORTING_WM_CHECK", False);
+ netwmname = XInternAtom(display, "_NET_WM_NAME", False);
+ utf8_string = XInternAtom(display, "UTF8_STRING", False);
+ for (i = 0; i < ScreenCount(display); i++) {
+ root = screens[i].root;
+ XChangeProperty(display, root, netwmcheck, XA_WINDOW, 32,
+ PropModeReplace, (unsigned char *)&root, 1);
+ XChangeProperty(display, root, netwmname, utf8_string, 8,
+ PropModeReplace, "LG3D", strlen("LG3D"));
+ }
+}
+
int
main(int argc, char *argv[])
{
TAILQ_FOREACH(r, &screens[i].rl, entry)
bar_setup(r);
- /* ws[0].focus = TAILQ_FIRST(&ws[0].winlist); */
+ /* set some values to work around bad programs */
+ workaround();
grabkeys();
stack();