X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=6cab5d360d7cfea8d55bfbb475bcddb08256d11e;hb=76ccafd5020fed21aa64969bbd80ac44d22344c6;hp=835c1d413664ae1378ed0fb981e3acbc256e4dfa;hpb=bbb499e87a8c905214478e1badd67465701fc5cb;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index 835c1d4..6cab5d3 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -50,7 +50,7 @@ static const char *cvstag = "$scrotwm$"; -#define SWM_VERSION "0.8" +#define SWM_VERSION "0.9" #include #include @@ -140,6 +140,8 @@ u_int32_t swm_debug = 0 char **start_argv; Atom astate; +Atom aprot; +Atom adelete; int (*xerrorxlib)(Display *, XErrorEvent *); int other_wm; int running = 1; @@ -228,6 +230,7 @@ struct ws_win { int font_size_boundary[SWM_MAX_FONT_STEPS]; int font_steps; int last_inc; + int can_delete; unsigned long quirks; struct workspace *ws; /* always valid */ struct swm_screen *s; /* always valid, never changes */ @@ -246,6 +249,7 @@ void horizontal_stack(struct workspace *, struct swm_geometry *); void max_stack(struct workspace *, struct swm_geometry *); void grabbuttons(struct ws_win *, int); +void new_region(struct swm_screen *, int, int, int, int); struct layout { void (*l_stack)(struct workspace *, struct swm_geometry *); @@ -330,6 +334,8 @@ union arg { #define SWM_ARG_ID_SS_WINDOW (1) #define SWM_ARG_ID_DONTCENTER (0) #define SWM_ARG_ID_CENTER (1) +#define SWM_ARG_ID_KILLWINDOW (0) +#define SWM_ARG_ID_DELETEWINDOW (1) char **argv; }; @@ -342,13 +348,20 @@ struct quirk { #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 }, + { "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}, }; @@ -425,8 +438,6 @@ setscreencolor(char *val, int i, int c) i, ScreenCount(display)); } -void new_region(struct swm_screen *, int, int, int, int); - void custom_region(char *val) { @@ -650,7 +661,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) @@ -695,26 +705,23 @@ bar_toggle(struct swm_region *r, union arg *args) 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; - 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 @@ -810,6 +817,21 @@ version(struct swm_region *r, union arg *args) } void +client_msg(struct ws_win *win, Atom a) +{ + XClientMessageEvent cm; + + bzero(&cm, sizeof cm); + cm.type = ClientMessage; + cm.window = win->id; + cm.message_type = aprot; + cm.format = 32; + cm.data.l[0] = a; + cm.data.l[1] = CurrentTime; + XSendEvent(display, win->id, False, 0L, (XEvent *)&cm); +} + +void config_win(struct ws_win *win) { XConfigureEvent ce; @@ -1349,7 +1371,11 @@ stack_floater(struct ws_win *win, struct swm_region *r) 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; @@ -1410,8 +1436,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; @@ -1426,7 +1453,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; @@ -1460,14 +1493,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; @@ -1558,6 +1585,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) @@ -1763,9 +1791,16 @@ send_to_ws(struct swm_region *r, union arg *args) void wkill(struct swm_region *r, union arg *args) { - DNPRINTF(SWM_D_MISC, "wkill\n"); - if(r->ws->focus != NULL) + DNPRINTF(SWM_D_MISC, "wkill %d\n", args->id); + + if(r->ws->focus == NULL) + return; + + if (args->id == SWM_ARG_ID_KILLWINDOW) XKillClient(display, r->ws->focus->id); + else + if (r->ws->focus->can_delete) + client_msg(r->ws->focus, adelete); } void @@ -1859,7 +1894,8 @@ struct key { { MODKEY, XK_b, bar_toggle, {0} }, { MODKEY, XK_Tab, focus, {.id = SWM_ARG_ID_FOCUSNEXT} }, { MODKEY | ShiftMask, XK_Tab, focus, {.id = SWM_ARG_ID_FOCUSPREV} }, - { MODKEY | ShiftMask, XK_x, wkill, {0} }, + { MODKEY | ShiftMask, XK_x, wkill, {.id = SWM_ARG_ID_KILLWINDOW} }, + { MODKEY, XK_x, wkill, {.id = SWM_ARG_ID_DELETEWINDOW} }, { MODKEY, XK_s, screenshot, {.id = SWM_ARG_ID_SS_ALL} }, { MODKEY | ShiftMask, XK_s, screenshot, {.id = SWM_ARG_ID_SS_WINDOW} }, { MODKEY, XK_t, floating_toggle,{0} }, @@ -1920,10 +1956,10 @@ resize(struct ws_win *win, union arg *args) handler[ev.type](&ev); break; case MotionNotify: - if (ev.xmotion.x < 0) - ev.xmotion.x = 0; - if (ev.xmotion.y < 0) - ev.xmotion.y = 0; + if (ev.xmotion.x <= 1) + ev.xmotion.x = 1; + if (ev.xmotion.y <= 1) + ev.xmotion.y = 1; win->g.w = ev.xmotion.x; win->g.h = ev.xmotion.y; @@ -2171,9 +2207,10 @@ manage_window(Window id) Window trans; struct workspace *ws; struct ws_win *win; - int format, i, ws_idx; + int format, i, ws_idx, n; unsigned long nitems, bytes; Atom ws_idx_atom = 0, type; + Atom *prot = NULL, *pp; unsigned char ws_idx_str[SWM_PROPLEN], *prop = NULL; struct swm_region *r; long mask; @@ -2199,6 +2236,14 @@ manage_window(Window id) DNPRINTF(SWM_D_MISC, "manage_window: win %u transient %u\n", (unsigned)win->id, win->transient); } + /* get supported protocols */ + if (XGetWMProtocols(display, id, &prot, &n)) { + for (i = 0, pp = prot; i < n; i++, pp++) + if (*pp == adelete) + win->can_delete = 1; + if (prot) + XFree(prot); + } /* * Figure out where to put the window. If it was previously assigned to @@ -2272,6 +2317,14 @@ manage_window(Window id) 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); @@ -2362,13 +2415,13 @@ configurerequest(XEvent *e) 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; } @@ -2573,13 +2626,12 @@ getstate(Window w) 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); } @@ -2651,7 +2703,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 @@ -2738,6 +2789,11 @@ screenchange(XEvent *e) { 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(); } @@ -2841,10 +2897,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; @@ -2860,6 +2917,8 @@ main(int argc, char *argv[]) errx(1, "other wm running"); astate = XInternAtom(display, "WM_STATE", False); + aprot = XInternAtom(display, "WM_PROTOCOLS", False); + adelete = XInternAtom(display, "WM_DELETE_WINDOW", False); /* look for local and global conf file */ pwd = getpwuid(getuid()); @@ -2881,7 +2940,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); */