2007-04-27 21:58:48 +04:00
|
|
|
/*
|
|
|
|
* calmwm - the calm window manager
|
|
|
|
*
|
|
|
|
* Copyright (c) 2004 Marius Aamodt Eriksen <marius@monkey.org>
|
2008-01-11 19:06:44 +03:00
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
2007-04-27 21:58:48 +04:00
|
|
|
*
|
2011-05-11 17:53:51 +04:00
|
|
|
* $OpenBSD$
|
2007-04-27 21:58:48 +04:00
|
|
|
*/
|
|
|
|
|
2009-12-15 07:10:42 +03:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/queue.h>
|
|
|
|
|
|
|
|
#include <err.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2007-04-27 21:58:48 +04:00
|
|
|
#include "calmwm.h"
|
|
|
|
|
2009-06-26 16:21:58 +04:00
|
|
|
static unsigned int ign_mods[] = { 0, LockMask, Mod2Mask, Mod2Mask | LockMask };
|
2008-06-18 03:40:33 +04:00
|
|
|
|
2007-04-27 21:58:48 +04:00
|
|
|
int
|
|
|
|
xu_ptr_grab(Window win, int mask, Cursor curs)
|
|
|
|
{
|
2007-05-28 22:34:27 +04:00
|
|
|
return (XGrabPointer(X_Dpy, win, False, mask,
|
2008-05-16 02:18:00 +04:00
|
|
|
GrabModeAsync, GrabModeAsync,
|
|
|
|
None, curs, CurrentTime) == GrabSuccess ? 0 : -1);
|
2007-04-27 21:58:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
xu_ptr_regrab(int mask, Cursor curs)
|
|
|
|
{
|
2007-05-28 22:34:27 +04:00
|
|
|
return (XChangeActivePointerGrab(X_Dpy, mask,
|
2008-05-16 02:18:00 +04:00
|
|
|
curs, CurrentTime) == GrabSuccess ? 0 : -1);
|
2007-04-27 21:58:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xu_ptr_ungrab(void)
|
|
|
|
{
|
2007-05-28 22:34:27 +04:00
|
|
|
XUngrabPointer(X_Dpy, CurrentTime);
|
2007-04-27 21:58:48 +04:00
|
|
|
}
|
|
|
|
|
2008-06-18 03:40:33 +04:00
|
|
|
void
|
2007-04-27 21:58:48 +04:00
|
|
|
xu_btn_grab(Window win, int mask, u_int btn)
|
|
|
|
{
|
2008-06-18 03:40:33 +04:00
|
|
|
int i;
|
2011-03-22 13:57:31 +03:00
|
|
|
for (i = 0; i < nitems(ign_mods); i++)
|
2008-06-18 03:40:33 +04:00
|
|
|
XGrabButton(X_Dpy, btn, (mask | ign_mods[i]), win,
|
|
|
|
False, ButtonMask, GrabModeAsync,
|
|
|
|
GrabModeSync, None, None);
|
2007-04-27 21:58:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xu_btn_ungrab(Window win, int mask, u_int btn)
|
|
|
|
{
|
2008-06-18 03:40:33 +04:00
|
|
|
int i;
|
2011-03-22 13:57:31 +03:00
|
|
|
for (i = 0; i < nitems(ign_mods); i++)
|
2008-06-18 03:40:33 +04:00
|
|
|
XUngrabButton(X_Dpy, btn, (mask | ign_mods[i]), win);
|
2007-04-27 21:58:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xu_ptr_getpos(Window rootwin, int *x, int *y)
|
|
|
|
{
|
2008-07-11 18:21:28 +04:00
|
|
|
Window w0, w1;
|
|
|
|
int tmp0, tmp1;
|
|
|
|
u_int tmp2;
|
2007-04-27 21:58:48 +04:00
|
|
|
|
2008-04-16 00:24:41 +04:00
|
|
|
XQueryPointer(X_Dpy, rootwin, &w0, &w1, &tmp0, &tmp1, x, y, &tmp2);
|
2007-04-27 21:58:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xu_ptr_setpos(Window win, int x, int y)
|
|
|
|
{
|
2007-05-28 22:34:27 +04:00
|
|
|
XWarpPointer(X_Dpy, None, win, 0, 0, 0, 0, x, y);
|
2007-04-27 21:58:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xu_key_grab(Window win, int mask, int keysym)
|
|
|
|
{
|
2008-07-11 18:21:28 +04:00
|
|
|
KeyCode code;
|
|
|
|
int i;
|
2007-04-27 21:58:48 +04:00
|
|
|
|
2007-05-28 22:34:27 +04:00
|
|
|
code = XKeysymToKeycode(X_Dpy, keysym);
|
|
|
|
if ((XKeycodeToKeysym(X_Dpy, code, 0) != keysym) &&
|
|
|
|
(XKeycodeToKeysym(X_Dpy, code, 1) == keysym))
|
2007-04-27 21:58:48 +04:00
|
|
|
mask |= ShiftMask;
|
|
|
|
|
2011-03-22 13:57:31 +03:00
|
|
|
for (i = 0; i < nitems(ign_mods); i++)
|
2008-07-23 00:26:12 +04:00
|
|
|
XGrabKey(X_Dpy, code, (mask | ign_mods[i]), win,
|
|
|
|
True, GrabModeAsync, GrabModeAsync);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xu_key_ungrab(Window win, int mask, int keysym)
|
|
|
|
{
|
|
|
|
KeyCode code;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
code = XKeysymToKeycode(X_Dpy, keysym);
|
|
|
|
if ((XKeycodeToKeysym(X_Dpy, code, 0) != keysym) &&
|
|
|
|
(XKeycodeToKeysym(X_Dpy, code, 1) == keysym))
|
|
|
|
mask |= ShiftMask;
|
|
|
|
|
2011-03-22 13:57:31 +03:00
|
|
|
for (i = 0; i < nitems(ign_mods); i++)
|
2008-07-23 00:26:12 +04:00
|
|
|
XUngrabKey(X_Dpy, code, (mask | ign_mods[i]), win);
|
2007-04-27 21:58:48 +04:00
|
|
|
}
|
|
|
|
|
2011-03-22 13:49:46 +03:00
|
|
|
void
|
|
|
|
xu_configure(struct client_ctx *cc)
|
|
|
|
{
|
|
|
|
XConfigureEvent ce;
|
|
|
|
|
|
|
|
ce.type = ConfigureNotify;
|
|
|
|
ce.event = cc->win;
|
|
|
|
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.border_width = cc->bwidth;
|
|
|
|
ce.above = None;
|
|
|
|
ce.override_redirect = 0;
|
|
|
|
|
|
|
|
XSendEvent(X_Dpy, cc->win, False, StructureNotifyMask, (XEvent *)&ce);
|
|
|
|
}
|
|
|
|
|
2007-04-27 21:58:48 +04:00
|
|
|
void
|
2010-04-11 20:51:26 +04:00
|
|
|
xu_sendmsg(Window win, Atom atm, long val)
|
2007-04-27 21:58:48 +04:00
|
|
|
{
|
2008-07-11 18:21:28 +04:00
|
|
|
XEvent e;
|
2007-04-27 21:58:48 +04:00
|
|
|
|
|
|
|
memset(&e, 0, sizeof(e));
|
|
|
|
e.xclient.type = ClientMessage;
|
2010-04-11 20:51:26 +04:00
|
|
|
e.xclient.window = win;
|
2007-04-27 21:58:48 +04:00
|
|
|
e.xclient.message_type = atm;
|
|
|
|
e.xclient.format = 32;
|
|
|
|
e.xclient.data.l[0] = val;
|
|
|
|
e.xclient.data.l[1] = CurrentTime;
|
|
|
|
|
2010-04-11 20:51:26 +04:00
|
|
|
XSendEvent(X_Dpy, win, False, 0, &e);
|
2007-04-27 21:58:48 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2010-04-11 20:51:26 +04:00
|
|
|
xu_getprop(Window win, Atom atm, Atom type, long len, u_char **p)
|
2007-04-27 21:58:48 +04:00
|
|
|
{
|
2008-07-11 18:21:28 +04:00
|
|
|
Atom realtype;
|
|
|
|
u_long n, extra;
|
|
|
|
int format;
|
2007-04-27 21:58:48 +04:00
|
|
|
|
2010-04-11 20:51:26 +04:00
|
|
|
if (XGetWindowProperty(X_Dpy, win, atm, 0L, len, False, type,
|
2008-05-16 02:18:00 +04:00
|
|
|
&realtype, &format, &n, &extra, p) != Success || *p == NULL)
|
2007-04-27 21:58:48 +04:00
|
|
|
return (-1);
|
|
|
|
|
|
|
|
if (n == 0)
|
|
|
|
XFree(*p);
|
|
|
|
|
|
|
|
return (n);
|
|
|
|
}
|
|
|
|
|
2010-05-23 02:10:31 +04:00
|
|
|
int
|
|
|
|
xu_getstrprop(Window win, Atom atm, char **text) {
|
|
|
|
XTextProperty prop;
|
|
|
|
char **list;
|
2010-05-23 02:32:08 +04:00
|
|
|
int nitems = 0;
|
2010-05-23 02:10:31 +04:00
|
|
|
|
|
|
|
*text = NULL;
|
|
|
|
|
|
|
|
XGetTextProperty(X_Dpy, win, &prop, atm);
|
|
|
|
if (!prop.nitems)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
if (Xutf8TextPropertyToTextList(X_Dpy, &prop, &list,
|
|
|
|
&nitems) == Success && nitems > 0 && *list) {
|
|
|
|
if (nitems > 1) {
|
|
|
|
XTextProperty prop2;
|
|
|
|
if (Xutf8TextListToTextProperty(X_Dpy, list, nitems,
|
|
|
|
XUTF8StringStyle, &prop2) == Success) {
|
|
|
|
*text = xstrdup(prop2.value);
|
|
|
|
XFree(prop2.value);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*text = xstrdup(*list);
|
|
|
|
}
|
|
|
|
XFreeStringList(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
XFree(prop.value);
|
|
|
|
|
|
|
|
return (nitems);
|
|
|
|
}
|
|
|
|
|
2007-04-27 21:58:48 +04:00
|
|
|
int
|
|
|
|
xu_getstate(struct client_ctx *cc, int *state)
|
|
|
|
{
|
2008-07-11 18:21:28 +04:00
|
|
|
long *p = NULL;
|
|
|
|
|
2010-04-11 20:51:26 +04:00
|
|
|
if (xu_getprop(cc->win, WM_STATE, WM_STATE, 2L, (u_char **)&p) <= 0)
|
2007-04-27 21:58:48 +04:00
|
|
|
return (-1);
|
|
|
|
|
|
|
|
*state = (int)*p;
|
|
|
|
XFree((char *)p);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xu_setstate(struct client_ctx *cc, int state)
|
|
|
|
{
|
2008-07-11 18:21:28 +04:00
|
|
|
long dat[2];
|
2007-04-27 21:58:48 +04:00
|
|
|
|
2009-06-17 17:08:37 +04:00
|
|
|
dat[0] = state;
|
|
|
|
dat[1] = None;
|
2007-04-27 21:58:48 +04:00
|
|
|
|
|
|
|
cc->state = state;
|
2009-01-22 18:26:33 +03:00
|
|
|
XChangeProperty(X_Dpy, cc->win, WM_STATE, WM_STATE, 32,
|
2007-04-27 21:58:48 +04:00
|
|
|
PropModeReplace, (unsigned char *)dat, 2);
|
|
|
|
}
|
2009-01-22 18:26:33 +03:00
|
|
|
|
|
|
|
Atom cwm_atoms[CWM_NO_ATOMS];
|
2009-01-23 23:04:30 +03:00
|
|
|
char *atoms[CWM_NO_ATOMS] = {
|
|
|
|
"WM_STATE",
|
|
|
|
"WM_DELETE_WINDOW",
|
|
|
|
"WM_TAKE_FOCUS",
|
|
|
|
"WM_PROTOCOLS",
|
2009-01-27 03:42:53 +03:00
|
|
|
"_MOTIF_WM_HINTS",
|
2009-12-08 00:20:52 +03:00
|
|
|
"UTF8_STRING",
|
|
|
|
"_NET_SUPPORTED",
|
|
|
|
"_NET_SUPPORTING_WM_CHECK",
|
|
|
|
"_NET_WM_NAME",
|
2009-12-08 01:21:59 +03:00
|
|
|
"_NET_ACTIVE_WINDOW",
|
2009-12-08 01:46:15 +03:00
|
|
|
"_NET_CLIENT_LIST",
|
2009-12-08 02:19:51 +03:00
|
|
|
"_NET_NUMBER_OF_DESKTOPS",
|
2009-12-11 02:14:58 +03:00
|
|
|
"_NET_CURRENT_DESKTOP",
|
|
|
|
"_NET_DESKTOP_VIEWPORT",
|
|
|
|
"_NET_DESKTOP_GEOMETRY",
|
2009-12-11 02:21:26 +03:00
|
|
|
"_NET_VIRTUAL_ROOTS",
|
|
|
|
"_NET_SHOWING_DESKTOP",
|
2009-12-11 20:51:42 +03:00
|
|
|
"_NET_DESKTOP_NAMES",
|
2009-12-11 20:55:42 +03:00
|
|
|
"_NET_WM_DESKTOP",
|
2009-12-11 21:09:16 +03:00
|
|
|
"_NET_WORKAREA",
|
2009-01-23 23:04:30 +03:00
|
|
|
};
|
|
|
|
|
2009-01-22 18:26:33 +03:00
|
|
|
void
|
|
|
|
xu_getatoms(void)
|
|
|
|
{
|
2009-01-23 23:04:30 +03:00
|
|
|
XInternAtoms(X_Dpy, atoms, CWM_NO_ATOMS, False, cwm_atoms);
|
2009-01-22 18:26:33 +03:00
|
|
|
}
|
2009-05-18 03:40:57 +04:00
|
|
|
|
2009-12-08 00:20:52 +03:00
|
|
|
void
|
|
|
|
xu_setwmname(struct screen_ctx *sc)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* set up the _NET_SUPPORTED hint with all netwm atoms that we
|
|
|
|
* know about.
|
|
|
|
*/
|
|
|
|
XChangeProperty(X_Dpy, sc->rootwin, _NET_SUPPORTED, XA_ATOM, 32,
|
|
|
|
PropModeReplace, (unsigned char *)&_NET_SUPPORTED,
|
|
|
|
CWM_NO_ATOMS - CWM_NETWM_START);
|
|
|
|
/*
|
|
|
|
* netwm spec says that to prove that the hint is not stale you must
|
|
|
|
* provide _NET_SUPPORTING_WM_CHECK containing a window (we use the
|
|
|
|
* menu window). The property must be set on the root window and the
|
|
|
|
* window itself, the window also must have _NET_WM_NAME set with the
|
|
|
|
* window manager name.
|
|
|
|
*/
|
|
|
|
XChangeProperty(X_Dpy, sc->rootwin, _NET_SUPPORTING_WM_CHECK,
|
|
|
|
XA_WINDOW, 32, PropModeReplace, (unsigned char *)&sc->menuwin, 1);
|
|
|
|
XChangeProperty(X_Dpy, sc->menuwin, _NET_SUPPORTING_WM_CHECK,
|
|
|
|
XA_WINDOW, 32, PropModeReplace, (unsigned char *)&sc->menuwin, 1);
|
|
|
|
XChangeProperty(X_Dpy, sc->menuwin, _NET_WM_NAME, UTF8_STRING,
|
|
|
|
8, PropModeReplace, WMNAME, strlen(WMNAME));
|
|
|
|
}
|
|
|
|
|
2009-05-18 03:40:57 +04:00
|
|
|
unsigned long
|
|
|
|
xu_getcolor(struct screen_ctx *sc, char *name)
|
|
|
|
{
|
|
|
|
XColor color, tmp;
|
|
|
|
|
|
|
|
if (!XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, sc->which),
|
|
|
|
name, &color, &tmp)) {
|
|
|
|
warnx("XAllocNamedColor error: '%s'", name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return color.pixel;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
xu_freecolor(struct screen_ctx *sc, unsigned long pixel)
|
|
|
|
{
|
|
|
|
XFreeColors(X_Dpy, DefaultColormap(X_Dpy, sc->which), &pixel, 1, 0L);
|
|
|
|
}
|