X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=6f891fe1e59a537525fe7ab1daecb6fac6b88cff;hb=80969cf8c29a2dafad8dd7cd15b8aea39110f876;hp=572be960929a8e78c1b9150886e872c9c9d13b87;hpb=97f28c42c72e35b7cc8e24878d4c9f7fa9c4f5fb;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index 572be96..6f891fe 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -128,9 +128,9 @@ u_int32_t swm_debug = 0 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define SWM_PROPLEN (16) -#define X(r) (r)->g.x +#define X(r) (r)->g.x #define Y(r) (r)->g.y -#define WIDTH(r) (r)->g.w +#define WIDTH(r) (r)->g.w #define HEIGHT(r) (r)->g.h #ifndef SWM_LIB @@ -143,6 +143,7 @@ int (*xerrorxlib)(Display *, XErrorEvent *); int other_wm; int running = 1; int ss_enabled = 0; +int xrandr_support; int xrandr_eventbase; int ignore_enter = 0; unsigned int numlockmask = 0; @@ -220,6 +221,7 @@ struct ws_win { int floating; int transient; int manual; + unsigned long quirks; struct workspace *ws; /* always valid */ struct swm_screen *s; /* always valid, never changes */ XWindowAttributes wa; @@ -265,8 +267,10 @@ struct workspace { struct { int horizontal_msize; int horizontal_mwin; + int horizontal_stacks; int vertical_msize; int vertical_mwin; + int vertical_stacks; } l_state; }; @@ -278,8 +282,8 @@ enum { SWM_S_COLOR_BAR, SWM_S_COLOR_BAR_BORDER, SWM_S_COLOR_BAR_FONT, struct swm_screen { int idx; /* screen index */ struct swm_region_list rl; /* list of regions on this screen */ + struct swm_region_list orl; /* list of old regions */ Window root; - int xrandr_support; struct workspace ws[SWM_WS_MAX]; /* colors */ @@ -312,6 +316,10 @@ union arg { #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_COLINC (16) +#define SWM_ARG_ID_COLDEC (17) +#define SWM_ARG_ID_ROWINC (16) +#define SWM_ARG_ID_ROWDEL (17) #define SWM_ARG_ID_SS_ALL (0) #define SWM_ARG_ID_SS_WINDOW (1) #define SWM_ARG_ID_DONTCENTER (0) @@ -325,9 +333,12 @@ struct quirk { char *name; unsigned long quirk; #define SWM_Q_FLOAT (1<<0) +#define SWM_Q_TRANSSZ (1<<1) } 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}, { NULL, NULL, 0}, }; @@ -404,8 +415,7 @@ setscreencolor(char *val, int i, int c) i, ScreenCount(display)); } -void new_region(struct swm_screen *, struct workspace *, - int, int, int, int); +void new_region(struct swm_screen *, int, int, int, int); void custom_region(char *val) @@ -431,7 +441,7 @@ custom_region(char *val) "(%ux%u)\n", w, h, x, y, DisplayWidth(display, sidx), DisplayHeight(display, sidx)); - new_region(&screens[sidx], NULL, x, y, w, h); + new_region(&screens[sidx], x, y, w, h); } int @@ -860,7 +870,7 @@ restart(struct swm_region *r, union arg *args) struct swm_region * root_to_region(Window root) { - struct swm_region *r; + struct swm_region *r = NULL; Window rr, cr; int i, x, y, wx, wy; unsigned int mask; @@ -870,20 +880,17 @@ root_to_region(Window root) break; if (XQueryPointer(display, screens[i].root, - &rr, &cr, &x, &y, &wx, &wy, &mask) == False) { - /* if we can't query the pointer, grab the first region */ - r = TAILQ_FIRST(&screens[i].rl); - } else { - /* otherwise, choose a region based on pointer location */ - TAILQ_FOREACH(r, &screens[i].rl, entry) { + &rr, &cr, &x, &y, &wx, &wy, &mask) != False) { + /* choose a region based on pointer location */ + TAILQ_FOREACH(r, &screens[i].rl, entry) if (x >= X(r) && x <= X(r) + WIDTH(r) && y >= Y(r) && y <= Y(r) + HEIGHT(r)) break; - } - - if (r == NULL) - r = TAILQ_FIRST(&screens[i].rl); } + + if (r == NULL) + r = TAILQ_FIRST(&screens[i].rl); + return (r); } @@ -1023,13 +1030,14 @@ switchws(struct swm_region *r, union arg *args) if (!other_r) { /* if the other workspace is hidden, switch windows */ /* map new window first to prevent ugly blinking */ + old_ws->r = NULL; + old_ws->restack = 1; + TAILQ_FOREACH(win, &new_ws->winlist, entry) XMapRaised(display, win->id); TAILQ_FOREACH(win, &old_ws->winlist, entry) XUnmapWindow(display, win->id); - old_ws->r = NULL; - old_ws->restack = 1; } else { other_r->ws = old_ws; old_ws->r = other_r; @@ -1271,7 +1279,7 @@ 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->transient) { + if (win->transient && (win->quirks & SWM_Q_TRANSSZ)) { win->g.w = (double)WIDTH(r) * dialog_ratio; win->g.h = (double)HEIGHT(r) * dialog_ratio; } @@ -1302,7 +1310,7 @@ 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, w_inc, h_inc, w_base, h_base; + int i, j, s, w_inc, h_inc, w_base, h_base, stacks; int hrh, extra, h_slice, last_h = 0; int split, colno, winno, mwin, msize, mscale; int remain, missing, v_slice;; @@ -1324,22 +1332,27 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) w_base = win->sh.base_width; mwin = ws->l_state.horizontal_mwin; mscale = ws->l_state.horizontal_msize; + stacks = ws->l_state.horizontal_stacks; 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; + stacks = ws->l_state.vertical_stacks; } win_g = r_g; + if (stacks > winno - mwin) + stacks = winno - mwin; + 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 = v_slice * mscale; + win_g.w = v_slice * mscale; if (w_inc > 1 && w_inc < v_slice) { /* adjust for window's requested size increment */ @@ -1355,32 +1368,40 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) } } - win_g.w = msize; + msize = win_g.w; if (flip) win_g.x += r_g.w - msize; } else { - colno = winno; - split = 0; + if (stacks > 1) { + colno = split = (winno - mwin) / stacks; + } else { + split = 0; + colno = winno; + } } hrh = r_g.h / colno; extra = r_g.h - (colno * hrh); win_g.h = hrh - 2; /* stack all the tiled windows */ - i = j = 0; + i = j = 0, s = stacks; TAILQ_FOREACH(win, &ws->winlist, entry) { if (win->transient != 0 || win->floating != 0) continue; if (split && i == split) { - colno = winno - split; + colno = (winno - split) / s; + if (stacks == 1) + colno += (winno - split) % s; + split = split + colno; hrh = (r_g.h / colno); 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.x += win_g.w + 2; + win_g.w = (r_g.w - (msize + 2) - (stacks * 2)) / stacks; + s--; j = 0; } win_g.h = hrh - 2; @@ -1388,7 +1409,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) h_inc = win->sh.width_inc; h_base = win->sh.base_width; } else { - h_inc = win->sh.height_inc; + h_inc = win->sh.height_inc; h_base = win->sh.base_height; } if (j == colno - 1) { @@ -1428,9 +1449,6 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth; XConfigureWindow(display, win->id, mask, &wc); XMapRaised(display, win->id); - /* - fprintf(stderr, "vertical_stack: win %d x %d y %d w %d h %d bw %d\n", win->id, win->g.x, win->g.y, win->g.w , win->g.h, wc.border_width); - */ last_h = win_g.h; i++; @@ -1460,6 +1478,7 @@ vertical_config(struct workspace *ws, int id) case SWM_ARG_ID_STACKINIT: ws->l_state.vertical_msize = SWM_V_SLICE / 2; ws->l_state.vertical_mwin = 1; + ws->l_state.vertical_stacks = 1; break; case SWM_ARG_ID_MASTERSHRINK: if (ws->l_state.vertical_msize > 1) @@ -1475,6 +1494,12 @@ vertical_config(struct workspace *ws, int id) case SWM_ARG_ID_MASTERDEL: if (ws->l_state.vertical_mwin > 0) ws->l_state.vertical_mwin--; + case SWM_ARG_ID_COLINC: + ws->l_state.vertical_stacks++; + break; + case SWM_ARG_ID_COLDEC: + if (ws->l_state.vertical_stacks > 1) + ws->l_state.vertical_stacks--; break; default: return; @@ -1499,6 +1524,7 @@ horizontal_config(struct workspace *ws, int id) case SWM_ARG_ID_STACKINIT: ws->l_state.horizontal_mwin = 1; ws->l_state.horizontal_msize = SWM_H_SLICE / 2; + ws->l_state.horizontal_stacks = 1; break; case SWM_ARG_ID_MASTERSHRINK: if (ws->l_state.horizontal_msize > 1) @@ -1515,6 +1541,12 @@ horizontal_config(struct workspace *ws, int id) if (ws->l_state.horizontal_mwin > 0) ws->l_state.horizontal_mwin--; break; + case SWM_ARG_ID_COLINC: + ws->l_state.horizontal_stacks++; + break; + case SWM_ARG_ID_COLDEC: + if (ws->l_state.horizontal_stacks > 1) + ws->l_state.horizontal_stacks--; default: return; } @@ -1683,6 +1715,8 @@ struct key { { MODKEY, XK_l, stack_config, {.id = SWM_ARG_ID_MASTERGROW} }, { MODKEY, XK_comma, stack_config, {.id = SWM_ARG_ID_MASTERADD} }, { MODKEY, XK_period, stack_config, {.id = SWM_ARG_ID_MASTERDEL} }, + { MODKEY | ShiftMask, XK_comma, stack_config, {.id = SWM_ARG_ID_COLINC} }, + { MODKEY | ShiftMask, XK_period, stack_config, {.id = SWM_ARG_ID_COLDEC} }, { MODKEY, XK_Return, swapwin, {.id = SWM_ARG_ID_SWAPMAIN} }, { MODKEY, XK_j, focus, {.id = SWM_ARG_ID_FOCUSNEXT} }, { MODKEY, XK_k, focus, {.id = SWM_ARG_ID_FOCUSPREV} }, @@ -2058,7 +2092,7 @@ manage_window(Window id) DNPRINTF(SWM_D_MISC, "manage_window: win %u transient %u\n", (unsigned)win->id, win->transient); } - + /* * Figure out where to put the window. If it was previously assigned to * a workspace (either by spawn() or manually moving), and isn't @@ -2097,10 +2131,6 @@ manage_window(Window id) } XFree(prop); - /* - fprintf(stderr, "manage window: %d x %d y %d w %d h %d\n", win->id, win->g.x, win->g.y, win->g.w, win->g.h); - */ - if (XGetClassHint(display, win->id, &win->ch)) { DNPRINTF(SWM_D_CLASS, "class: %s name: %s\n", win->ch.res_class, win->ch.res_name); @@ -2112,6 +2142,7 @@ manage_window(Window id) win->ch.res_class, win->ch.res_name); if (quirks[i].quirk & SWM_Q_FLOAT) win->floating = 1; + win->quirks = quirks[i].quirk; } } } @@ -2128,6 +2159,41 @@ manage_window(Window id) } void +unmanage_window(struct ws_win *win) +{ + struct workspace *ws; + + if (win == NULL) + return; + + DNPRINTF(SWM_D_MISC, "unmanage_window: %lu\n", win->id); + + /* don't unmanage if we are switching workspaces */ + ws = win->ws; + if (ws->restack) + return; + + /* find a window to focus */ + if (ws->focus == win) + ws->focus = TAILQ_PREV(win, ws_win_list, entry); + if (ws->focus == NULL) + ws->focus = TAILQ_FIRST(&ws->winlist); + if (ws->focus == NULL || ws->focus == win) { + ws->focus = NULL; + unfocus_all(); + } else + focus_win(ws->focus); + + TAILQ_REMOVE(&win->ws->winlist, win, entry); + set_win_state(win, WithdrawnState); + if (win->ch.res_class) + XFree(win->ch.res_class); + if (win->ch.res_name) + XFree(win->ch.res_name); + free(win); +} + +void configurerequest(XEvent *e) { XConfigureRequestEvent *ev = &e->xconfigurerequest; @@ -2141,10 +2207,6 @@ configurerequest(XEvent *e) if (new) { DNPRINTF(SWM_D_EVENT, "configurerequest: new window: %lu\n", ev->window); - /* - fprintf(stderr, "configurerequest: new window: %lu x %d y %d w %d h %d bw %d s %d sm %d\n", - ev->window, ev->x, ev->y, ev->width, ev->height, ev->border_width, ev->above, ev->detail); - */ bzero(&wc, sizeof wc); wc.x = ev->x; wc.y = ev->y; @@ -2155,10 +2217,6 @@ configurerequest(XEvent *e) wc.stack_mode = ev->detail; XConfigureWindow(display, ev->window, ev->value_mask, &wc); } else { - /* - fprintf(stderr, "configurerequest: change window: %lu\n", - ev->window); - */ DNPRINTF(SWM_D_EVENT, "configurerequest: change window: %lu\n", ev->window); if (win->floating) { @@ -2206,29 +2264,11 @@ destroynotify(XEvent *e) { struct ws_win *win; XDestroyWindowEvent *ev = &e->xdestroywindow; - struct workspace *ws; DNPRINTF(SWM_D_EVENT, "destroynotify: window %lu\n", ev->window); if ((win = find_window(ev->window)) != NULL) { - ws = win->ws; - /* find a window to focus */ - if (ws->focus == win) - ws->focus = TAILQ_PREV(win, ws_win_list, entry); - if (ws->focus == NULL) - ws->focus = TAILQ_FIRST(&ws->winlist); - if (ws->focus == NULL || ws->focus == win) { - ws->focus = NULL; - unfocus_all(); - } else - focus_win(ws->focus); - TAILQ_REMOVE(&ws->winlist, win, entry); - set_win_state(win, WithdrawnState); - if (win->ch.res_class) - XFree(win->ch.res_class); - if (win->ch.res_name) - XFree(win->ch.res_name); - free(win); + unmanage_window(win); stack(); } } @@ -2324,7 +2364,14 @@ propertynotify(XEvent *e) void unmapnotify(XEvent *e) { + XDestroyWindowEvent *ev = &e->xdestroywindow; + struct ws_win *win; + DNPRINTF(SWM_D_EVENT, "unmapnotify: window: %lu\n", e->xunmap.window); + + if ((win = find_window(ev->window)) != NULL) + if (win->transient) + unmanage_window(win); } void @@ -2395,28 +2442,10 @@ getstate(Window w) } void -remove_region(struct swm_region *r) -{ - struct swm_screen *s = r->s; - struct ws_win *win; - - DNPRINTF(SWM_D_MISC, "removing region: screen[%d]:%dx%d+%d+%d\n", - s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r)); - - TAILQ_FOREACH(win, &r->ws->winlist, entry) - XUnmapWindow(display, win->id); - r->ws->r = NULL; - - XDestroyWindow(display, r->bar_window); - TAILQ_REMOVE(&s->rl, r, entry); - free(r); -} - -void -new_region(struct swm_screen *s, struct workspace *ws, - int x, int y, int w, int h) +new_region(struct swm_screen *s, int x, int y, int w, int h) { struct swm_region *r, *n; + struct workspace *ws = NULL; int i; DNPRINTF(SWM_D_MISC, "new region: screen[%d]:%dx%d+%d+%d\n", @@ -2431,26 +2460,45 @@ new_region(struct swm_screen *s, struct workspace *ws, (X(r) + WIDTH(r)) > x && Y(r) < (y + h) && (Y(r) + HEIGHT(r)) > y) { - if (ws == NULL) - ws = r->ws; - remove_region(r); + XDestroyWindow(display, r->bar_window); + TAILQ_REMOVE(&s->rl, r, entry); + TAILQ_INSERT_TAIL(&s->orl, r, entry); } } - /* pick an appropriate workspace */ + /* search old regions for one to reuse */ + + /* size + location match */ + TAILQ_FOREACH(r, &s->orl, entry) + if (X(r) == x && Y(r) == y && + HEIGHT(r) == h && WIDTH(r) == w) + break; + + /* size match */ + TAILQ_FOREACH(r, &s->orl, entry) + if (HEIGHT(r) == h && WIDTH(r) == w) + break; + + if (r != NULL) { + TAILQ_REMOVE(&s->orl, r, entry); + /* try to use old region's workspace */ + if (r->ws->r == NULL) + ws = r->ws; + } else + if ((r = calloc(1, sizeof(struct swm_region))) == NULL) + errx(1, "calloc: failed to allocate memory for screen"); + + /* if we don't have a workspace already, find one */ if (ws == NULL) { for (i = 0; i < SWM_WS_MAX; i++) if (s->ws[i].r == NULL) { ws = &s->ws[i]; break; } - - if (ws == NULL) - errx(1, "no free regions\n"); } - if ((r = calloc(1, sizeof(struct swm_region))) == NULL) - errx(1, "calloc: failed to allocate memory for screen"); + if (ws == NULL) + errx(1, "no free workspaces\n"); X(r) = x; Y(r) = y; @@ -2464,20 +2512,100 @@ new_region(struct swm_screen *s, struct workspace *ws, } void -setup_screens(void) +scan_xrandr(int i) { #ifdef SWM_XRR_HAS_CRTC XRRCrtcInfo *ci; XRRScreenResources *sr; int c; + int ncrtc = 0; #endif /* SWM_XRR_HAS_CRTC */ + struct swm_region *r; + + + if (i >= ScreenCount(display)) + errx(1, "invalid screen"); + + /* remove any old regions */ + while ((r = TAILQ_FIRST(&screens[i].rl)) != NULL) { + r->ws->r = NULL; + XDestroyWindow(display, r->bar_window); + TAILQ_REMOVE(&screens[i].rl, r, entry); + TAILQ_INSERT_TAIL(&screens[i].orl, r, entry); + } + + /* map virtual screens onto physical screens */ +#ifdef SWM_XRR_HAS_CRTC + if (xrandr_support) { + sr = XRRGetScreenResources(display, screens[i].root); + if (sr == NULL) + new_region(&screens[i], 0, 0, + DisplayWidth(display, i), + DisplayHeight(display, i)); + else + ncrtc = sr->ncrtc; + + for (c = 0, ci = NULL; c < ncrtc; c++) { + ci = XRRGetCrtcInfo(display, sr, sr->crtcs[c]); + if (ci->noutput == 0) + continue; + + if (ci != NULL && ci->mode == None) + new_region(&screens[i], 0, 0, + DisplayWidth(display, i), + DisplayHeight(display, i)); + else + new_region(&screens[i], + ci->x, ci->y, ci->width, ci->height); + } + if (ci) + XRRFreeCrtcInfo(ci); + XRRFreeScreenResources(sr); + } else +#endif /* SWM_XRR_HAS_CRTC */ + { + new_region(&screens[i], 0, 0, DisplayWidth(display, i), + DisplayHeight(display, i)); + } +} + +void +screenchange(XEvent *e) { + XRRScreenChangeNotifyEvent *xe = (XRRScreenChangeNotifyEvent *)e; + struct swm_region *r; + struct ws_win *win; + int i; + + DNPRINTF(SWM_D_EVENT, "screenchange: %lu\n", xe->root); + + if (!XRRUpdateConfiguration(e)) + return; + + /* silly event doesn't include the screen index */ + for (i = 0; i < ScreenCount(display); i++) + if (screens[i].root == xe->root) + break; + if (i >= ScreenCount(display)) + errx(1, "screenchange: screen not found\n"); + + /* brute force for now, just re-enumerate the regions */ + scan_xrandr(i); + + /* hide any windows that went away */ + TAILQ_FOREACH(r, &screens[i].rl, entry) + TAILQ_FOREACH(win, &r->ws->winlist, entry) + XUnmapWindow(display, win->id); + stack(); +} + +void +setup_screens(void) +{ Window d1, d2, *wins = NULL; XWindowAttributes wa; - struct swm_region *r; unsigned int no; - int errorbase, major, minor; - int ncrtc = 0, w = 0; int i, j, k; + int errorbase, major, minor; struct workspace *ws; int ws_idx_atom; @@ -2487,13 +2615,20 @@ setup_screens(void) errx(1, "calloc: screens"); ws_idx_atom = XInternAtom(display, "_SWM_WS", False); - + + /* initial Xrandr setup */ + xrandr_support = XRRQueryExtension(display, + &xrandr_eventbase, &errorbase); + if (xrandr_support) + if (XRRQueryVersion(display, &major, &minor) && major < 1) + xrandr_support = 0; /* map physical screens */ for (i = 0; i < ScreenCount(display); i++) { DNPRINTF(SWM_D_WS, "setup_screens: init screen %d\n", i); screens[i].idx = i; TAILQ_INIT(&screens[i].rl); + TAILQ_INIT(&screens[i].orl); screens[i].root = RootWindow(display, i); /* set default colors */ @@ -2504,6 +2639,7 @@ setup_screens(void) setscreencolor("rgb:a0/a0/a0", i + 1, SWM_S_COLOR_BAR_FONT); /* init all workspaces */ + /* XXX these should be dynamically allocated too */ for (j = 0; j < SWM_WS_MAX; j++) { ws = &screens[i].ws[j]; ws->idx = j; @@ -2518,83 +2654,38 @@ setup_screens(void) SWM_ARG_ID_STACKINIT); ws->cur_layout = &layouts[0]; } - - /* map virtual screens onto physical screens */ - screens[i].xrandr_support = XRRQueryExtension(display, - &xrandr_eventbase, &errorbase); - if (screens[i].xrandr_support) - if (XRRQueryVersion(display, &major, &minor) && - major < 1) - screens[i].xrandr_support = 0; - -#if 0 /* not ready for dynamic screen changes */ - if (screens[i].xrandr_support) - XRRSelectInput(display, - screens[r->s].root, - RRScreenChangeNotifyMask); -#endif - /* grab existing windows (before we build the bars)*/ if (!XQueryTree(display, screens[i].root, &d1, &d2, &wins, &no)) continue; -#ifdef SWM_XRR_HAS_CRTC - sr = XRRGetScreenResources(display, screens[i].root); - if (sr == NULL) - new_region(&screens[i], &screens[i].ws[w], - 0, 0, DisplayWidth(display, i), - DisplayHeight(display, i)); - else - ncrtc = sr->ncrtc; - - for (c = 0, ci = NULL; c < ncrtc; c++) { - ci = XRRGetCrtcInfo(display, sr, sr->crtcs[c]); - if (ci->noutput == 0) - continue; + scan_xrandr(i); - if (ci != NULL && ci->mode == None) - new_region(&screens[i], &screens[i].ws[w], 0, 0, - DisplayWidth(display, i), - DisplayHeight(display, i)); - else - new_region(&screens[i], &screens[i].ws[w], - ci->x, ci->y, ci->width, ci->height); - w++; - } - if (ci) - XRRFreeCrtcInfo(ci); - XRRFreeScreenResources(sr); -#else - new_region(&screens[i], &screens[i].ws[w], 0, 0, - DisplayWidth(display, i), - DisplayHeight(display, i)); -#endif /* SWM_XRR_HAS_CRTC */ + if (xrandr_support) + XRRSelectInput(display, screens[i].root, + RRScreenChangeNotifyMask); /* attach windows to a region */ /* normal windows */ - if ((r = TAILQ_FIRST(&screens[i].rl)) == NULL) - errx(1, "no regions on screen %d", i); - - for (i = 0; i < no; i++) { - XGetWindowAttributes(display, wins[i], &wa); - if (!XGetWindowAttributes(display, wins[i], &wa) || + for (j = 0; j < no; j++) { + XGetWindowAttributes(display, wins[j], &wa); + if (!XGetWindowAttributes(display, wins[j], &wa) || wa.override_redirect || - XGetTransientForHint(display, wins[i], &d1)) + XGetTransientForHint(display, wins[j], &d1)) continue; if (wa.map_state == IsViewable || - getstate(wins[i]) == NormalState) - manage_window(wins[i]); + getstate(wins[j]) == NormalState) + manage_window(wins[j]); } /* transient windows */ - for (i = 0; i < no; i++) { - if (!XGetWindowAttributes(display, wins[i], &wa)) + for (j = 0; j < no; j++) { + if (!XGetWindowAttributes(display, wins[j], &wa)) continue; - if (XGetTransientForHint(display, wins[i], &d1) && - (wa.map_state == IsViewable || getstate(wins[i]) == + if (XGetTransientForHint(display, wins[j], &d1) && + (wa.map_state == IsViewable || getstate(wins[j]) == NormalState)) - manage_window(wins[i]); + manage_window(wins[j]); } if (wins) { XFree(wins); @@ -2665,10 +2756,25 @@ main(int argc, char *argv[]) bar_alarm = 0; bar_update(); } - while(XPending(display)) { + while (XPending(display)) { XNextEvent(display, &e); - if (handler[e.type]) - handler[e.type](&e); + if (e.type < LASTEvent) { + if (handler[e.type]) + handler[e.type](&e); + else + DNPRINTF(SWM_D_EVENT, + "unkown event: %d\n", e.type); + } else { + switch (e.type - xrandr_eventbase) { + case RRScreenChangeNotify: + screenchange(&e); + break; + default: + DNPRINTF(SWM_D_EVENT, + "unkown event: %d\n", e.type); + break; + } + } } }