diff options
author | okan <okan> | 2012-07-18 21:53:22 +0000 |
---|---|---|
committer | okan <okan> | 2012-07-18 21:53:22 +0000 |
commit | 1545eb0837814fa024c0de85e64da262f6d1e209 (patch) | |
tree | 1ffbb683959e0b0f16de86d8b414f20e0de464e0 | |
parent | 8f587e6c8052543125ad4b03cc89560d05a4aca4 (diff) | |
parent | 013497c79cdb17d8a40f53d5535b4ba8362f0ef5 (diff) | |
download | cwm-1545eb0837814fa024c0de85e64da262f6d1e209.tar.gz cwm-1545eb0837814fa024c0de85e64da262f6d1e209.tar.xz cwm-1545eb0837814fa024c0de85e64da262f6d1e209.zip |
cvsimport
-rw-r--r-- | calmwm.c | 16 | ||||
-rw-r--r-- | calmwm.h | 95 | ||||
-rw-r--r-- | client.c | 218 | ||||
-rw-r--r-- | cwmrc.5 | 6 | ||||
-rw-r--r-- | group.c | 58 | ||||
-rw-r--r-- | kbfunc.c | 56 | ||||
-rw-r--r-- | menu.c | 4 | ||||
-rw-r--r-- | mousefunc.c | 38 | ||||
-rw-r--r-- | screen.c | 60 | ||||
-rw-r--r-- | xevents.c | 17 | ||||
-rw-r--r-- | xutil.c | 210 |
11 files changed, 429 insertions, 349 deletions
diff --git a/calmwm.c b/calmwm.c index 2a52f6a..911c280 100644 --- a/calmwm.c +++ b/calmwm.c @@ -44,7 +44,7 @@ Cursor Cursor_resize; struct screen_ctx_q Screenq = TAILQ_HEAD_INITIALIZER(Screenq); struct client_ctx_q Clientq = TAILQ_HEAD_INITIALIZER(Clientq); -int HasXinerama, HasRandr, Randr_ev; +int HasRandr, Randr_ev; struct conf Conf; static void sigchld_cb(int); @@ -157,7 +157,6 @@ x_setupscreen(struct screen_ctx *sc, u_int which) Window *wins, w0, w1; XWindowAttributes winattr; XSetWindowAttributes rootattr; - int fake; u_int nwins, i; sc->which = which; @@ -167,8 +166,8 @@ x_setupscreen(struct screen_ctx *sc, u_int which) xu_ewmh_net_supported_wm_check(sc); conf_gap(&Conf, sc); - screen_update_geometry(sc, DisplayWidth(X_Dpy, sc->which), - DisplayHeight(X_Dpy, sc->which)); + + screen_update_geometry(sc); conf_color(&Conf, sc); @@ -201,17 +200,8 @@ x_setupscreen(struct screen_ctx *sc, u_int which) screen_updatestackingorder(sc); - if (XineramaQueryExtension(X_Dpy, &fake, &fake) == 1 && - ((HasXinerama = XineramaIsActive(X_Dpy)) == 1)) - HasXinerama = 1; if (HasRandr) XRRSelectInput(X_Dpy, sc->rootwin, RRScreenChangeNotifyMask); - /* - * initial setup of xinerama screens, if we're using RandR then we'll - * redo this whenever the screen changes since a CTRC may have been - * added or removed - */ - screen_init_xinerama(sc); XSync(X_Dpy, False); } diff --git a/calmwm.h b/calmwm.h index bf08c93..8dffc68 100644 --- a/calmwm.h +++ b/calmwm.h @@ -108,6 +108,13 @@ struct color { unsigned long pixel; }; +struct geom { + int x; + int y; + int w; + int h; +}; + struct gap { int top; int bottom; @@ -130,12 +137,7 @@ struct client_ctx { XSizeHints *size; Colormap cmap; u_int bwidth; /* border width */ - struct { - int x; /* x position */ - int y; /* y position */ - int width; /* width */ - int height;/* height */ - } geom, savegeom; + struct geom geom, savegeom; struct { int basew; /* desired width */ int baseh; /* desired height */ @@ -216,8 +218,8 @@ struct screen_ctx { struct color color[CWM_COLOR_MAX]; GC gc; int cycling; - int xmax; - int ymax; + struct geom view; /* viewable area */ + struct geom work; /* workable area, gap-applied */ struct gap gap; struct cycle_entry_q mruq; XftColor xftcolor; @@ -372,8 +374,7 @@ void search_print_client(struct menu *, int); XineramaScreenInfo *screen_find_xinerama(struct screen_ctx *, int, int); struct screen_ctx *screen_fromroot(Window); -void screen_init_xinerama(struct screen_ctx *); -void screen_update_geometry(struct screen_ctx *, int, int); +void screen_update_geometry(struct screen_ctx *); void screen_updatestackingorder(struct screen_ctx *); void kbfunc_client_cycle(struct client_ctx *, union arg *); @@ -478,6 +479,19 @@ void xu_setstate(struct client_ctx *, int); void xu_ewmh_net_supported(struct screen_ctx *); void xu_ewmh_net_supported_wm_check(struct screen_ctx *); +void xu_ewmh_net_desktop_geometry(struct screen_ctx *); +void xu_ewmh_net_workarea(struct screen_ctx *); +void xu_ewmh_net_client_list(struct screen_ctx *); +void xu_ewmh_net_active_window(struct screen_ctx *, Window); +void xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *); +void xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *); +void xu_ewmh_net_showing_desktop(struct screen_ctx *); +void xu_ewmh_net_virtual_roots(struct screen_ctx *); +void xu_ewmh_net_current_desktop(struct screen_ctx *, long); +void xu_ewmh_net_desktop_names(struct screen_ctx *, unsigned char *, int); + +void xu_ewmh_net_wm_desktop(struct client_ctx *); + void u_exec(char *); void u_spawn(char *); @@ -502,34 +516,37 @@ extern struct conf Conf; extern int HasXinerama, HasRandr, Randr_ev; -#define WM_STATE cwm_atoms[0] -#define WM_DELETE_WINDOW cwm_atoms[1] -#define WM_TAKE_FOCUS cwm_atoms[2] -#define WM_PROTOCOLS cwm_atoms[3] -#define _MOTIF_WM_HINTS cwm_atoms[4] -#define UTF8_STRING cwm_atoms[5] -/* - * please make all hints below this point netwm hints, starting with - * _NET_SUPPORTED. If you change other hints make sure you update - * CWM_NETWM_START - */ -#define _NET_SUPPORTED cwm_atoms[6] -#define _NET_SUPPORTING_WM_CHECK cwm_atoms[7] -#define _NET_WM_NAME cwm_atoms[8] -#define _NET_ACTIVE_WINDOW cwm_atoms[9] -#define _NET_CLIENT_LIST cwm_atoms[10] -#define _NET_NUMBER_OF_DESKTOPS cwm_atoms[11] -#define _NET_CURRENT_DESKTOP cwm_atoms[12] -#define _NET_DESKTOP_VIEWPORT cwm_atoms[13] -#define _NET_DESKTOP_GEOMETRY cwm_atoms[14] -#define _NET_VIRTUAL_ROOTS cwm_atoms[15] -#define _NET_SHOWING_DESKTOP cwm_atoms[16] -#define _NET_DESKTOP_NAMES cwm_atoms[17] -#define _NET_WM_DESKTOP cwm_atoms[18] -#define _NET_WORKAREA cwm_atoms[19] -#define CWM_NO_ATOMS 20 -#define CWM_NETWM_START 6 - -extern Atom cwm_atoms[CWM_NO_ATOMS]; +enum { + WM_STATE, + WM_DELETE_WINDOW, + WM_TAKE_FOCUS, + WM_PROTOCOLS, + _MOTIF_WM_HINTS, + UTF8_STRING, + CWMH_NITEMS +}; +enum { + _NET_SUPPORTED, + _NET_SUPPORTING_WM_CHECK, + _NET_ACTIVE_WINDOW, + _NET_CLIENT_LIST, + _NET_NUMBER_OF_DESKTOPS, + _NET_CURRENT_DESKTOP, + _NET_DESKTOP_VIEWPORT, + _NET_DESKTOP_GEOMETRY, + _NET_VIRTUAL_ROOTS, + _NET_SHOWING_DESKTOP, + _NET_DESKTOP_NAMES, + _NET_WORKAREA, + _NET_WM_NAME, + _NET_WM_DESKTOP, + EWMH_NITEMS +}; +struct atom_ctx { + char *name; + Atom atom; +}; +extern struct atom_ctx cwmh[CWMH_NITEMS]; +extern struct atom_ctx ewmh[EWMH_NITEMS]; #endif /* _CALMWM_H_ */ diff --git a/client.c b/client.c index 5fe7aaf..15052eb 100644 --- a/client.c +++ b/client.c @@ -89,8 +89,8 @@ client_new(Window win, struct screen_ctx *sc, int mapped) XGetWindowAttributes(X_Dpy, cc->win, &wattr); cc->geom.x = wattr.x; cc->geom.y = wattr.y; - cc->geom.width = wattr.width; - cc->geom.height = wattr.height; + cc->geom.w = wattr.width; + cc->geom.h = wattr.height; cc->cmap = wattr.colormap; if (wattr.map_state != IsViewable) { @@ -126,9 +126,8 @@ client_new(Window win, struct screen_ctx *sc, int mapped) TAILQ_INSERT_TAIL(&sc->mruq, cc, mru_entry); TAILQ_INSERT_TAIL(&Clientq, cc, entry); - /* append to the client list */ - XChangeProperty(X_Dpy, sc->rootwin, _NET_CLIENT_LIST, XA_WINDOW, 32, - PropModeAppend, (unsigned char *)&cc->win, 1); + + xu_ewmh_net_client_list(sc); client_gethints(cc); client_update(cc); @@ -143,10 +142,7 @@ void client_delete(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; - struct client_ctx *tcc; struct winname *wn; - Window *winlist; - int i, j; group_client_delete(cc); @@ -159,23 +155,8 @@ client_delete(struct client_ctx *cc) TAILQ_REMOVE(&sc->mruq, cc, mru_entry); TAILQ_REMOVE(&Clientq, cc, entry); - /* - * Sadly we can't remove just one entry from a property, so we must - * redo the whole thing from scratch. this is the stupid way, the other - * way incurs many roundtrips to the server. - */ - i = j = 0; - TAILQ_FOREACH(tcc, &Clientq, entry) - i++; - if (i > 0) { - winlist = xmalloc(i * sizeof(*winlist)); - TAILQ_FOREACH(tcc, &Clientq, entry) - winlist[j++] = tcc->win; - XChangeProperty(X_Dpy, sc->rootwin, _NET_CLIENT_LIST, - XA_WINDOW, 32, PropModeReplace, - (unsigned char *)winlist, i); - xfree(winlist); - } + + xu_ewmh_net_client_list(sc); if (_curcc == cc) client_none(sc); @@ -236,9 +217,7 @@ client_setactive(struct client_ctx *cc, int fg) if (fg && _curcc != cc) { client_setactive(NULL, 0); _curcc = cc; - XChangeProperty(X_Dpy, sc->rootwin, _NET_ACTIVE_WINDOW, - XA_WINDOW, 32, PropModeReplace, - (unsigned char *)&cc->win, 1); + xu_ewmh_net_active_window(sc, cc->win); } cc->active = fg; @@ -253,8 +232,8 @@ client_none(struct screen_ctx *sc) { Window none = None; - XChangeProperty(X_Dpy, sc->rootwin, _NET_ACTIVE_WINDOW, - XA_WINDOW, 32, PropModeReplace, (unsigned char *)&none, 1); + xu_ewmh_net_active_window(sc, none); + _curcc = NULL; } @@ -277,8 +256,8 @@ void client_maximize(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; - int xmax = sc->xmax, ymax = sc->ymax; - int x_org = 0, y_org = 0; + int x_org, y_org, xmax, ymax; + XineramaScreenInfo *xine; if (cc->flags & CLIENT_FREEZE) return; @@ -291,37 +270,38 @@ client_maximize(struct client_ctx *cc) } if ((cc->flags & CLIENT_VMAXIMIZED) == 0) { - cc->savegeom.height = cc->geom.height; + cc->savegeom.h = cc->geom.h; cc->savegeom.y = cc->geom.y; } if ((cc->flags & CLIENT_HMAXIMIZED) == 0) { - cc->savegeom.width = cc->geom.width; + cc->savegeom.w = cc->geom.w; cc->savegeom.x = cc->geom.x; } - if (HasXinerama) { - XineramaScreenInfo *xine; - /* - * pick screen that the middle of the window is on. - * that's probably more fair than if just the origin of - * a window is poking over a boundary - */ - xine = screen_find_xinerama(sc, - cc->geom.x + cc->geom.width / 2, - cc->geom.y + cc->geom.height / 2); - if (xine == NULL) - goto calc; + /* + * pick screen that the middle of the window is on. + * that's probably more fair than if just the origin of + * a window is poking over a boundary + */ + xine = screen_find_xinerama(sc, + cc->geom.x + cc->geom.w / 2, + cc->geom.y + cc->geom.h / 2); + if (xine) { x_org = xine->x_org; y_org = xine->y_org; xmax = xine->width; ymax = xine->height; + } else { + x_org = y_org = 0; + xmax = sc->view.w; + ymax = sc->view.h; } -calc: + cc->geom.x = x_org + sc->gap.left; cc->geom.y = y_org + sc->gap.top; - cc->geom.height = ymax - (sc->gap.top + sc->gap.bottom); - cc->geom.width = xmax - (sc->gap.left + sc->gap.right); + cc->geom.h = ymax - (sc->gap.top + sc->gap.bottom); + cc->geom.w = xmax - (sc->gap.left + sc->gap.right); cc->bwidth = 0; cc->flags |= CLIENT_MAXIMIZED; @@ -333,43 +313,44 @@ void client_vertmaximize(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; - int y_org = 0, ymax = sc->ymax; + int y_org, ymax; + XineramaScreenInfo *xine; if (cc->flags & CLIENT_FREEZE) return; if (cc->flags & CLIENT_VMAXIMIZED) { cc->geom.y = cc->savegeom.y; - cc->geom.height = cc->savegeom.height; + cc->geom.h = cc->savegeom.h; cc->bwidth = Conf.bwidth; if (cc->flags & CLIENT_HMAXIMIZED) - cc->geom.width -= cc->bwidth * 2; + cc->geom.w -= cc->bwidth * 2; cc->flags &= ~CLIENT_VMAXIMIZED; goto resize; } cc->savegeom.y = cc->geom.y; - cc->savegeom.height = cc->geom.height; + cc->savegeom.h = cc->geom.h; /* if this will make us fully maximized then remove boundary */ if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_HMAXIMIZED) { - cc->geom.width += Conf.bwidth * 2; + cc->geom.w += Conf.bwidth * 2; cc->bwidth = 0; } - if (HasXinerama) { - XineramaScreenInfo *xine; - xine = screen_find_xinerama(sc, - cc->geom.x + cc->geom.width / 2, - cc->geom.y + cc->geom.height / 2); - if (xine == NULL) - goto calc; + xine = screen_find_xinerama(sc, + cc->geom.x + cc->geom.w / 2, + cc->geom.y + cc->geom.h / 2); + if (xine) { y_org = xine->y_org; ymax = xine->height; + } else { + y_org = 0; + ymax = sc->view.h; } -calc: + cc->geom.y = y_org + sc->gap.top; - cc->geom.height = ymax - (cc->bwidth * 2) - (sc->gap.top + + cc->geom.h = ymax - (cc->bwidth * 2) - (sc->gap.top + sc->gap.bottom); cc->flags |= CLIENT_VMAXIMIZED; @@ -381,43 +362,44 @@ void client_horizmaximize(struct client_ctx *cc) { struct screen_ctx *sc = cc->sc; - int x_org = 0, xmax = sc->xmax; + int x_org, xmax; + XineramaScreenInfo *xine; if (cc->flags & CLIENT_FREEZE) return; if (cc->flags & CLIENT_HMAXIMIZED) { cc->geom.x = cc->savegeom.x; - cc->geom.width = cc->savegeom.width; + cc->geom.w = cc->savegeom.w; cc->bwidth = Conf.bwidth; if (cc->flags & CLIENT_VMAXIMIZED) - cc->geom.height -= cc->bwidth * 2; + cc->geom.h -= cc->bwidth * 2; cc->flags &= ~CLIENT_HMAXIMIZED; goto resize; } cc->savegeom.x = cc->geom.x; - cc->savegeom.width = cc->geom.width; + cc->savegeom.w = cc->geom.w; /* if this will make us fully maximized then remove boundary */ if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_VMAXIMIZED) { - cc->geom.height += cc->bwidth * 2; + cc->geom.h += cc->bwidth * 2; cc->bwidth = 0; } - if (HasXinerama) { - XineramaScreenInfo *xine; - xine = screen_find_xinerama(sc, - cc->geom.x + cc->geom.width / 2, - cc->geom.y + cc->geom.height / 2); - if (xine == NULL) - goto calc; + xine = screen_find_xinerama(sc, + cc->geom.x + cc->geom.w / 2, + cc->geom.y + cc->geom.h / 2); + if (xine) { x_org = xine->x_org; xmax = xine->width; + } else { + x_org = 0; + xmax = sc->view.w; } -calc: + cc->geom.x = x_org + sc->gap.left; - cc->geom.width = xmax - (cc->bwidth * 2) - (sc->gap.left + + cc->geom.w = xmax - (cc->bwidth * 2) - (sc->gap.left + sc->gap.right); cc->flags |= CLIENT_HMAXIMIZED; @@ -431,7 +413,7 @@ client_resize(struct client_ctx *cc) client_draw_border(cc); XMoveResizeWindow(X_Dpy, cc->win, cc->geom.x, - cc->geom.y, cc->geom.width, cc->geom.height); + cc->geom.y, cc->geom.w, cc->geom.h); xu_configure(cc); } @@ -460,8 +442,8 @@ client_ptrwarp(struct client_ctx *cc) int x = cc->ptr.x, y = cc->ptr.y; if (x == -1 || y == -1) { - x = cc->geom.width / 2; - y = cc->geom.height / 2; + x = cc->geom.w / 2; + y = cc->geom.h / 2; } (cc->state == IconicState) ? client_unhide(cc) : client_raise(cc); @@ -540,14 +522,14 @@ client_update(struct client_ctx *cc) int i; long n; - if ((n = xu_getprop(cc->win, WM_PROTOCOLS, + if ((n = xu_getprop(cc->win, cwmh[WM_PROTOCOLS].atom, XA_ATOM, 20L, (u_char **)&p)) <= 0) return; for (i = 0; i < n; i++) - if (p[i] == WM_DELETE_WINDOW) + if (p[i] == cwmh[WM_DELETE_WINDOW].atom) cc->xproto |= CLIENT_PROTO_DELETE; - else if (p[i] == WM_TAKE_FOCUS) + else if (p[i] == cwmh[WM_TAKE_FOCUS].atom) cc->xproto |= CLIENT_PROTO_TAKEFOCUS; XFree(p); @@ -557,7 +539,8 @@ void client_send_delete(struct client_ctx *cc) { if (cc->xproto & CLIENT_PROTO_DELETE) - xu_sendmsg(cc->win, WM_PROTOCOLS, WM_DELETE_WINDOW); + xu_sendmsg(cc->win, + cwmh[WM_PROTOCOLS].atom, cwmh[WM_DELETE_WINDOW].atom); else XKillClient(X_Dpy, cc->win); } @@ -568,7 +551,7 @@ client_setname(struct client_ctx *cc) struct winname *wn; char *newname; - if (!xu_getstrprop(cc->win, _NET_WM_NAME, &newname)) + if (!xu_getstrprop(cc->win, ewmh[_NET_WM_NAME].atom, &newname)) if (!xu_getstrprop(cc->win, XA_WM_NAME, &newname)) newname = emptystring; @@ -690,8 +673,8 @@ client_placecalc(struct client_ctx *cc) * XRandR bits mean that {x,y}max shouldn't be outside what's * currently there. */ - xslack = sc->xmax - cc->geom.width - cc->bwidth * 2; - yslack = sc->ymax - cc->geom.height - cc->bwidth * 2; + xslack = sc->view.w - cc->geom.w - cc->bwidth * 2; + yslack = sc->view.h - cc->geom.h - cc->bwidth * 2; if (cc->size->x > 0) cc->geom.x = MIN(cc->size->x, xslack); if (cc->size->y > 0) @@ -702,28 +685,25 @@ client_placecalc(struct client_ctx *cc) int xmax, ymax; xu_ptr_getpos(sc->rootwin, &xmouse, &ymouse); - if (HasXinerama) { - info = screen_find_xinerama(sc, xmouse, ymouse); - if (info == NULL) - goto noxine; + info = screen_find_xinerama(sc, xmouse, ymouse); + if (info) { xorig = info->x_org; yorig = info->y_org; xmax = xorig + info->width; ymax = yorig + info->height; } else { -noxine: xorig = yorig = 0; - xmax = sc->xmax; - ymax = sc->ymax; + xmax = sc->view.w; + ymax = sc->view.h; } - xmouse = MAX(xmouse, xorig) - cc->geom.width / 2; - ymouse = MAX(ymouse, yorig) - cc->geom.height / 2; + xmouse = MAX(xmouse, xorig) - cc->geom.w / 2; + ymouse = MAX(ymouse, yorig) - cc->geom.h / 2; xmouse = MAX(xmouse, xorig); ymouse = MAX(ymouse, yorig); - xslack = xmax - cc->geom.width - cc->bwidth * 2; - yslack = ymax - cc->geom.height - cc->bwidth * 2; + xslack = xmax - cc->geom.w - cc->bwidth * 2; + yslack = ymax - cc->geom.h - cc->bwidth * 2; if (xslack >= xorig) { cc->geom.x = MAX(MIN(xmouse, xslack), @@ -732,7 +712,7 @@ noxine: cc->geom.x -= sc->gap.right; } else { cc->geom.x = xorig + sc->gap.left; - cc->geom.width = xmax - sc->gap.left; + cc->geom.w = xmax - sc->gap.left; } if (yslack >= yorig) { cc->geom.y = MAX(MIN(ymouse, yslack), @@ -741,7 +721,7 @@ noxine: cc->geom.y -= sc->gap.bottom; } else { cc->geom.y = yorig + sc->gap.top; - cc->geom.height = ymax - sc->gap.top; + cc->geom.h = ymax - sc->gap.top; } } } @@ -816,43 +796,43 @@ client_applysizehints(struct client_ctx *cc) /* temporarily remove base dimensions, ICCCM 4.1.2.3 */ if (!baseismin) { - cc->geom.width -= cc->hint.basew; - cc->geom.height -= cc->hint.baseh; + cc->geom.w -= cc->hint.basew; + cc->geom.h -= cc->hint.baseh; } /* adjust for aspect limits */ if (cc->hint.mina > 0 && cc->hint.maxa > 0) { if (cc->hint.maxa < - (float)cc->geom.width / cc->geom.height) - cc->geom.width = cc->geom.height * cc->hint.maxa; + (float)cc->geom.w / cc->geom.h) + cc->geom.w = cc->geom.h * cc->hint.maxa; else if (cc->hint.mina < - (float)cc->geom.height / cc->geom.width) - cc->geom.height = cc->geom.width * cc->hint.mina; + (float)cc->geom.h / cc->geom.w) + cc->geom.h = cc->geom.w * cc->hint.mina; } /* remove base dimensions for increment */ if (baseismin) { - cc->geom.width -= cc->hint.basew; - cc->geom.height -= cc->hint.baseh; + cc->geom.w -= cc->hint.basew; + cc->geom.h -= cc->hint.baseh; } /* adjust for increment value */ - cc->geom.width -= cc->geom.width % cc->hint.incw; - cc->geom.height -= cc->geom.height % cc->hint.inch; + cc->geom.w -= cc->geom.w % cc->hint.incw; + cc->geom.h -= cc->geom.h % cc->hint.inch; /* restore base dimensions */ - cc->geom.width += cc->hint.basew; - cc->geom.height += cc->hint.baseh; + cc->geom.w += cc->hint.basew; + cc->geom.h += cc->hint.baseh; /* adjust for min width/height */ - cc->geom.width = MAX(cc->geom.width, cc->hint.minw); - cc->geom.height = MAX(cc->geom.height, cc->hint.minh); + cc->geom.w = MAX(cc->geom.w, cc->hint.minw); + cc->geom.h = MAX(cc->geom.h, cc->hint.minh); /* adjust for max width/height */ if (cc->hint.maxw) - cc->geom.width = MIN(cc->geom.width, cc->hint.maxw); + cc->geom.w = MIN(cc->geom.w, cc->hint.maxw); if (cc->hint.maxh) - cc->geom.height = MIN(cc->geom.height, cc->hint.maxh); + cc->geom.h = MIN(cc->geom.h, cc->hint.maxh); } static void @@ -868,7 +848,7 @@ client_gethints(struct client_ctx *cc) cc->app_class = xch.res_class; } - if (xu_getprop(cc->win, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, + if (xu_getprop(cc->win, cwmh[_MOTIF_WM_HINTS].atom, _MOTIF_WM_HINTS, PROP_MWM_HINTS_ELEMENTS, (u_char **)&mwmh) == MWM_NUMHINTS) if (mwmh->flags & MWM_HINTS_DECORATIONS && !(mwmh->decorations & MWM_DECOR_ALL) && @@ -903,8 +883,8 @@ client_transient(struct client_ctx *cc) static int client_inbound(struct client_ctx *cc, int x, int y) { - return (x < cc->geom.width && x >= 0 && - y < cc->geom.height && y >= 0); + return (x < cc->geom.w && x >= 0 && + y < cc->geom.h && y >= 0); } int diff --git a/cwmrc.5 b/cwmrc.5 index 2bb1d53..e09e35b 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: September 8 2011 $ +.Dd $Mdocdate: November 6 2011 $ .Dt CWMRC 5 .Os .Sh NAME @@ -244,6 +244,10 @@ ignore xclock bind CM-r label bind CS-Return "xterm -e top" bind 4-o unmap +bind CM-equal unmap +bind CMS-equal unmap +bind C4-equal vmaximize +bind C4S-equal hmaximize bind M-1 grouponly1 bind M-2 grouponly2 bind M-3 grouponly3 diff --git a/group.c b/group.c index 85a0e67..f28640c 100644 --- a/group.c +++ b/group.c @@ -48,38 +48,31 @@ const char *shortcut_to_name[] = { static void group_add(struct group_ctx *gc, struct client_ctx *cc) { - long no; if (cc == NULL || gc == NULL) errx(1, "group_add: a ctx is NULL"); - no = gc->shortcut - 1; - if (cc->group == gc) return; if (cc->group != NULL) TAILQ_REMOVE(&cc->group->clients, cc, group_entry); - XChangeProperty(X_Dpy, cc->win, _NET_WM_DESKTOP, XA_CARDINAL, - 32, PropModeReplace, (unsigned char *)&no, 1); - TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry); cc->group = gc; + + xu_ewmh_net_wm_desktop(cc); } static void group_remove(struct client_ctx *cc) { - long no = 0xffffffff; - if (cc == NULL || cc->group == NULL) errx(1, "group_remove: a ctx is NULL"); - XChangeProperty(X_Dpy, cc->win, _NET_WM_DESKTOP, XA_CARDINAL, - 32, PropModeReplace, (unsigned char *)&no, 1); - TAILQ_REMOVE(&cc->group->clients, cc, group_entry); cc->group = NULL; + + xu_ewmh_net_wm_desktop(cc); } static void @@ -146,8 +139,6 @@ void group_init(struct screen_ctx *sc) { int i; - long viewports[2] = {0, 0}; - long ndesks = CALMWM_NGROUPS, zero = 0; TAILQ_INIT(&sc->groupq); sc->group_hideall = 0; @@ -164,23 +155,11 @@ group_init(struct screen_ctx *sc) TAILQ_INSERT_TAIL(&sc->groupq, &sc->groups[i], entry); } - /* we don't support large desktops, so this is always (0, 0) */ - XChangeProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_VIEWPORT, - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)viewports, 2); - XChangeProperty(X_Dpy, sc->rootwin, _NET_NUMBER_OF_DESKTOPS, - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&ndesks, 1); - /* - * we don't use virtual roots, so make sure it's not there from a - * previous wm. - */ - XDeleteProperty(X_Dpy, sc->rootwin, _NET_VIRTUAL_ROOTS); - /* - * We don't really have a ``showing desktop'' mode, so this is zero - * always. XXX Note that when we hide all groups, or when all groups - * are hidden we could technically set this later on. - */ - XChangeProperty(X_Dpy, sc->rootwin, _NET_SHOWING_DESKTOP, - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&zero, 1); + xu_ewmh_net_wm_desktop_viewport(sc); + xu_ewmh_net_wm_number_of_desktops(sc); + xu_ewmh_net_showing_desktop(sc); + xu_ewmh_net_virtual_roots(sc); + group_setactive(sc, 0); } @@ -209,8 +188,8 @@ static void group_setactive(struct screen_ctx *sc, long idx) { sc->group_active = &sc->groups[idx]; - XChangeProperty(X_Dpy, sc->rootwin, _NET_CURRENT_DESKTOP, - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&idx, 1); + + xu_ewmh_net_current_desktop(sc, idx); } void @@ -439,8 +418,8 @@ group_autogroup(struct client_ctx *cc) if (cc->app_class == NULL || cc->app_name == NULL) return; - if (xu_getprop(cc->win, _NET_WM_DESKTOP, XA_CARDINAL, - 1, (unsigned char **)&grpno) > 0) { + if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP].atom, + XA_CARDINAL, 1, (unsigned char **)&grpno) > 0) { if (*grpno == 0xffffffff) no = 0; else if (*grpno > CALMWM_NGROUPS || *grpno < 0) @@ -480,11 +459,12 @@ group_update_names(struct screen_ctx *sc) char **strings, *p; unsigned char *prop_ret; Atom type_ret; - int format_ret, i = 0, nstrings = 0, n, setnames = 0; + int format_ret, i = 0, nstrings = 0, n = 0, setnames = 0; unsigned long bytes_after, num_ret; - if (XGetWindowProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_NAMES, 0, - 0xffffff, False, UTF8_STRING, &type_ret, &format_ret, + if (XGetWindowProperty(X_Dpy, sc->rootwin, + ewmh[_NET_DESKTOP_NAMES].atom, 0, 0xffffff, False, + cwmh[UTF8_STRING].atom, &type_ret, &format_ret, &num_ret, &bytes_after, &prop_ret) == Success && prop_ret != NULL && format_ret == 8) { /* failure, just set defaults */ @@ -498,7 +478,6 @@ group_update_names(struct screen_ctx *sc) strings = xmalloc((nstrings < CALMWM_NGROUPS ? CALMWM_NGROUPS : nstrings) * sizeof(*strings)); - i = n = 0; p = prop_ret; while (n < nstrings) { strings[n++] = xstrdup(p); @@ -545,6 +524,5 @@ group_set_names(struct screen_ctx *sc) q += slen; } - XChangeProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_NAMES, - UTF8_STRING, 8, PropModeReplace, p, len); + xu_ewmh_net_desktop_names(sc, p, len); } diff --git a/kbfunc.c b/kbfunc.c index 106bf95..f76bd92 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -55,14 +55,13 @@ kbfunc_client_raise(struct client_ctx *cc, union arg *arg) void kbfunc_moveresize(struct client_ctx *cc, union arg *arg) { - struct screen_ctx *sc; + struct screen_ctx *sc = cc->sc; int x, y, flags, amt; u_int mx, my; if (cc->flags & CLIENT_FREEZE) return; - sc = cc->sc; mx = my = 0; flags = arg->i; @@ -90,22 +89,22 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg) switch (flags & TYPEMASK) { case CWM_MOVE: cc->geom.y += my; - if (cc->geom.y + cc->geom.height < 0) - cc->geom.y = -cc->geom.height; - if (cc->geom.y > cc->sc->ymax - 1) - cc->geom.y = cc->sc->ymax - 1; + if (cc->geom.y + cc->geom.h < 0) + cc->geom.y = -cc->geom.h; + if (cc->geom.y > sc->view.h - 1) + cc->geom.y = sc->view.h - 1; cc->geom.x += mx; - if (cc->geom.x + cc->geom.width < 0) - cc->geom.x = -cc->geom.width; - if (cc->geom.x > cc->sc->xmax - 1) - cc->geom.x = cc->sc->xmax - 1; + if (cc->geom.x + cc->geom.w < 0) + cc->geom.x = -cc->geom.w; + if (cc->geom.x > sc->view.w - 1) + cc->geom.x = sc->view.w - 1; cc->geom.x += client_snapcalc(cc->geom.x, - cc->geom.width, cc->sc->xmax, + cc->geom.w, sc->view.w, cc->bwidth, Conf.snapdist); cc->geom.y += client_snapcalc(cc->geom.y, - cc->geom.height, cc->sc->ymax, + cc->geom.h, sc->view.h, cc->bwidth, Conf.snapdist); client_move(cc); @@ -115,18 +114,18 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg) client_ptrwarp(cc); break; case CWM_RESIZE: - if ((cc->geom.height += my) < 1) - cc->geom.height = 1; - if ((cc->geom.width += mx) < 1) - cc->geom.width = 1; + if ((cc->geom.h += my) < 1) + cc->geom.h = 1; + if ((cc->geom.w += mx) < 1) + cc->geom.w = 1; client_resize(cc); /* Make sure the pointer stays within the window. */ xu_ptr_getpos(cc->win, &cc->ptr.x, &cc->ptr.y); - if (cc->ptr.x > cc->geom.width) - cc->ptr.x = cc->geom.width - cc->bwidth; - if (cc->ptr.y > cc->geom.height) - cc->ptr.y = cc->geom.height - cc->bwidth; + if (cc->ptr.x > cc->geom.w) + cc->ptr.x = cc->geom.w - cc->bwidth; + if (cc->ptr.y > cc->geom.h) + cc->ptr.y = cc->geom.h - cc->bwidth; client_ptrwarp(cc); break; case CWM_PTRMOVE: @@ -141,12 +140,11 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg) void kbfunc_client_search(struct client_ctx *cc, union arg *arg) { - struct screen_ctx *sc; + struct screen_ctx *sc = cc->sc; struct client_ctx *old_cc; struct menu *mi; struct menu_q menuq; - sc = cc->sc; old_cc = client_current(); TAILQ_INIT(&menuq); @@ -178,12 +176,11 @@ kbfunc_client_search(struct client_ctx *cc, union arg *arg) void kbfunc_menu_search(struct client_ctx *cc, union arg *arg) { - struct screen_ctx *sc; + struct screen_ctx *sc = cc->sc; struct cmd *cmd; struct menu *mi; struct menu_q menuq; - sc = cc->sc; TAILQ_INIT(&menuq); TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { @@ -206,9 +203,7 @@ kbfunc_menu_search(struct client_ctx *cc, union arg *arg) void kbfunc_client_cycle(struct client_ctx *cc, union arg *arg) { - struct screen_ctx *sc; - - sc = cc->sc; + struct screen_ctx *sc = cc->sc; /* XXX for X apps that ignore events */ XGrabKeyboard(X_Dpy, sc->rootwin, True, @@ -245,7 +240,7 @@ void kbfunc_exec(struct client_ctx *cc, union arg *arg) { #define NPATHS 256 - struct screen_ctx *sc; + struct screen_ctx *sc = cc->sc; char **ap, *paths[NPATHS], *path, *pathcpy, *label; char tpath[MAXPATHLEN]; DIR *dirp; @@ -254,7 +249,6 @@ kbfunc_exec(struct client_ctx *cc, union arg *arg) struct menu_q menuq; int l, i, cmd = arg->i; - sc = cc->sc; switch (cmd) { case CWM_EXEC_PROGRAM: label = "exec"; @@ -333,7 +327,7 @@ out: void kbfunc_ssh(struct client_ctx *cc, union arg *arg) { - struct screen_ctx *sc; + struct screen_ctx *sc = cc->sc; struct menu *mi; struct menu_q menuq; FILE *fp; @@ -343,8 +337,6 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg) int l; size_t len; - sc = cc->sc; - if ((home = getenv("HOME")) == NULL) return; diff --git a/menu.c b/menu.c index 17c665a..58ed618 100644 --- a/menu.c +++ b/menu.c @@ -349,8 +349,8 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq, ymax = xine->y_org + xine->height; } else { xmin = ymin = 0; - xmax = sc->xmax; - ymax = sc->ymax; + xmax = sc->view.w; + ymax = sc->view.h; } xsave = mc->x; diff --git a/mousefunc.c b/mousefunc.c index c165977..b0bd40f 100644 --- a/mousefunc.c +++ b/mousefunc.c @@ -37,17 +37,17 @@ static void mousefunc_sweep_draw(struct client_ctx *); static int mousefunc_sweep_calc(struct client_ctx *cc, int x, int y, int mx, int my) { - int width = cc->geom.width, height = cc->geom.height; + int width = cc->geom.w, height = cc->geom.h; - cc->geom.width = abs(x - mx) - cc->bwidth; - cc->geom.height = abs(y - my) - cc->bwidth; + cc->geom.w = abs(x - mx) - cc->bwidth; + cc->geom.h = abs(y - my) - cc->bwidth; client_applysizehints(cc); - cc->geom.x = x <= mx ? x : x - cc->geom.width; - cc->geom.y = y <= my ? y : y - cc->geom.height; + cc->geom.x = x <= mx ? x : x - cc->geom.w; + cc->geom.y = y <= my ? y : y - cc->geom.h; - return (width != cc->geom.width || height != cc->geom.height); + return (width != cc->geom.w || height != cc->geom.h); } static void @@ -58,8 +58,8 @@ mousefunc_sweep_draw(struct client_ctx *cc) int width, width_size, width_name; (void)snprintf(asize, sizeof(asize), "%dx%d", - (cc->geom.width - cc->hint.basew) / cc->hint.incw, - (cc->geom.height - cc->hint.baseh) / cc->hint.inch); + (cc->geom.w - cc->hint.basew) / cc->hint.incw, + (cc->geom.h - cc->hint.baseh) / cc->hint.inch); width_size = font_width(sc, asize, strlen(asize)) + 4; width_name = font_width(sc, cc->name, strlen(cc->name)) + 4; width = MAX(width_size, width_name); @@ -91,7 +91,7 @@ mousefunc_window_resize(struct client_ctx *cc, void *arg) if (xu_ptr_grab(cc->win, MOUSEMASK, Cursor_resize) < 0) return; - xu_ptr_setpos(cc->win, cc->geom.width, cc->geom.height); + xu_ptr_setpos(cc->win, cc->geom.w, cc->geom.h); mousefunc_sweep_draw(cc); for (;;) { @@ -121,10 +121,10 @@ mousefunc_window_resize(struct client_ctx *cc, void *arg) xu_ptr_ungrab(); /* Make sure the pointer stays within the window. */ - if (cc->ptr.x > cc->geom.width) - cc->ptr.x = cc->geom.width - cc->bwidth; - if (cc->ptr.y > cc->geom.height) - cc->ptr.y = cc->geom.height - cc->bwidth; + if (cc->ptr.x > cc->geom.w) + cc->ptr.x = cc->geom.w - cc->bwidth; + if (cc->ptr.y > cc->geom.h) + cc->ptr.y = cc->geom.h - cc->bwidth; client_ptrwarp(cc); return; } @@ -137,6 +137,7 @@ mousefunc_window_move(struct client_ctx *cc, void *arg) { XEvent ev; Time ltime = 0; + struct screen_ctx *sc = cc->sc; int px, py; client_raise(cc); @@ -161,10 +162,10 @@ mousefunc_window_move(struct client_ctx *cc, void *arg) cc->geom.y = ev.xmotion.y_root - py - cc->bwidth; cc->geom.x += client_snapcalc(cc->geom.x, - cc->geom.width, cc->sc->xmax, + cc->geom.w, sc->view.w, cc->bwidth, Conf.snapdist); cc->geom.y += client_snapcalc(cc->geom.y, - cc->geom.height, cc->sc->ymax, + cc->geom.h, sc->view.h, cc->bwidth, Conf.snapdist); /* don't move more than 60 times / second */ @@ -217,13 +218,12 @@ mousefunc_menu_group(struct client_ctx *cc, void *arg) void mousefunc_menu_unhide(struct client_ctx *cc, void *arg) { - struct screen_ctx *sc; + struct screen_ctx *sc = cc->sc; struct client_ctx *old_cc; struct menu *mi; struct menu_q menuq; char *wname; - sc = cc->sc; old_cc = client_current(); TAILQ_INIT(&menuq); @@ -261,13 +261,11 @@ mousefunc_menu_unhide(struct client_ctx *cc, void *arg) void mousefunc_menu_cmd(struct client_ctx *cc, void *arg) { - struct screen_ctx *sc; + struct screen_ctx *sc = cc->sc; struct menu *mi; struct menu_q menuq; struct cmd *cmd; - sc = cc->sc; - TAILQ_INIT(&menuq); TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { mi = xcalloc(1, sizeof(*mi)); diff --git a/screen.c b/screen.c index ecd8104..69a638a 100644 --- a/screen.c +++ b/screen.c @@ -30,6 +30,8 @@ #include "calmwm.h" +static void screen_init_xinerama(struct screen_ctx *); + struct screen_ctx * screen_fromroot(Window rootwin) { @@ -65,24 +67,18 @@ screen_updatestackingorder(struct screen_ctx *sc) XFree(wins); } +/* + * If we're using RandR then we'll redo this whenever the screen + * changes since a CTRC may have been added or removed + */ void screen_init_xinerama(struct screen_ctx *sc) { - XineramaScreenInfo *info; - int no; - - if (HasXinerama == 0 || XineramaIsActive(X_Dpy) == 0) { - HasXinerama = 0; - sc->xinerama_no = 0; - } + XineramaScreenInfo *info = NULL; + int no = 0; - info = XineramaQueryScreens(X_Dpy, &no); - if (info == NULL) { - /* Is xinerama actually off, instead of a malloc failure? */ - if (sc->xinerama == NULL) - HasXinerama = 0; - return; - } + if (XineramaIsActive(X_Dpy)) + info = XineramaQueryScreens(X_Dpy, &no); if (sc->xinerama != NULL) XFree(sc->xinerama); @@ -99,6 +95,9 @@ screen_find_xinerama(struct screen_ctx *sc, int x, int y) XineramaScreenInfo *info; int i; + if (sc->xinerama == NULL) + return (NULL); + for (i = 0; i < sc->xinerama_no; i++) { info = &sc->xinerama[i]; if (x >= info->x_org && x < info->x_org + info->width && @@ -109,25 +108,20 @@ screen_find_xinerama(struct screen_ctx *sc, int x, int y) } void -screen_update_geometry(struct screen_ctx *sc, int width, int height) +screen_update_geometry(struct screen_ctx *sc) { - long geom[2], workareas[CALMWM_NGROUPS][4]; - int i; - - sc->xmax = geom[0] = width; - sc->ymax = geom[1] = height; - XChangeProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_GEOMETRY, - XA_CARDINAL, 32, PropModeReplace, (unsigned char *)geom , 2); - - /* x, y, width, height. */ - for (i = 0; i < CALMWM_NGROUPS; i++) { - workareas[i][0] = sc->gap.left; - workareas[i][1] = sc->gap.top; - workareas[i][2] = width - (sc->gap.left + sc->gap.right); - workareas[i][3] = height - (sc->gap.top + sc->gap.bottom); - } + sc->view.x = 0; + sc->view.y = 0; + sc->view.w = DisplayWidth(X_Dpy, sc->which); + sc->view.h = DisplayHeight(X_Dpy, sc->which); + + sc->work.x = sc->view.x + sc->gap.left; + sc->work.y = sc->view.y + sc->gap.top; + sc->work.w = sc->view.w - (sc->gap.left + sc->gap.right); + sc->work.h = sc->view.h - (sc->gap.top + sc->gap.bottom); + + screen_init_xinerama(sc); - XChangeProperty(X_Dpy, sc->rootwin, _NET_WORKAREA, - XA_CARDINAL, 32, PropModeReplace, - (unsigned char *)workareas, CALMWM_NGROUPS * 4); + xu_ewmh_net_desktop_geometry(sc); + xu_ewmh_net_workarea(sc); } diff --git a/xevents.c b/xevents.c index 9cd03f9..0d91067 100644 --- a/xevents.c +++ b/xevents.c @@ -142,9 +142,9 @@ xev_handle_configurerequest(XEvent *ee) sc = cc->sc; if (e->value_mask & CWWidth) - cc->geom.width = e->width; + cc->geom.w = e->width; if (e->value_mask & CWHeight) - cc->geom.height = e->height; + cc->geom.h = e->height; if (e->value_mask & CWX) cc->geom.x = e->x; if (e->value_mask & CWY) @@ -152,16 +152,16 @@ xev_handle_configurerequest(XEvent *ee) if (e->value_mask & CWBorderWidth) wc.border_width = e->border_width; - if (cc->geom.x == 0 && cc->geom.width >= sc->xmax) + if (cc->geom.x == 0 && cc->geom.w >= sc->view.w) cc->geom.x -= cc->bwidth; - if (cc->geom.y == 0 && cc->geom.height >= sc->ymax) + if (cc->geom.y == 0 && cc->geom.h >= sc->view.h) cc->geom.y -= cc->bwidth; wc.x = cc->geom.x; wc.y = cc->geom.y; - wc.width = cc->geom.width; - wc.height = cc->geom.height; + wc.width = cc->geom.w; + wc.height = cc->geom.h; wc.border_width = cc->bwidth; XConfigureWindow(X_Dpy, cc->win, e->value_mask, &wc); @@ -208,7 +208,7 @@ xev_handle_propertynotify(XEvent *ee) goto test; return; test: - if (e->atom == _NET_DESKTOP_NAMES) + if (e->atom == ewmh[_NET_DESKTOP_NAMES].atom) group_update_names(sc); } } @@ -366,8 +366,7 @@ xev_handle_randr(XEvent *ee) TAILQ_FOREACH(sc, &Screenq, entry) { if (sc->which == (u_int)i) { XRRUpdateConfiguration(ee); - screen_update_geometry(sc, rev->width, rev->height); - screen_init_xinerama(sc); + screen_update_geometry(sc); } } } diff --git a/xutil.c b/xutil.c index 030584b..d3f7978 100644 --- a/xutil.c +++ b/xutil.c @@ -128,8 +128,8 @@ xu_configure(struct client_ctx *cc) ce.window = cc->win; ce.x = cc->geom.x; ce.y = cc->geom.y; - ce.width = cc->geom.width; - ce.height = cc->geom.height; + ce.width = cc->geom.w; + ce.height = cc->geom.h; ce.border_width = cc->bwidth; ce.above = None; ce.override_redirect = 0; @@ -207,7 +207,8 @@ xu_getstate(struct client_ctx *cc, int *state) { long *p = NULL; - if (xu_getprop(cc->win, WM_STATE, WM_STATE, 2L, (u_char **)&p) <= 0) + if (xu_getprop(cc->win, cwmh[WM_STATE].atom, cwmh[WM_STATE].atom, 2L, + (u_char **)&p) <= 0) return (-1); *state = (int)*p; @@ -225,67 +226,194 @@ xu_setstate(struct client_ctx *cc, int state) dat[1] = None; cc->state = state; - XChangeProperty(X_Dpy, cc->win, WM_STATE, WM_STATE, 32, + XChangeProperty(X_Dpy, cc->win, + cwmh[WM_STATE].atom, cwmh[WM_STATE].atom, 32, PropModeReplace, (unsigned char *)dat, 2); } -Atom cwm_atoms[CWM_NO_ATOMS]; -char *atoms[CWM_NO_ATOMS] = { - "WM_STATE", - "WM_DELETE_WINDOW", - "WM_TAKE_FOCUS", - "WM_PROTOCOLS", - "_MOTIF_WM_HINTS", - "UTF8_STRING", - "_NET_SUPPORTED", - "_NET_SUPPORTING_WM_CHECK", - "_NET_WM_NAME", - "_NET_ACTIVE_WINDOW", - "_NET_CLIENT_LIST", - "_NET_NUMBER_OF_DESKTOPS", - "_NET_CURRENT_DESKTOP", - "_NET_DESKTOP_VIEWPORT", - "_NET_DESKTOP_GEOMETRY", - "_NET_VIRTUAL_ROOTS", - "_NET_SHOWING_DESKTOP", - "_NET_DESKTOP_NAMES", - "_NET_WM_DESKTOP", - "_NET_WORKAREA", +struct atom_ctx cwmh[CWMH_NITEMS] = { + {"WM_STATE", None}, + {"WM_DELETE_WINDOW", None}, + {"WM_TAKE_FOCUS", None}, + {"WM_PROTOCOLS", None}, + {"_MOTIF_WM_HINTS", None}, + {"UTF8_STRING", None}, +}; +struct atom_ctx ewmh[EWMH_NITEMS] = { + {"_NET_SUPPORTED", None}, + {"_NET_SUPPORTING_WM_CHECK", None}, + {"_NET_ACTIVE_WINDOW", None}, + {"_NET_CLIENT_LIST", None}, + {"_NET_NUMBER_OF_DESKTOPS", None}, + {"_NET_CURRENT_DESKTOP", None}, + {"_NET_DESKTOP_VIEWPORT", None}, + {"_NET_DESKTOP_GEOMETRY", None}, + {"_NET_VIRTUAL_ROOTS", None}, + {"_NET_SHOWING_DESKTOP", None}, + {"_NET_DESKTOP_NAMES", None}, + {"_NET_WORKAREA", None}, + {"_NET_WM_NAME", None}, + {"_NET_WM_DESKTOP", None}, }; void xu_getatoms(void) { - XInternAtoms(X_Dpy, atoms, CWM_NO_ATOMS, False, cwm_atoms); + int i; + + for (i = 0; i < nitems(cwmh); i++) + cwmh[i].atom = XInternAtom(X_Dpy, cwmh[i].name, False); + for (i = 0; i < nitems(ewmh); i++) + ewmh[i].atom = XInternAtom(X_Dpy, ewmh[i].name, False); } +/* Root Window Properties */ void xu_ewmh_net_supported(struct screen_ctx *sc) { - XChangeProperty(X_Dpy, sc->rootwin, _NET_SUPPORTED, XA_ATOM, 32, - PropModeReplace, (unsigned char *)&_NET_SUPPORTED, - CWM_NO_ATOMS - CWM_NETWM_START); + Atom atom[EWMH_NITEMS]; + int i; + + for (i = 0; i < nitems(ewmh); i++) + atom[i] = ewmh[i].atom; + + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_SUPPORTED].atom, + XA_ATOM, 32, PropModeReplace, (unsigned char *)atom, EWMH_NITEMS); } -/* - * The netwm spec says that to prove that the hint is not stale, one - * must provide _NET_SUPPORTING_WM_CHECK containing a window created by - * the root window. The property must be set on the root window and the - * window itself. This child window also must have _NET_WM_NAME set with - * the window manager name. - */ void xu_ewmh_net_supported_wm_check(struct screen_ctx *sc) { Window w; w = XCreateSimpleWindow(X_Dpy, sc->rootwin, -1, -1, 1, 1, 0, 0, 0); - XChangeProperty(X_Dpy, sc->rootwin, _NET_SUPPORTING_WM_CHECK, + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_SUPPORTING_WM_CHECK].atom, XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1); - XChangeProperty(X_Dpy, w, _NET_SUPPORTING_WM_CHECK, + XChangeProperty(X_Dpy, w, ewmh[_NET_SUPPORTING_WM_CHECK].atom, XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1); - XChangeProperty(X_Dpy, w, _NET_WM_NAME, UTF8_STRING, - 8, PropModeReplace, WMNAME, strlen(WMNAME)); + XChangeProperty(X_Dpy, w, ewmh[_NET_WM_NAME].atom, + XA_WM_NAME, 8, PropModeReplace, WMNAME, strlen(WMNAME)); +} + +void +xu_ewmh_net_desktop_geometry(struct screen_ctx *sc) +{ + long geom[2] = { sc->view.w, sc->view.h }; + + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_GEOMETRY].atom, + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)geom , 2); +} + +void +xu_ewmh_net_workarea(struct screen_ctx *sc) +{ + long workareas[CALMWM_NGROUPS][4]; + int i; + + for (i = 0; i < CALMWM_NGROUPS; i++) { + workareas[i][0] = sc->work.x; + workareas[i][1] = sc->work.y; + workareas[i][2] = sc->work.w; + workareas[i][3] = sc->work.h; + } + + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_WORKAREA].atom, + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)workareas, + CALMWM_NGROUPS * 4); +} + +void +xu_ewmh_net_client_list(struct screen_ctx *sc) +{ + struct client_ctx *cc; + Window *winlist; + int i = 0, j = 0; + + TAILQ_FOREACH(cc, &Clientq, entry) + i++; + if (i == 0) + return; + + winlist = xmalloc(i * sizeof(*winlist)); + TAILQ_FOREACH(cc, &Clientq, entry) + winlist[j++] = cc->win; + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_CLIENT_LIST].atom, + XA_WINDOW, 32, PropModeReplace, (unsigned char *)winlist, i); + xfree(winlist); +} + +void +xu_ewmh_net_active_window(struct screen_ctx *sc, Window w) +{ + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_ACTIVE_WINDOW].atom, + XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1); +} + +void +xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *sc) +{ + long viewports[2] = {0, 0}; + + /* We don't support large desktops, so this is (0, 0). */ + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_VIEWPORT].atom, + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)viewports, 2); +} + +void +xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *sc) +{ + long ndesks = CALMWM_NGROUPS; + + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_NUMBER_OF_DESKTOPS].atom, + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&ndesks, 1); +} + +void +xu_ewmh_net_showing_desktop(struct screen_ctx *sc) +{ + long zero = 0; + + /* We don't support `showing desktop' mode, so this is zero. + * Note that when we hide all groups, or when all groups are + * hidden we could technically set this later on. + */ + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_SHOWING_DESKTOP].atom, + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&zero, 1); +} + +void +xu_ewmh_net_virtual_roots(struct screen_ctx *sc) +{ + /* We don't support virtual roots, so delete if set by previous wm. */ + XDeleteProperty(X_Dpy, sc->rootwin, ewmh[_NET_VIRTUAL_ROOTS].atom); +} + +void +xu_ewmh_net_current_desktop(struct screen_ctx *sc, long idx) +{ + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_CURRENT_DESKTOP].atom, + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&idx, 1); +} + +void +xu_ewmh_net_desktop_names(struct screen_ctx *sc, unsigned char *data, int n) +{ + XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_NAMES].atom, + cwmh[UTF8_STRING].atom, 8, PropModeReplace, data, n); +} + +/* Application Window Properties */ +void +xu_ewmh_net_wm_desktop(struct client_ctx *cc) +{ + struct group_ctx *gc = cc->group; + long no = 0xffffffff; + + if (gc) + no = gc->shortcut - 1; + + XChangeProperty(X_Dpy, cc->win, ewmh[_NET_WM_DESKTOP].atom, + XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&no, 1); } unsigned long |