cvsimport

This commit is contained in:
okan 2012-07-18 21:53:22 +00:00
commit 1545eb0837
11 changed files with 427 additions and 347 deletions

View File

@ -44,7 +44,7 @@ Cursor Cursor_resize;
struct screen_ctx_q Screenq = TAILQ_HEAD_INITIALIZER(Screenq); struct screen_ctx_q Screenq = TAILQ_HEAD_INITIALIZER(Screenq);
struct client_ctx_q Clientq = TAILQ_HEAD_INITIALIZER(Clientq); struct client_ctx_q Clientq = TAILQ_HEAD_INITIALIZER(Clientq);
int HasXinerama, HasRandr, Randr_ev; int HasRandr, Randr_ev;
struct conf Conf; struct conf Conf;
static void sigchld_cb(int); static void sigchld_cb(int);
@ -157,7 +157,6 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
Window *wins, w0, w1; Window *wins, w0, w1;
XWindowAttributes winattr; XWindowAttributes winattr;
XSetWindowAttributes rootattr; XSetWindowAttributes rootattr;
int fake;
u_int nwins, i; u_int nwins, i;
sc->which = which; sc->which = which;
@ -167,8 +166,8 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
xu_ewmh_net_supported_wm_check(sc); xu_ewmh_net_supported_wm_check(sc);
conf_gap(&Conf, 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); conf_color(&Conf, sc);
@ -201,17 +200,8 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
screen_updatestackingorder(sc); screen_updatestackingorder(sc);
if (XineramaQueryExtension(X_Dpy, &fake, &fake) == 1 &&
((HasXinerama = XineramaIsActive(X_Dpy)) == 1))
HasXinerama = 1;
if (HasRandr) if (HasRandr)
XRRSelectInput(X_Dpy, sc->rootwin, RRScreenChangeNotifyMask); 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); XSync(X_Dpy, False);
} }

View File

@ -108,6 +108,13 @@ struct color {
unsigned long pixel; unsigned long pixel;
}; };
struct geom {
int x;
int y;
int w;
int h;
};
struct gap { struct gap {
int top; int top;
int bottom; int bottom;
@ -130,12 +137,7 @@ struct client_ctx {
XSizeHints *size; XSizeHints *size;
Colormap cmap; Colormap cmap;
u_int bwidth; /* border width */ u_int bwidth; /* border width */
struct { struct geom geom, savegeom;
int x; /* x position */
int y; /* y position */
int width; /* width */
int height;/* height */
} geom, savegeom;
struct { struct {
int basew; /* desired width */ int basew; /* desired width */
int baseh; /* desired height */ int baseh; /* desired height */
@ -216,8 +218,8 @@ struct screen_ctx {
struct color color[CWM_COLOR_MAX]; struct color color[CWM_COLOR_MAX];
GC gc; GC gc;
int cycling; int cycling;
int xmax; struct geom view; /* viewable area */
int ymax; struct geom work; /* workable area, gap-applied */
struct gap gap; struct gap gap;
struct cycle_entry_q mruq; struct cycle_entry_q mruq;
XftColor xftcolor; XftColor xftcolor;
@ -372,8 +374,7 @@ void search_print_client(struct menu *, int);
XineramaScreenInfo *screen_find_xinerama(struct screen_ctx *, int, int); XineramaScreenInfo *screen_find_xinerama(struct screen_ctx *, int, int);
struct screen_ctx *screen_fromroot(Window); struct screen_ctx *screen_fromroot(Window);
void screen_init_xinerama(struct screen_ctx *); void screen_update_geometry(struct screen_ctx *);
void screen_update_geometry(struct screen_ctx *, int, int);
void screen_updatestackingorder(struct screen_ctx *); void screen_updatestackingorder(struct screen_ctx *);
void kbfunc_client_cycle(struct client_ctx *, union arg *); 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(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 *);
@ -502,34 +516,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_ */

218
client.c
View File

@ -89,8 +89,8 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
XGetWindowAttributes(X_Dpy, cc->win, &wattr); XGetWindowAttributes(X_Dpy, cc->win, &wattr);
cc->geom.x = wattr.x; cc->geom.x = wattr.x;
cc->geom.y = wattr.y; cc->geom.y = wattr.y;
cc->geom.width = wattr.width; cc->geom.w = wattr.width;
cc->geom.height = wattr.height; cc->geom.h = wattr.height;
cc->cmap = wattr.colormap; cc->cmap = wattr.colormap;
if (wattr.map_state != IsViewable) { 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(&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;
} }
@ -277,8 +256,8 @@ void
client_maximize(struct client_ctx *cc) client_maximize(struct client_ctx *cc)
{ {
struct screen_ctx *sc = cc->sc; struct screen_ctx *sc = cc->sc;
int xmax = sc->xmax, ymax = sc->ymax; int x_org, y_org, xmax, ymax;
int x_org = 0, y_org = 0; XineramaScreenInfo *xine;
if (cc->flags & CLIENT_FREEZE) if (cc->flags & CLIENT_FREEZE)
return; return;
@ -291,37 +270,38 @@ client_maximize(struct client_ctx *cc)
} }
if ((cc->flags & CLIENT_VMAXIMIZED) == 0) { if ((cc->flags & CLIENT_VMAXIMIZED) == 0) {
cc->savegeom.height = cc->geom.height; cc->savegeom.h = cc->geom.h;
cc->savegeom.y = cc->geom.y; cc->savegeom.y = cc->geom.y;
} }
if ((cc->flags & CLIENT_HMAXIMIZED) == 0) { if ((cc->flags & CLIENT_HMAXIMIZED) == 0) {
cc->savegeom.width = cc->geom.width; cc->savegeom.w = cc->geom.w;
cc->savegeom.x = cc->geom.x; 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
* pick screen that the middle of the window is on. * a window is poking over a boundary
* 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,
xine = screen_find_xinerama(sc, cc->geom.y + cc->geom.h / 2);
cc->geom.x + cc->geom.width / 2, if (xine) {
cc->geom.y + cc->geom.height / 2);
if (xine == NULL)
goto calc;
x_org = xine->x_org; x_org = xine->x_org;
y_org = xine->y_org; y_org = xine->y_org;
xmax = xine->width; xmax = xine->width;
ymax = xine->height; 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.x = x_org + sc->gap.left;
cc->geom.y = y_org + sc->gap.top; cc->geom.y = y_org + sc->gap.top;
cc->geom.height = ymax - (sc->gap.top + sc->gap.bottom); cc->geom.h = ymax - (sc->gap.top + sc->gap.bottom);
cc->geom.width = xmax - (sc->gap.left + sc->gap.right); cc->geom.w = xmax - (sc->gap.left + sc->gap.right);
cc->bwidth = 0; cc->bwidth = 0;
cc->flags |= CLIENT_MAXIMIZED; cc->flags |= CLIENT_MAXIMIZED;
@ -333,43 +313,44 @@ void
client_vertmaximize(struct client_ctx *cc) client_vertmaximize(struct client_ctx *cc)
{ {
struct screen_ctx *sc = cc->sc; struct screen_ctx *sc = cc->sc;
int y_org = 0, ymax = sc->ymax; int y_org, ymax;
XineramaScreenInfo *xine;
if (cc->flags & CLIENT_FREEZE) if (cc->flags & CLIENT_FREEZE)
return; return;
if (cc->flags & CLIENT_VMAXIMIZED) { if (cc->flags & CLIENT_VMAXIMIZED) {
cc->geom.y = cc->savegeom.y; cc->geom.y = cc->savegeom.y;
cc->geom.height = cc->savegeom.height; cc->geom.h = cc->savegeom.h;
cc->bwidth = Conf.bwidth; cc->bwidth = Conf.bwidth;
if (cc->flags & CLIENT_HMAXIMIZED) if (cc->flags & CLIENT_HMAXIMIZED)
cc->geom.width -= cc->bwidth * 2; cc->geom.w -= cc->bwidth * 2;
cc->flags &= ~CLIENT_VMAXIMIZED; cc->flags &= ~CLIENT_VMAXIMIZED;
goto resize; goto resize;
} }
cc->savegeom.y = cc->geom.y; 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 this will make us fully maximized then remove boundary */
if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_HMAXIMIZED) { if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_HMAXIMIZED) {
cc->geom.width += Conf.bwidth * 2; cc->geom.w += Conf.bwidth * 2;
cc->bwidth = 0; cc->bwidth = 0;
} }
if (HasXinerama) { xine = screen_find_xinerama(sc,
XineramaScreenInfo *xine; cc->geom.x + cc->geom.w / 2,
xine = screen_find_xinerama(sc, cc->geom.y + cc->geom.h / 2);
cc->geom.x + cc->geom.width / 2, if (xine) {
cc->geom.y + cc->geom.height / 2);
if (xine == NULL)
goto calc;
y_org = xine->y_org; y_org = xine->y_org;
ymax = xine->height; ymax = xine->height;
} else {
y_org = 0;
ymax = sc->view.h;
} }
calc:
cc->geom.y = y_org + sc->gap.top; 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); sc->gap.bottom);
cc->flags |= CLIENT_VMAXIMIZED; cc->flags |= CLIENT_VMAXIMIZED;
@ -381,43 +362,44 @@ void
client_horizmaximize(struct client_ctx *cc) client_horizmaximize(struct client_ctx *cc)
{ {
struct screen_ctx *sc = cc->sc; struct screen_ctx *sc = cc->sc;
int x_org = 0, xmax = sc->xmax; int x_org, xmax;
XineramaScreenInfo *xine;
if (cc->flags & CLIENT_FREEZE) if (cc->flags & CLIENT_FREEZE)
return; return;
if (cc->flags & CLIENT_HMAXIMIZED) { if (cc->flags & CLIENT_HMAXIMIZED) {
cc->geom.x = cc->savegeom.x; cc->geom.x = cc->savegeom.x;
cc->geom.width = cc->savegeom.width; cc->geom.w = cc->savegeom.w;
cc->bwidth = Conf.bwidth; cc->bwidth = Conf.bwidth;
if (cc->flags & CLIENT_VMAXIMIZED) if (cc->flags & CLIENT_VMAXIMIZED)
cc->geom.height -= cc->bwidth * 2; cc->geom.h -= cc->bwidth * 2;
cc->flags &= ~CLIENT_HMAXIMIZED; cc->flags &= ~CLIENT_HMAXIMIZED;
goto resize; goto resize;
} }
cc->savegeom.x = cc->geom.x; 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 this will make us fully maximized then remove boundary */
if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_VMAXIMIZED) { if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_VMAXIMIZED) {
cc->geom.height += cc->bwidth * 2; cc->geom.h += cc->bwidth * 2;
cc->bwidth = 0; cc->bwidth = 0;
} }
if (HasXinerama) { xine = screen_find_xinerama(sc,
XineramaScreenInfo *xine; cc->geom.x + cc->geom.w / 2,
xine = screen_find_xinerama(sc, cc->geom.y + cc->geom.h / 2);
cc->geom.x + cc->geom.width / 2, if (xine) {
cc->geom.y + cc->geom.height / 2);
if (xine == NULL)
goto calc;
x_org = xine->x_org; x_org = xine->x_org;
xmax = xine->width; xmax = xine->width;
} else {
x_org = 0;
xmax = sc->view.w;
} }
calc:
cc->geom.x = x_org + sc->gap.left; 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); sc->gap.right);
cc->flags |= CLIENT_HMAXIMIZED; cc->flags |= CLIENT_HMAXIMIZED;
@ -431,7 +413,7 @@ client_resize(struct client_ctx *cc)
client_draw_border(cc); client_draw_border(cc);
XMoveResizeWindow(X_Dpy, cc->win, cc->geom.x, 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); xu_configure(cc);
} }
@ -460,8 +442,8 @@ client_ptrwarp(struct client_ctx *cc)
int x = cc->ptr.x, y = cc->ptr.y; int x = cc->ptr.x, y = cc->ptr.y;
if (x == -1 || y == -1) { if (x == -1 || y == -1) {
x = cc->geom.width / 2; x = cc->geom.w / 2;
y = cc->geom.height / 2; y = cc->geom.h / 2;
} }
(cc->state == IconicState) ? client_unhide(cc) : client_raise(cc); (cc->state == IconicState) ? client_unhide(cc) : client_raise(cc);
@ -540,14 +522,14 @@ client_update(struct client_ctx *cc)
int i; int i;
long n; 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) XA_ATOM, 20L, (u_char **)&p)) <= 0)
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 +539,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 +551,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;
@ -690,8 +673,8 @@ client_placecalc(struct client_ctx *cc)
* XRandR bits mean that {x,y}max shouldn't be outside what's * XRandR bits mean that {x,y}max shouldn't be outside what's
* currently there. * currently there.
*/ */
xslack = sc->xmax - cc->geom.width - cc->bwidth * 2; xslack = sc->view.w - cc->geom.w - cc->bwidth * 2;
yslack = sc->ymax - cc->geom.height - cc->bwidth * 2; yslack = sc->view.h - cc->geom.h - cc->bwidth * 2;
if (cc->size->x > 0) if (cc->size->x > 0)
cc->geom.x = MIN(cc->size->x, xslack); cc->geom.x = MIN(cc->size->x, xslack);
if (cc->size->y > 0) if (cc->size->y > 0)
@ -702,28 +685,25 @@ client_placecalc(struct client_ctx *cc)
int xmax, ymax; int xmax, ymax;
xu_ptr_getpos(sc->rootwin, &xmouse, &ymouse); xu_ptr_getpos(sc->rootwin, &xmouse, &ymouse);
if (HasXinerama) { info = screen_find_xinerama(sc, xmouse, ymouse);
info = screen_find_xinerama(sc, xmouse, ymouse); if (info) {
if (info == NULL)
goto noxine;
xorig = info->x_org; xorig = info->x_org;
yorig = info->y_org; yorig = info->y_org;
xmax = xorig + info->width; xmax = xorig + info->width;
ymax = yorig + info->height; ymax = yorig + info->height;
} else { } else {
noxine:
xorig = yorig = 0; xorig = yorig = 0;
xmax = sc->xmax; xmax = sc->view.w;
ymax = sc->ymax; ymax = sc->view.h;
} }
xmouse = MAX(xmouse, xorig) - cc->geom.width / 2; xmouse = MAX(xmouse, xorig) - cc->geom.w / 2;
ymouse = MAX(ymouse, yorig) - cc->geom.height / 2; ymouse = MAX(ymouse, yorig) - cc->geom.h / 2;
xmouse = MAX(xmouse, xorig); xmouse = MAX(xmouse, xorig);
ymouse = MAX(ymouse, yorig); ymouse = MAX(ymouse, yorig);
xslack = xmax - cc->geom.width - cc->bwidth * 2; xslack = xmax - cc->geom.w - cc->bwidth * 2;
yslack = ymax - cc->geom.height - cc->bwidth * 2; yslack = ymax - cc->geom.h - cc->bwidth * 2;
if (xslack >= xorig) { if (xslack >= xorig) {
cc->geom.x = MAX(MIN(xmouse, xslack), cc->geom.x = MAX(MIN(xmouse, xslack),
@ -732,7 +712,7 @@ noxine:
cc->geom.x -= sc->gap.right; cc->geom.x -= sc->gap.right;
} else { } else {
cc->geom.x = xorig + sc->gap.left; cc->geom.x = xorig + sc->gap.left;
cc->geom.width = xmax - sc->gap.left; cc->geom.w = xmax - sc->gap.left;
} }
if (yslack >= yorig) { if (yslack >= yorig) {
cc->geom.y = MAX(MIN(ymouse, yslack), cc->geom.y = MAX(MIN(ymouse, yslack),
@ -741,7 +721,7 @@ noxine:
cc->geom.y -= sc->gap.bottom; cc->geom.y -= sc->gap.bottom;
} else { } else {
cc->geom.y = yorig + sc->gap.top; 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 */ /* temporarily remove base dimensions, ICCCM 4.1.2.3 */
if (!baseismin) { if (!baseismin) {
cc->geom.width -= cc->hint.basew; cc->geom.w -= cc->hint.basew;
cc->geom.height -= cc->hint.baseh; cc->geom.h -= cc->hint.baseh;
} }
/* adjust for aspect limits */ /* adjust for aspect limits */
if (cc->hint.mina > 0 && cc->hint.maxa > 0) { if (cc->hint.mina > 0 && cc->hint.maxa > 0) {
if (cc->hint.maxa < if (cc->hint.maxa <
(float)cc->geom.width / cc->geom.height) (float)cc->geom.w / cc->geom.h)
cc->geom.width = cc->geom.height * cc->hint.maxa; cc->geom.w = cc->geom.h * cc->hint.maxa;
else if (cc->hint.mina < else if (cc->hint.mina <
(float)cc->geom.height / cc->geom.width) (float)cc->geom.h / cc->geom.w)
cc->geom.height = cc->geom.width * cc->hint.mina; cc->geom.h = cc->geom.w * cc->hint.mina;
} }
/* remove base dimensions for increment */ /* remove base dimensions for increment */
if (baseismin) { if (baseismin) {
cc->geom.width -= cc->hint.basew; cc->geom.w -= cc->hint.basew;
cc->geom.height -= cc->hint.baseh; cc->geom.h -= cc->hint.baseh;
} }
/* adjust for increment value */ /* adjust for increment value */
cc->geom.width -= cc->geom.width % cc->hint.incw; cc->geom.w -= cc->geom.w % cc->hint.incw;
cc->geom.height -= cc->geom.height % cc->hint.inch; cc->geom.h -= cc->geom.h % cc->hint.inch;
/* restore base dimensions */ /* restore base dimensions */
cc->geom.width += cc->hint.basew; cc->geom.w += cc->hint.basew;
cc->geom.height += cc->hint.baseh; cc->geom.h += cc->hint.baseh;
/* adjust for min width/height */ /* adjust for min width/height */
cc->geom.width = MAX(cc->geom.width, cc->hint.minw); cc->geom.w = MAX(cc->geom.w, cc->hint.minw);
cc->geom.height = MAX(cc->geom.height, cc->hint.minh); cc->geom.h = MAX(cc->geom.h, cc->hint.minh);
/* adjust for max width/height */ /* adjust for max width/height */
if (cc->hint.maxw) 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) 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 static void
@ -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) &&
@ -903,8 +883,8 @@ client_transient(struct client_ctx *cc)
static int static int
client_inbound(struct client_ctx *cc, int x, int y) client_inbound(struct client_ctx *cc, int x, int y)
{ {
return (x < cc->geom.width && x >= 0 && return (x < cc->geom.w && x >= 0 &&
y < cc->geom.height && y >= 0); y < cc->geom.h && y >= 0);
} }
int int

View File

@ -14,7 +14,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.
.\" .\"
.Dd $Mdocdate: September 8 2011 $ .Dd $Mdocdate: November 6 2011 $
.Dt CWMRC 5 .Dt CWMRC 5
.Os .Os
.Sh NAME .Sh NAME
@ -244,6 +244,10 @@ ignore xclock
bind CM-r label bind CM-r label
bind CS-Return "xterm -e top" bind CS-Return "xterm -e top"
bind 4-o unmap 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-1 grouponly1
bind M-2 grouponly2 bind M-2 grouponly2
bind M-3 grouponly3 bind M-3 grouponly3

58
group.c
View File

@ -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)
@ -480,11 +459,12 @@ group_update_names(struct screen_ctx *sc)
char **strings, *p; char **strings, *p;
unsigned char *prop_ret; unsigned char *prop_ret;
Atom type_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; 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 */
@ -498,7 +478,6 @@ group_update_names(struct screen_ctx *sc)
strings = xmalloc((nstrings < CALMWM_NGROUPS ? CALMWM_NGROUPS : strings = xmalloc((nstrings < CALMWM_NGROUPS ? CALMWM_NGROUPS :
nstrings) * sizeof(*strings)); nstrings) * sizeof(*strings));
i = n = 0;
p = prop_ret; p = prop_ret;
while (n < nstrings) { while (n < nstrings) {
strings[n++] = xstrdup(p); strings[n++] = xstrdup(p);
@ -545,6 +524,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

@ -55,14 +55,13 @@ kbfunc_client_raise(struct client_ctx *cc, union arg *arg)
void void
kbfunc_moveresize(struct client_ctx *cc, union arg *arg) kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
{ {
struct screen_ctx *sc; struct screen_ctx *sc = cc->sc;
int x, y, flags, amt; int x, y, flags, amt;
u_int mx, my; u_int mx, my;
if (cc->flags & CLIENT_FREEZE) if (cc->flags & CLIENT_FREEZE)
return; return;
sc = cc->sc;
mx = my = 0; mx = my = 0;
flags = arg->i; flags = arg->i;
@ -90,22 +89,22 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
switch (flags & TYPEMASK) { switch (flags & TYPEMASK) {
case CWM_MOVE: case CWM_MOVE:
cc->geom.y += my; cc->geom.y += my;
if (cc->geom.y + cc->geom.height < 0) if (cc->geom.y + cc->geom.h < 0)
cc->geom.y = -cc->geom.height; cc->geom.y = -cc->geom.h;
if (cc->geom.y > cc->sc->ymax - 1) if (cc->geom.y > sc->view.h - 1)
cc->geom.y = cc->sc->ymax - 1; cc->geom.y = sc->view.h - 1;
cc->geom.x += mx; cc->geom.x += mx;
if (cc->geom.x + cc->geom.width < 0) if (cc->geom.x + cc->geom.w < 0)
cc->geom.x = -cc->geom.width; cc->geom.x = -cc->geom.w;
if (cc->geom.x > cc->sc->xmax - 1) if (cc->geom.x > sc->view.w - 1)
cc->geom.x = cc->sc->xmax - 1; cc->geom.x = sc->view.w - 1;
cc->geom.x += client_snapcalc(cc->geom.x, 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->bwidth, Conf.snapdist);
cc->geom.y += client_snapcalc(cc->geom.y, cc->geom.y += client_snapcalc(cc->geom.y,
cc->geom.height, cc->sc->ymax, cc->geom.h, sc->view.h,
cc->bwidth, Conf.snapdist); cc->bwidth, Conf.snapdist);
client_move(cc); client_move(cc);
@ -115,18 +114,18 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
client_ptrwarp(cc); client_ptrwarp(cc);
break; break;
case CWM_RESIZE: case CWM_RESIZE:
if ((cc->geom.height += my) < 1) if ((cc->geom.h += my) < 1)
cc->geom.height = 1; cc->geom.h = 1;
if ((cc->geom.width += mx) < 1) if ((cc->geom.w += mx) < 1)
cc->geom.width = 1; cc->geom.w = 1;
client_resize(cc); client_resize(cc);
/* Make sure the pointer stays within the window. */ /* Make sure the pointer stays within the window. */
xu_ptr_getpos(cc->win, &cc->ptr.x, &cc->ptr.y); xu_ptr_getpos(cc->win, &cc->ptr.x, &cc->ptr.y);
if (cc->ptr.x > cc->geom.width) if (cc->ptr.x > cc->geom.w)
cc->ptr.x = cc->geom.width - cc->bwidth; cc->ptr.x = cc->geom.w - cc->bwidth;
if (cc->ptr.y > cc->geom.height) if (cc->ptr.y > cc->geom.h)
cc->ptr.y = cc->geom.height - cc->bwidth; cc->ptr.y = cc->geom.h - cc->bwidth;
client_ptrwarp(cc); client_ptrwarp(cc);
break; break;
case CWM_PTRMOVE: case CWM_PTRMOVE:
@ -141,12 +140,11 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
void void
kbfunc_client_search(struct client_ctx *cc, union arg *arg) 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 client_ctx *old_cc;
struct menu *mi; struct menu *mi;
struct menu_q menuq; struct menu_q menuq;
sc = cc->sc;
old_cc = client_current(); old_cc = client_current();
TAILQ_INIT(&menuq); TAILQ_INIT(&menuq);
@ -178,12 +176,11 @@ kbfunc_client_search(struct client_ctx *cc, union arg *arg)
void void
kbfunc_menu_search(struct client_ctx *cc, union arg *arg) kbfunc_menu_search(struct client_ctx *cc, union arg *arg)
{ {
struct screen_ctx *sc; struct screen_ctx *sc = cc->sc;
struct cmd *cmd; struct cmd *cmd;
struct menu *mi; struct menu *mi;
struct menu_q menuq; struct menu_q menuq;
sc = cc->sc;
TAILQ_INIT(&menuq); TAILQ_INIT(&menuq);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
@ -206,9 +203,7 @@ kbfunc_menu_search(struct client_ctx *cc, union arg *arg)
void void
kbfunc_client_cycle(struct client_ctx *cc, union arg *arg) kbfunc_client_cycle(struct client_ctx *cc, union arg *arg)
{ {
struct screen_ctx *sc; struct screen_ctx *sc = cc->sc;
sc = cc->sc;
/* XXX for X apps that ignore events */ /* XXX for X apps that ignore events */
XGrabKeyboard(X_Dpy, sc->rootwin, True, XGrabKeyboard(X_Dpy, sc->rootwin, True,
@ -245,7 +240,7 @@ void
kbfunc_exec(struct client_ctx *cc, union arg *arg) kbfunc_exec(struct client_ctx *cc, union arg *arg)
{ {
#define NPATHS 256 #define NPATHS 256
struct screen_ctx *sc; struct screen_ctx *sc = cc->sc;
char **ap, *paths[NPATHS], *path, *pathcpy, *label; char **ap, *paths[NPATHS], *path, *pathcpy, *label;
char tpath[MAXPATHLEN]; char tpath[MAXPATHLEN];
DIR *dirp; DIR *dirp;
@ -254,7 +249,6 @@ kbfunc_exec(struct client_ctx *cc, union arg *arg)
struct menu_q menuq; struct menu_q menuq;
int l, i, cmd = arg->i; int l, i, cmd = arg->i;
sc = cc->sc;
switch (cmd) { switch (cmd) {
case CWM_EXEC_PROGRAM: case CWM_EXEC_PROGRAM:
label = "exec"; label = "exec";
@ -333,7 +327,7 @@ out:
void void
kbfunc_ssh(struct client_ctx *cc, union arg *arg) kbfunc_ssh(struct client_ctx *cc, union arg *arg)
{ {
struct screen_ctx *sc; struct screen_ctx *sc = cc->sc;
struct menu *mi; struct menu *mi;
struct menu_q menuq; struct menu_q menuq;
FILE *fp; FILE *fp;
@ -343,8 +337,6 @@ kbfunc_ssh(struct client_ctx *cc, union arg *arg)
int l; int l;
size_t len; size_t len;
sc = cc->sc;
if ((home = getenv("HOME")) == NULL) if ((home = getenv("HOME")) == NULL)
return; return;

4
menu.c
View File

@ -349,8 +349,8 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
ymax = xine->y_org + xine->height; ymax = xine->y_org + xine->height;
} else { } else {
xmin = ymin = 0; xmin = ymin = 0;
xmax = sc->xmax; xmax = sc->view.w;
ymax = sc->ymax; ymax = sc->view.h;
} }
xsave = mc->x; xsave = mc->x;

View File

@ -37,17 +37,17 @@ static void mousefunc_sweep_draw(struct client_ctx *);
static int static int
mousefunc_sweep_calc(struct client_ctx *cc, int x, int y, int mx, int my) 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.w = abs(x - mx) - cc->bwidth;
cc->geom.height = abs(y - my) - cc->bwidth; cc->geom.h = abs(y - my) - cc->bwidth;
client_applysizehints(cc); client_applysizehints(cc);
cc->geom.x = x <= mx ? x : x - cc->geom.width; cc->geom.x = x <= mx ? x : x - cc->geom.w;
cc->geom.y = y <= my ? y : y - cc->geom.height; 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 static void
@ -58,8 +58,8 @@ mousefunc_sweep_draw(struct client_ctx *cc)
int width, width_size, width_name; int width, width_size, width_name;
(void)snprintf(asize, sizeof(asize), "%dx%d", (void)snprintf(asize, sizeof(asize), "%dx%d",
(cc->geom.width - cc->hint.basew) / cc->hint.incw, (cc->geom.w - cc->hint.basew) / cc->hint.incw,
(cc->geom.height - cc->hint.baseh) / cc->hint.inch); (cc->geom.h - cc->hint.baseh) / cc->hint.inch);
width_size = font_width(sc, asize, strlen(asize)) + 4; width_size = font_width(sc, asize, strlen(asize)) + 4;
width_name = font_width(sc, cc->name, strlen(cc->name)) + 4; width_name = font_width(sc, cc->name, strlen(cc->name)) + 4;
width = MAX(width_size, width_name); 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) if (xu_ptr_grab(cc->win, MOUSEMASK, Cursor_resize) < 0)
return; 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); mousefunc_sweep_draw(cc);
for (;;) { for (;;) {
@ -121,10 +121,10 @@ mousefunc_window_resize(struct client_ctx *cc, void *arg)
xu_ptr_ungrab(); xu_ptr_ungrab();
/* Make sure the pointer stays within the window. */ /* Make sure the pointer stays within the window. */
if (cc->ptr.x > cc->geom.width) if (cc->ptr.x > cc->geom.w)
cc->ptr.x = cc->geom.width - cc->bwidth; cc->ptr.x = cc->geom.w - cc->bwidth;
if (cc->ptr.y > cc->geom.height) if (cc->ptr.y > cc->geom.h)
cc->ptr.y = cc->geom.height - cc->bwidth; cc->ptr.y = cc->geom.h - cc->bwidth;
client_ptrwarp(cc); client_ptrwarp(cc);
return; return;
} }
@ -137,6 +137,7 @@ mousefunc_window_move(struct client_ctx *cc, void *arg)
{ {
XEvent ev; XEvent ev;
Time ltime = 0; Time ltime = 0;
struct screen_ctx *sc = cc->sc;
int px, py; int px, py;
client_raise(cc); 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.y = ev.xmotion.y_root - py - cc->bwidth;
cc->geom.x += client_snapcalc(cc->geom.x, 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->bwidth, Conf.snapdist);
cc->geom.y += client_snapcalc(cc->geom.y, cc->geom.y += client_snapcalc(cc->geom.y,
cc->geom.height, cc->sc->ymax, cc->geom.h, sc->view.h,
cc->bwidth, Conf.snapdist); cc->bwidth, Conf.snapdist);
/* don't move more than 60 times / second */ /* don't move more than 60 times / second */
@ -217,13 +218,12 @@ mousefunc_menu_group(struct client_ctx *cc, void *arg)
void void
mousefunc_menu_unhide(struct client_ctx *cc, void *arg) 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 client_ctx *old_cc;
struct menu *mi; struct menu *mi;
struct menu_q menuq; struct menu_q menuq;
char *wname; char *wname;
sc = cc->sc;
old_cc = client_current(); old_cc = client_current();
TAILQ_INIT(&menuq); TAILQ_INIT(&menuq);
@ -261,13 +261,11 @@ mousefunc_menu_unhide(struct client_ctx *cc, void *arg)
void void
mousefunc_menu_cmd(struct client_ctx *cc, void *arg) mousefunc_menu_cmd(struct client_ctx *cc, void *arg)
{ {
struct screen_ctx *sc; struct screen_ctx *sc = cc->sc;
struct menu *mi; struct menu *mi;
struct menu_q menuq; struct menu_q menuq;
struct cmd *cmd; struct cmd *cmd;
sc = cc->sc;
TAILQ_INIT(&menuq); TAILQ_INIT(&menuq);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) { TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
mi = xcalloc(1, sizeof(*mi)); mi = xcalloc(1, sizeof(*mi));

View File

@ -30,6 +30,8 @@
#include "calmwm.h" #include "calmwm.h"
static void screen_init_xinerama(struct screen_ctx *);
struct screen_ctx * struct screen_ctx *
screen_fromroot(Window rootwin) screen_fromroot(Window rootwin)
{ {
@ -65,24 +67,18 @@ screen_updatestackingorder(struct screen_ctx *sc)
XFree(wins); 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 void
screen_init_xinerama(struct screen_ctx *sc) screen_init_xinerama(struct screen_ctx *sc)
{ {
XineramaScreenInfo *info; XineramaScreenInfo *info = NULL;
int no; int no = 0;
if (HasXinerama == 0 || XineramaIsActive(X_Dpy) == 0) { if (XineramaIsActive(X_Dpy))
HasXinerama = 0; info = XineramaQueryScreens(X_Dpy, &no);
sc->xinerama_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 (sc->xinerama != NULL) if (sc->xinerama != NULL)
XFree(sc->xinerama); XFree(sc->xinerama);
@ -99,6 +95,9 @@ screen_find_xinerama(struct screen_ctx *sc, int x, int y)
XineramaScreenInfo *info; XineramaScreenInfo *info;
int i; int i;
if (sc->xinerama == NULL)
return (NULL);
for (i = 0; i < sc->xinerama_no; i++) { for (i = 0; i < sc->xinerama_no; i++) {
info = &sc->xinerama[i]; info = &sc->xinerama[i];
if (x >= info->x_org && x < info->x_org + info->width && 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 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]; sc->view.x = 0;
int i; sc->view.y = 0;
sc->view.w = DisplayWidth(X_Dpy, sc->which);
sc->view.h = DisplayHeight(X_Dpy, sc->which);
sc->xmax = geom[0] = width; sc->work.x = sc->view.x + sc->gap.left;
sc->ymax = geom[1] = height; sc->work.y = sc->view.y + sc->gap.top;
XChangeProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_GEOMETRY, sc->work.w = sc->view.w - (sc->gap.left + sc->gap.right);
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)geom , 2); sc->work.h = sc->view.h - (sc->gap.top + sc->gap.bottom);
/* x, y, width, height. */ screen_init_xinerama(sc);
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, xu_ewmh_net_desktop_geometry(sc);
XA_CARDINAL, 32, PropModeReplace, xu_ewmh_net_workarea(sc);
(unsigned char *)workareas, CALMWM_NGROUPS * 4);
} }

View File

@ -142,9 +142,9 @@ xev_handle_configurerequest(XEvent *ee)
sc = cc->sc; sc = cc->sc;
if (e->value_mask & CWWidth) if (e->value_mask & CWWidth)
cc->geom.width = e->width; cc->geom.w = e->width;
if (e->value_mask & CWHeight) if (e->value_mask & CWHeight)
cc->geom.height = e->height; cc->geom.h = e->height;
if (e->value_mask & CWX) if (e->value_mask & CWX)
cc->geom.x = e->x; cc->geom.x = e->x;
if (e->value_mask & CWY) if (e->value_mask & CWY)
@ -152,16 +152,16 @@ xev_handle_configurerequest(XEvent *ee)
if (e->value_mask & CWBorderWidth) if (e->value_mask & CWBorderWidth)
wc.border_width = e->border_width; 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; 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; cc->geom.y -= cc->bwidth;
wc.x = cc->geom.x; wc.x = cc->geom.x;
wc.y = cc->geom.y; wc.y = cc->geom.y;
wc.width = cc->geom.width; wc.width = cc->geom.w;
wc.height = cc->geom.height; wc.height = cc->geom.h;
wc.border_width = cc->bwidth; wc.border_width = cc->bwidth;
XConfigureWindow(X_Dpy, cc->win, e->value_mask, &wc); XConfigureWindow(X_Dpy, cc->win, e->value_mask, &wc);
@ -208,7 +208,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);
} }
} }
@ -366,8 +366,7 @@ xev_handle_randr(XEvent *ee)
TAILQ_FOREACH(sc, &Screenq, entry) { TAILQ_FOREACH(sc, &Screenq, entry) {
if (sc->which == (u_int)i) { if (sc->which == (u_int)i) {
XRRUpdateConfiguration(ee); XRRUpdateConfiguration(ee);
screen_update_geometry(sc, rev->width, rev->height); screen_update_geometry(sc);
screen_init_xinerama(sc);
} }
} }
} }

210
xutil.c
View File

@ -128,8 +128,8 @@ xu_configure(struct client_ctx *cc)
ce.window = cc->win; ce.window = cc->win;
ce.x = cc->geom.x; ce.x = cc->geom.x;
ce.y = cc->geom.y; ce.y = cc->geom.y;
ce.width = cc->geom.width; ce.width = cc->geom.w;
ce.height = cc->geom.height; ce.height = cc->geom.h;
ce.border_width = cc->bwidth; ce.border_width = cc->bwidth;
ce.above = None; ce.above = None;
ce.override_redirect = 0; ce.override_redirect = 0;
@ -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, cwmh[WM_STATE].atom, 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, cwmh[WM_STATE].atom, 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->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 unsigned long