re-implement atom handing; makes for a normalized and more consistent

separation between cwm and ewmh.  seen by a few.
This commit is contained in:
okan 2012-07-03 13:49:03 +00:00
parent 4e7daddec8
commit d24974f4cb
6 changed files with 253 additions and 164 deletions

View File

@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* *
* $OpenBSD: calmwm.h,v 1.146 2012/05/16 01:17:14 okan Exp $ * $OpenBSD: calmwm.h,v 1.147 2012/07/03 13:49:03 okan Exp $
*/ */
#ifndef _CALMWM_H_ #ifndef _CALMWM_H_
@ -466,6 +466,19 @@ void xu_setstate(struct client_ctx *, int);
void xu_ewmh_net_supported(struct screen_ctx *); void xu_ewmh_net_supported(struct screen_ctx *);
void xu_ewmh_net_supported_wm_check(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_exec(char *);
void u_spawn(char *); void u_spawn(char *);
@ -490,34 +503,37 @@ extern struct conf Conf;
extern int HasXinerama, HasRandr, Randr_ev; extern int HasXinerama, HasRandr, Randr_ev;
#define WM_STATE cwm_atoms[0] enum {
#define WM_DELETE_WINDOW cwm_atoms[1] WM_STATE,
#define WM_TAKE_FOCUS cwm_atoms[2] WM_DELETE_WINDOW,
#define WM_PROTOCOLS cwm_atoms[3] WM_TAKE_FOCUS,
#define _MOTIF_WM_HINTS cwm_atoms[4] WM_PROTOCOLS,
#define UTF8_STRING cwm_atoms[5] _MOTIF_WM_HINTS,
/* UTF8_STRING,
* please make all hints below this point netwm hints, starting with CWMH_NITEMS
* _NET_SUPPORTED. If you change other hints make sure you update };
* CWM_NETWM_START enum {
*/ _NET_SUPPORTED,
#define _NET_SUPPORTED cwm_atoms[6] _NET_SUPPORTING_WM_CHECK,
#define _NET_SUPPORTING_WM_CHECK cwm_atoms[7] _NET_ACTIVE_WINDOW,
#define _NET_WM_NAME cwm_atoms[8] _NET_CLIENT_LIST,
#define _NET_ACTIVE_WINDOW cwm_atoms[9] _NET_NUMBER_OF_DESKTOPS,
#define _NET_CLIENT_LIST cwm_atoms[10] _NET_CURRENT_DESKTOP,
#define _NET_NUMBER_OF_DESKTOPS cwm_atoms[11] _NET_DESKTOP_VIEWPORT,
#define _NET_CURRENT_DESKTOP cwm_atoms[12] _NET_DESKTOP_GEOMETRY,
#define _NET_DESKTOP_VIEWPORT cwm_atoms[13] _NET_VIRTUAL_ROOTS,
#define _NET_DESKTOP_GEOMETRY cwm_atoms[14] _NET_SHOWING_DESKTOP,
#define _NET_VIRTUAL_ROOTS cwm_atoms[15] _NET_DESKTOP_NAMES,
#define _NET_SHOWING_DESKTOP cwm_atoms[16] _NET_WORKAREA,
#define _NET_DESKTOP_NAMES cwm_atoms[17] _NET_WM_NAME,
#define _NET_WM_DESKTOP cwm_atoms[18] _NET_WM_DESKTOP,
#define _NET_WORKAREA cwm_atoms[19] EWMH_NITEMS
#define CWM_NO_ATOMS 20 };
#define CWM_NETWM_START 6 struct atom_ctx {
char *name;
extern Atom cwm_atoms[CWM_NO_ATOMS]; Atom atom;
};
extern struct atom_ctx cwmh[CWMH_NITEMS];
extern struct atom_ctx ewmh[EWMH_NITEMS];
#endif /* _CALMWM_H_ */ #endif /* _CALMWM_H_ */

View File

@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* *
* $OpenBSD: client.c,v 1.94 2012/05/16 01:09:17 okan Exp $ * $OpenBSD: client.c,v 1.95 2012/07/03 13:49:03 okan Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -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(&sc->mruq, cc, mru_entry);
TAILQ_INSERT_TAIL(&Clientq, cc, entry); TAILQ_INSERT_TAIL(&Clientq, cc, entry);
/* append to the client list */
XChangeProperty(X_Dpy, sc->rootwin, _NET_CLIENT_LIST, XA_WINDOW, 32, xu_ewmh_net_client_list(sc);
PropModeAppend, (unsigned char *)&cc->win, 1);
client_gethints(cc); client_gethints(cc);
client_update(cc); client_update(cc);
@ -143,10 +142,7 @@ void
client_delete(struct client_ctx *cc) client_delete(struct client_ctx *cc)
{ {
struct screen_ctx *sc = cc->sc; struct screen_ctx *sc = cc->sc;
struct client_ctx *tcc;
struct winname *wn; struct winname *wn;
Window *winlist;
int i, j;
group_client_delete(cc); group_client_delete(cc);
@ -159,23 +155,8 @@ client_delete(struct client_ctx *cc)
TAILQ_REMOVE(&sc->mruq, cc, mru_entry); TAILQ_REMOVE(&sc->mruq, cc, mru_entry);
TAILQ_REMOVE(&Clientq, cc, entry); TAILQ_REMOVE(&Clientq, cc, entry);
/*
* Sadly we can't remove just one entry from a property, so we must xu_ewmh_net_client_list(sc);
* 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);
}
if (_curcc == cc) if (_curcc == cc)
client_none(sc); client_none(sc);
@ -236,9 +217,7 @@ client_setactive(struct client_ctx *cc, int fg)
if (fg && _curcc != cc) { if (fg && _curcc != cc) {
client_setactive(NULL, 0); client_setactive(NULL, 0);
_curcc = cc; _curcc = cc;
XChangeProperty(X_Dpy, sc->rootwin, _NET_ACTIVE_WINDOW, xu_ewmh_net_active_window(sc, cc->win);
XA_WINDOW, 32, PropModeReplace,
(unsigned char *)&cc->win, 1);
} }
cc->active = fg; cc->active = fg;
@ -253,8 +232,8 @@ client_none(struct screen_ctx *sc)
{ {
Window none = None; Window none = None;
XChangeProperty(X_Dpy, sc->rootwin, _NET_ACTIVE_WINDOW, xu_ewmh_net_active_window(sc, none);
XA_WINDOW, 32, PropModeReplace, (unsigned char *)&none, 1);
_curcc = NULL; _curcc = NULL;
} }
@ -545,9 +524,9 @@ client_update(struct client_ctx *cc)
return; return;
for (i = 0; i < n; i++) 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; 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; cc->xproto |= CLIENT_PROTO_TAKEFOCUS;
XFree(p); XFree(p);
@ -557,7 +536,8 @@ void
client_send_delete(struct client_ctx *cc) client_send_delete(struct client_ctx *cc)
{ {
if (cc->xproto & CLIENT_PROTO_DELETE) 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 else
XKillClient(X_Dpy, cc->win); XKillClient(X_Dpy, cc->win);
} }
@ -568,7 +548,7 @@ client_setname(struct client_ctx *cc)
struct winname *wn; struct winname *wn;
char *newname; 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)) if (!xu_getstrprop(cc->win, XA_WM_NAME, &newname))
newname = emptystring; newname = emptystring;
@ -868,7 +848,7 @@ client_gethints(struct client_ctx *cc)
cc->app_class = xch.res_class; 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) PROP_MWM_HINTS_ELEMENTS, (u_char **)&mwmh) == MWM_NUMHINTS)
if (mwmh->flags & MWM_HINTS_DECORATIONS && if (mwmh->flags & MWM_HINTS_DECORATIONS &&
!(mwmh->decorations & MWM_DECOR_ALL) && !(mwmh->decorations & MWM_DECOR_ALL) &&

View File

@ -16,7 +16,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* *
* $OpenBSD: group.c,v 1.57 2012/05/16 21:57:21 okan Exp $ * $OpenBSD: group.c,v 1.58 2012/07/03 13:49:03 okan Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -48,38 +48,31 @@ const char *shortcut_to_name[] = {
static void static void
group_add(struct group_ctx *gc, struct client_ctx *cc) group_add(struct group_ctx *gc, struct client_ctx *cc)
{ {
long no;
if (cc == NULL || gc == NULL) if (cc == NULL || gc == NULL)
errx(1, "group_add: a ctx is NULL"); errx(1, "group_add: a ctx is NULL");
no = gc->shortcut - 1;
if (cc->group == gc) if (cc->group == gc)
return; return;
if (cc->group != NULL) if (cc->group != NULL)
TAILQ_REMOVE(&cc->group->clients, cc, group_entry); 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); TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry);
cc->group = gc; cc->group = gc;
xu_ewmh_net_wm_desktop(cc);
} }
static void static void
group_remove(struct client_ctx *cc) group_remove(struct client_ctx *cc)
{ {
long no = 0xffffffff;
if (cc == NULL || cc->group == NULL) if (cc == NULL || cc->group == NULL)
errx(1, "group_remove: a ctx is 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); TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
cc->group = NULL; cc->group = NULL;
xu_ewmh_net_wm_desktop(cc);
} }
static void static void
@ -146,8 +139,6 @@ void
group_init(struct screen_ctx *sc) group_init(struct screen_ctx *sc)
{ {
int i; int i;
long viewports[2] = {0, 0};
long ndesks = CALMWM_NGROUPS, zero = 0;
TAILQ_INIT(&sc->groupq); TAILQ_INIT(&sc->groupq);
sc->group_hideall = 0; sc->group_hideall = 0;
@ -164,23 +155,11 @@ group_init(struct screen_ctx *sc)
TAILQ_INSERT_TAIL(&sc->groupq, &sc->groups[i], entry); TAILQ_INSERT_TAIL(&sc->groupq, &sc->groups[i], entry);
} }
/* we don't support large desktops, so this is always (0, 0) */ xu_ewmh_net_wm_desktop_viewport(sc);
XChangeProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_VIEWPORT, xu_ewmh_net_wm_number_of_desktops(sc);
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)viewports, 2); xu_ewmh_net_showing_desktop(sc);
XChangeProperty(X_Dpy, sc->rootwin, _NET_NUMBER_OF_DESKTOPS, xu_ewmh_net_virtual_roots(sc);
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);
group_setactive(sc, 0); group_setactive(sc, 0);
} }
@ -209,8 +188,8 @@ static void
group_setactive(struct screen_ctx *sc, long idx) group_setactive(struct screen_ctx *sc, long idx)
{ {
sc->group_active = &sc->groups[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 void
@ -439,8 +418,8 @@ group_autogroup(struct client_ctx *cc)
if (cc->app_class == NULL || cc->app_name == NULL) if (cc->app_class == NULL || cc->app_name == NULL)
return; return;
if (xu_getprop(cc->win, _NET_WM_DESKTOP, XA_CARDINAL, if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP].atom,
1, (unsigned char **)&grpno) > 0) { XA_CARDINAL, 1, (unsigned char **)&grpno) > 0) {
if (*grpno == 0xffffffff) if (*grpno == 0xffffffff)
no = 0; no = 0;
else if (*grpno > CALMWM_NGROUPS || *grpno < 0) else if (*grpno > CALMWM_NGROUPS || *grpno < 0)
@ -483,8 +462,9 @@ group_update_names(struct screen_ctx *sc)
int format_ret, i = 0, nstrings = 0, n, setnames = 0; int format_ret, i = 0, nstrings = 0, n, setnames = 0;
unsigned long bytes_after, num_ret; unsigned long bytes_after, num_ret;
if (XGetWindowProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_NAMES, 0, if (XGetWindowProperty(X_Dpy, sc->rootwin,
0xffffff, False, UTF8_STRING, &type_ret, &format_ret, ewmh[_NET_DESKTOP_NAMES].atom, 0, 0xffffff, False,
cwmh[UTF8_STRING].atom, &type_ret, &format_ret,
&num_ret, &bytes_after, &prop_ret) == Success && &num_ret, &bytes_after, &prop_ret) == Success &&
prop_ret != NULL && format_ret == 8) { prop_ret != NULL && format_ret == 8) {
/* failure, just set defaults */ /* failure, just set defaults */
@ -545,6 +525,5 @@ group_set_names(struct screen_ctx *sc)
q += slen; q += slen;
} }
XChangeProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_NAMES, xu_ewmh_net_desktop_names(sc, p, len);
UTF8_STRING, 8, PropModeReplace, p, len);
} }

View File

@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* *
* $OpenBSD: screen.c,v 1.28 2011/05/11 13:53:51 okan Exp $ * $OpenBSD: screen.c,v 1.29 2012/07/03 13:49:03 okan Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -111,23 +111,9 @@ screen_find_xinerama(struct screen_ctx *sc, int x, int y)
void void
screen_update_geometry(struct screen_ctx *sc, int width, int height) screen_update_geometry(struct screen_ctx *sc, int width, int height)
{ {
long geom[2], workareas[CALMWM_NGROUPS][4]; sc->xmax = width;
int i; sc->ymax = height;
sc->xmax = geom[0] = width; xu_ewmh_net_desktop_geometry(sc);
sc->ymax = geom[1] = height; xu_ewmh_net_workarea(sc);
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);
}
XChangeProperty(X_Dpy, sc->rootwin, _NET_WORKAREA,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)workareas, CALMWM_NGROUPS * 4);
} }

View File

@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* *
* $OpenBSD: xevents.c,v 1.60 2012/05/16 21:57:21 okan Exp $ * $OpenBSD: xevents.c,v 1.61 2012/07/03 13:49:03 okan Exp $
*/ */
/* /*
@ -207,7 +207,7 @@ xev_handle_propertynotify(XEvent *ee)
goto test; goto test;
return; return;
test: test:
if (e->atom == _NET_DESKTOP_NAMES) if (e->atom == ewmh[_NET_DESKTOP_NAMES].atom)
group_update_names(sc); group_update_names(sc);
} }
} }

View File

@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* *
* $OpenBSD: xutil.c,v 1.40 2012/05/16 01:17:14 okan Exp $ * $OpenBSD: xutil.c,v 1.41 2012/07/03 13:49:03 okan Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -207,7 +207,8 @@ xu_getstate(struct client_ctx *cc, int *state)
{ {
long *p = NULL; 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, WM_STATE, 2L,
(u_char **)&p) <= 0)
return (-1); return (-1);
*state = (int)*p; *state = (int)*p;
@ -225,67 +226,194 @@ xu_setstate(struct client_ctx *cc, int state)
dat[1] = None; dat[1] = None;
cc->state = state; cc->state = state;
XChangeProperty(X_Dpy, cc->win, WM_STATE, WM_STATE, 32, XChangeProperty(X_Dpy, cc->win,
cwmh[WM_STATE].atom, WM_STATE, 32,
PropModeReplace, (unsigned char *)dat, 2); PropModeReplace, (unsigned char *)dat, 2);
} }
Atom cwm_atoms[CWM_NO_ATOMS]; struct atom_ctx cwmh[CWMH_NITEMS] = {
char *atoms[CWM_NO_ATOMS] = { {"WM_STATE", None},
"WM_STATE", {"WM_DELETE_WINDOW", None},
"WM_DELETE_WINDOW", {"WM_TAKE_FOCUS", None},
"WM_TAKE_FOCUS", {"WM_PROTOCOLS", None},
"WM_PROTOCOLS", {"_MOTIF_WM_HINTS", None},
"_MOTIF_WM_HINTS", {"UTF8_STRING", None},
"UTF8_STRING", };
"_NET_SUPPORTED", struct atom_ctx ewmh[EWMH_NITEMS] = {
"_NET_SUPPORTING_WM_CHECK", {"_NET_SUPPORTED", None},
"_NET_WM_NAME", {"_NET_SUPPORTING_WM_CHECK", None},
"_NET_ACTIVE_WINDOW", {"_NET_ACTIVE_WINDOW", None},
"_NET_CLIENT_LIST", {"_NET_CLIENT_LIST", None},
"_NET_NUMBER_OF_DESKTOPS", {"_NET_NUMBER_OF_DESKTOPS", None},
"_NET_CURRENT_DESKTOP", {"_NET_CURRENT_DESKTOP", None},
"_NET_DESKTOP_VIEWPORT", {"_NET_DESKTOP_VIEWPORT", None},
"_NET_DESKTOP_GEOMETRY", {"_NET_DESKTOP_GEOMETRY", None},
"_NET_VIRTUAL_ROOTS", {"_NET_VIRTUAL_ROOTS", None},
"_NET_SHOWING_DESKTOP", {"_NET_SHOWING_DESKTOP", None},
"_NET_DESKTOP_NAMES", {"_NET_DESKTOP_NAMES", None},
"_NET_WM_DESKTOP", {"_NET_WORKAREA", None},
"_NET_WORKAREA", {"_NET_WM_NAME", None},
{"_NET_WM_DESKTOP", None},
}; };
void void
xu_getatoms(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 void
xu_ewmh_net_supported(struct screen_ctx *sc) xu_ewmh_net_supported(struct screen_ctx *sc)
{ {
XChangeProperty(X_Dpy, sc->rootwin, _NET_SUPPORTED, XA_ATOM, 32, Atom atom[EWMH_NITEMS];
PropModeReplace, (unsigned char *)&_NET_SUPPORTED, int i;
CWM_NO_ATOMS - CWM_NETWM_START);
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 void
xu_ewmh_net_supported_wm_check(struct screen_ctx *sc) xu_ewmh_net_supported_wm_check(struct screen_ctx *sc)
{ {
Window w; Window w;
w = XCreateSimpleWindow(X_Dpy, sc->rootwin, -1, -1, 1, 1, 0, 0, 0); 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); 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); XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1);
XChangeProperty(X_Dpy, w, _NET_WM_NAME, UTF8_STRING, XChangeProperty(X_Dpy, w, ewmh[_NET_WM_NAME].atom,
8, PropModeReplace, WMNAME, strlen(WMNAME)); XA_WM_NAME, 8, PropModeReplace, WMNAME, strlen(WMNAME));
}
void
xu_ewmh_net_desktop_geometry(struct screen_ctx *sc)
{
long geom[2] = { sc->xmax, sc->ymax };
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->gap.left;
workareas[i][1] = sc->gap.top;
workareas[i][2] = sc->xmax - (sc->gap.left + sc->gap.right);
workareas[i][3] = sc->ymax - (sc->gap.top + sc->gap.bottom);
}
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 unsigned long