#include "lwm.h"
#include "ewmh.h"
-Atom ewmh_atom[EWMH_ATOM_LAST];
-Atom utf8_string;
-
-void
-ewmh_init(void) {
- /* build half a million EWMH atoms */
- ewmh_atom[_NET_SUPPORTED] =
- XInternAtom(dpy, "_NET_SUPPORTED", False);
- ewmh_atom[_NET_CLIENT_LIST] =
- XInternAtom(dpy, "_NET_CLIENT_LIST", False);
- ewmh_atom[_NET_CLIENT_LIST_STACKING] =
- XInternAtom(dpy, "_NET_CLIENT_LIST_STACKING", False);
- ewmh_atom[_NET_NUMBER_OF_DESKTOPS] =
- XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
- ewmh_atom[_NET_DESKTOP_GEOMETRY] =
- XInternAtom(dpy, "_NET_DESKTOP_GEOMETRY", False);
- ewmh_atom[_NET_DESKTOP_VIEWPORT] =
- XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False);
- ewmh_atom[_NET_CURRENT_DESKTOP] =
- XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
- ewmh_atom[_NET_ACTIVE_WINDOW] =
- XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
- ewmh_atom[_NET_WORKAREA] =
- XInternAtom(dpy, "_NET_WORKAREA", False);
- ewmh_atom[_NET_SUPPORTING_WM_CHECK] =
- XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
- ewmh_atom[_NET_CLOSE_WINDOW] =
- XInternAtom(dpy, "_NET_CLOSE_WINDOW", False);
- ewmh_atom[_NET_MOVERESIZE_WINDOW] =
- XInternAtom(dpy, "_NET_MOVERESIZE_WINDOW", False);
- ewmh_atom[_NET_WM_MOVERESIZE] =
- XInternAtom(dpy, "_NET_WM_MOVERESIZE", False);
- ewmh_atom[_NET_WM_NAME] =
- XInternAtom(dpy, "_NET_WM_NAME", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
- ewmh_atom[_NET_WM_STATE] =
- XInternAtom(dpy, "_NET_WM_STATE", False);
- ewmh_atom[_NET_WM_ALLOWED_ACTIONS] =
- XInternAtom(dpy, "_NET_WM_ALLOWED_ACTIONS", False);
- ewmh_atom[_NET_WM_STRUT] =
- XInternAtom(dpy, "_NET_WM_STRUT", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_DESKTOP] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_DOCK] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_TOOLBAR] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_MENU] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_MENU", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_UTILITY] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_UTILITY", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_SPLASH] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_SPLASH", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_DIALOG] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False);
- ewmh_atom[_NET_WM_WINDOW_TYPE_NORMAL] =
- XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False);
- ewmh_atom[_NET_WM_STATE_SKIP_TASKBAR] =
- XInternAtom(dpy, "_NET_WM_STATE_SKIP_TASKBAR", False);
- ewmh_atom[_NET_WM_STATE_SKIP_PAGER] =
- XInternAtom(dpy, "_NET_WM_STATE_SKIP_PAGER", False);
- ewmh_atom[_NET_WM_STATE_HIDDEN] =
- XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", False);
- ewmh_atom[_NET_WM_STATE_FULLSCREEN] =
- XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
- ewmh_atom[_NET_WM_ACTION_MOVE] =
- XInternAtom(dpy, "_NET_WM_ACTION_MOVE", False);
- ewmh_atom[_NET_WM_ACTION_RESIZE] =
- XInternAtom(dpy, "_NET_WM_ACTION_RESIZE", False);
- ewmh_atom[_NET_WM_ACTION_FULLSCREEN] =
- XInternAtom(dpy, "_NET_WM_ACTION_FULLSCREEN", False);
- ewmh_atom[_NET_WM_ACTION_CLOSE] =
- XInternAtom(dpy, "_NET_WM_ACTION_CLOSE", False);
- utf8_string = XInternAtom(dpy, "UTF8_STRING", False);
-}
-
-void
-ewmh_init_screens(void) {
- int i;
- unsigned long data[4];
-
- /* announce EWMH compatibility on all acreens */
- for (i = 0; i < screen_count; i++) {
- screens[i].ewmh_set_client_list = False;
- screens[i].ewmh_compat = XCreateSimpleWindow(dpy,
- screens[i].root,
- -200, -200, 1, 1,
- 0, 0, 0);
- XChangeProperty(dpy, screens[i].ewmh_compat,
- ewmh_atom[_NET_WM_NAME],
- utf8_string, 8, PropModeReplace,
- (unsigned char*)"lwm", 3);
-
- /* set root window properties */
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_SUPPORTED],
- XA_ATOM, 32, PropModeReplace,
- (unsigned char *)ewmh_atom, EWMH_ATOM_LAST);
-
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_SUPPORTING_WM_CHECK],
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char *)&screens[i].ewmh_compat, 1);
-
- data[0] = 1;
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_NUMBER_OF_DESKTOPS],
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char*)data, 1);
-
- data[0] = screens[i].display_width;
- data[1] = screens[i].display_height;
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_DESKTOP_GEOMETRY],
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char*)data, 2);
-
- data[0] = 0;
- data[1] = 0;
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_DESKTOP_VIEWPORT],
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char*)data, 2);
-
- data[0] = 0;
- XChangeProperty(dpy, screens[i].root,
- ewmh_atom[_NET_CURRENT_DESKTOP],
- XA_CARDINAL, 32, PropModeReplace,
- (unsigned char*)data, 1);
-
- ewmh_set_client_list(&screens[i]);
- }
-}
-
-EWMHWindowType
-ewmh_get_window_type(Window w) {
- Atom rt;
- Atom *type;
- int fmt;
- unsigned long n;
- unsigned long extra;
- int i;
- EWMHWindowType ret;
-
- i = XGetWindowProperty(dpy, w,
- ewmh_atom[_NET_WM_WINDOW_TYPE],
- 0, 100, False, XA_ATOM, &rt, &fmt, &n, &extra,
- (unsigned char **)&type);
- if (i != Success || type == NULL)
- return WTypeNone;
- ret = WTypeNone;
- for (; n; n--) {
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_DESKTOP]) {
- ret = WTypeDesktop;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_DOCK]) {
- ret = WTypeDock;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_TOOLBAR]) {
- ret = WTypeToolbar;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_MENU]) {
- ret = WTypeMenu;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_UTILITY]) {
- ret = WTypeUtility;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_SPLASH]) {
- ret = WTypeSplash;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_DIALOG]) {
- ret = WTypeDialog;
- break;
- }
- if (type[n - 1] ==
- ewmh_atom[_NET_WM_WINDOW_TYPE_NORMAL]) {
- ret = WTypeNormal;
- break;
- }
- }
- XFree(type);
- return ret;
-}
-
-
Bool ewmh_get_window_name(Client *c) {
- Atom rt;
+ Atom rt, utf8_string;
char *name;
int fmt;
unsigned long n;
unsigned long extra;
int i;
+ utf8_string = XInternAtom(dpy, "UTF8_STRING", False);
i = XGetWindowProperty(dpy, c->window,
- ewmh_atom[_NET_WM_NAME],
+ XInternAtom(dpy, "_NET_WM_NAME", False),
0, 100, False, utf8_string, &rt, &fmt, &n, &extra,
(unsigned char **)&name);
if (i != Success || name == NULL)
XFree(name);
return True;
}
-
-Bool
-ewmh_hasframe(Client *c) {
- switch (c->wtype) {
- case WTypeDesktop:
- case WTypeDock:
- case WTypeMenu:
- case WTypeSplash:
- return False;
- default:
- return True;
- }
-}
-
-static Bool
-new_state(unsigned long action, Bool current)
-{
- enum Action {remove, add, toggle};
-
- switch (action) {
- case remove:
- return False;
- case add:
- return True;
- case toggle:
- if (current == True) return False; else return True;
- }
- fprintf(stderr,"%s: bad action in _NET_WM_STATE (%d)\n",
- argv0, (int) action);
- return current;
-}
-
-void
-ewmh_set_allowed(Client *c)
-{
-/* FIXME: this is dumb - the allowed actions should be calculuated
- * but for now, anything goes.
- */
- Atom action[4];
-
- action[0] = ewmh_atom[_NET_WM_ACTION_MOVE];
- action[1] = ewmh_atom[_NET_WM_ACTION_RESIZE];
- action[2] = ewmh_atom[_NET_WM_ACTION_FULLSCREEN];
- action[3] = ewmh_atom[_NET_WM_ACTION_CLOSE];
- XChangeProperty(dpy, c->window, ewmh_atom[_NET_WM_ALLOWED_ACTIONS],
- XA_ATOM, 32, PropModeReplace, (unsigned char *)action, 4);
-}
-
-static Bool
-valid_for_client_list(ScreenInfo *screen, Client *c) {
- if (c->screen != screen) return False;
- if (c->state == WithdrawnState) return False;
- return True;
-}
-
-/*
-* update_client_list updates the properties on the root window used by
-* task lists and pagers.
-*
-* it should be called whenever the window stack is modified, or when clients
-* are hidden or unhidden.
-*/
-void
-ewmh_set_client_list(ScreenInfo *screen) {
- int no_clients=0;
- Window *client_list=NULL;
- Window *stacked_client_list=NULL;
- Client *c;
-
- if (screen == NULL || screen->ewmh_set_client_list == True) return;
- screen->ewmh_set_client_list = True;
- for (c = Client_List(); c; c = c->next) {
- if (valid_for_client_list(screen, c) == True) no_clients++;
- }
- if (no_clients > 0) {
- int i;
- Window dw1;
- Window dw2;
- Window *wins;
- unsigned int win;
- unsigned int nwins;
-
- client_list = malloc(sizeof(Window) * no_clients);
- i = no_clients - 1; /* array starts with oldest */
- for (c = Client_List(); c; c = c->next) {
- if (valid_for_client_list(screen, c) == True) {
- client_list[i] = c->window;
- i--;
- if (i < 0) break;
- }
- }
-
- stacked_client_list = malloc(sizeof(Window) * no_clients);
- i = 0;
- XQueryTree(dpy, screen->root, &dw1, &dw2, &wins, &nwins);
- for (win = 0; win < nwins; win++) {
- c = Client_Get(wins[win]);
- if (!c) continue;
- if (valid_for_client_list(screen, c) == True) {
- stacked_client_list[i] = c->window;
- i++;
- if (i >= no_clients) break;
- }
- }
- if ( nwins > 0 ) XFree(wins);
-
- }
- XChangeProperty(dpy, screen->root,
- ewmh_atom[_NET_CLIENT_LIST],
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char*)client_list, no_clients);
- XChangeProperty(dpy, screen->root,
- ewmh_atom[_NET_CLIENT_LIST_STACKING],
- XA_WINDOW, 32, PropModeReplace,
- (unsigned char*)stacked_client_list, no_clients);
- if (no_clients > 0 ) {
- free(client_list);
- free(stacked_client_list);
- }
- screen->ewmh_set_client_list = False;
-}