27 Commits

Author SHA1 Message Date
013497c79c Further simplify Xinerama init and re-init on XRR events.
While testing for Xinerama during setup was done display-wide, each time
XineramaQueryScreens() is called either in start-up or due to an XRR
event, the library re-tests for the Xinerama extension anyway before
moving on; so the initial test is redundant and allows another global to
go away with one other change: always fill in sc->xinerama (and _no),
regardless of the success of malloc in XineramaQueryScreens(), and use
it to see if Xinerama dimensions exist when asked by client and/or menu
code.
2012-07-18 21:53:22 +00:00
3f956098d9 unify various max routines to match client placement and partially menu ones
when calculating screen dimensions.
2012-07-16 01:53:14 +00:00
57af364a21 check value 2012-07-16 01:42:00 +00:00
e42d1c7f01 move the HasXinerama check into screen_find_xinerama and simplify logic;
moves closer to logic in menu code.
2012-07-16 01:36:30 +00:00
0e8815dfb0 re-use geom struct in client_ctx (saved)geometry. 2012-07-13 17:01:04 +00:00
186a78ff1e convert xmax/ymax uses to view geometry. 2012-07-13 15:21:35 +00:00
cc08aef0df introduce screen "view" area and "work" area (gap applied) to simplify
various blocks that require understanding the screen geometry.
2012-07-13 14:18:04 +00:00
2450e309ea fix atom for setting WM_STATE. 2012-07-08 02:55:01 +00:00
6faef40c55 fix atom for retrieving WM_STATE between re-exec's. 2012-07-08 02:50:41 +00:00
c8a17ef536 remove a redundant assignment and another one up. 2012-07-08 01:00:24 +00:00
cb893d0aa9 querying for Xinerama should be done per display, not per screen, so
move chuck to display init; allows some shuffling to occur limiting
screen_init_xinerama()'s scope while keeping order intact.
2012-07-06 14:18:00 +00:00
315f25f7ab Add a couple examples of keybindings using keysyms, as discussed
with okan@ and sthen@.

OK okan@, sthen@
2012-07-06 08:41:29 +00:00
1124ee5cc1 the display's width and height are updated after an XRandR event so we
don't need to pass down the new values to screen_update_geometry(); so
just read the width/height values directly for both uses of
screen_update_geometry().  prep for further changes in this area.
2012-07-05 17:35:13 +00:00
287a5b2aad assign and use screen ctx where appropriate and consistently. 2012-07-04 23:42:03 +00:00
3681b26914 use the screen ctx since we already have it assigned. 2012-07-04 18:07:12 +00:00
8c7964468f fix missing atom (WM_PROTOCOLS) wrt new style handing; without this, the
window manager didn't know if a client supported CLIENT_PROTO_DELETE and
thus used a hammer, XKillClient.

behaviour reported by Tim van der Molen.
2012-07-04 18:00:13 +00:00
f98e123bfc re-implement atom handing; makes for a normalized and more consistent
separation between cwm and ewmh.  seen by a few.
2012-07-03 13:49:03 +00:00
956c47dbeb get rid of more stray lines/spaces 2012-05-16 21:57:21 +00:00
490ef6a7df instead of using the menu window for _NET_SUPPORTING_WM_CHECK, create a
dummy one to use instead; allows us to not have to wait for menu_init(),
so re-shuffle _NET_SUPPORTED slightly.

ok sthen@
2012-05-16 01:17:14 +00:00
b4d582c6ef fix comment 2012-05-16 01:10:11 +00:00
ac82403a51 cycle through other common cycling modifiers; based on a diff from
Alexander Polakov.

ok sthen@
2012-05-16 01:09:17 +00:00
dd5bfdb064 convert from deprecated XKeycodeToKeysym to XkbKeycodeToKeysym
ok sthen@
2012-05-16 01:04:36 +00:00
57766d8606 altpersist->cycling to be more clear that this is for cycling mod
persistence; based on a diff from Alexander Polakov, in preparation for
looping through other potential cycling modifiers.
2012-05-13 15:17:13 +00:00
fb4936d0f7 knf, some from a diff from Tiago Cunha. 2012-05-13 15:15:54 +00:00
63b59e44c1 wrap long lines; from Tiago Cunha. 2012-05-10 00:39:47 +00:00
1d8839e8ad fix section order: move AUTHORS below HISTORY; from Tiago Cunha
ok jmc@
2012-05-09 18:37:39 +00:00
26c391b3dd kill useless .Pp
ok jmc@
2012-05-07 21:25:29 +00:00
19 changed files with 526 additions and 782 deletions

View File

@ -1,47 +1,24 @@
# cwm makefile for BSD make and GNU make
# uses pkg-config, DESTDIR and PREFIX
# $OpenBSD$
.include <bsd.xconf.mk>
PROG= cwm
PREFIX= /usr/local
SRCS= calmwm.c screen.c xmalloc.c client.c menu.c \
search.c util.c xutil.c conf.c xevents.c group.c \
kbfunc.c mousefunc.c font.c parse.y
OBJS= calmwm.o screen.o xmalloc.o client.o menu.o \
search.o util.o xutil.o conf.o xevents.o group.o \
kbfunc.o mousefunc.o font.o strlcpy.o strlcat.o y.tab.o \
strtonum.o fgetln.o
CPPFLAGS+= -I${X11BASE}/include -I${X11BASE}/include/freetype2 -I${.CURDIR}
CPPFLAGS+= `pkg-config --cflags fontconfig x11 xft xinerama xrandr`
CFLAGS+= -Wall
CFLAGS= -Wall -O2 -g
LDADD+= -L${X11BASE}/lib -lXft -lXrender -lX11 -lxcb -lXau -lXdmcp \
-lfontconfig -lexpat -lfreetype -lz -lXinerama -lXrandr -lXext
LDFLAGS+= `pkg-config --libs fontconfig x11 xft xinerama xrandr`
MANDIR= ${X11BASE}/man/man
MAN= cwm.1 cwmrc.5
MANPREFIX= ${PREFIX}/share/man
obj: _xenocara_obj
all: ${PROG}
clean:
rm -rf ${OBJS} ${PROG} y.tab.c
y.tab.c: parse.y
yacc parse.y
${PROG}: ${OBJS} y.tab.o
${CC} ${OBJS} ${LDFLAGS} -o ${PROG}
.c.o:
${CC} -c ${CFLAGS} ${CPPFLAGS} $<
install: ${PROG}
install -d ${DESTDIR}${PREFIX}/bin ${DESTDIR}${MANPREFIX}/man1 ${DESTDIR}${MANPREFIX}/man5
install -m 755 cwm ${DESTDIR}${PREFIX}/bin
install -m 644 cwm.1 ${DESTDIR}${MANPREFIX}/man1
install -m 644 cwmrc.5 ${DESTDIR}${MANPREFIX}/man5
release:
VERSION=$$(git describe --tags | sed 's/^v//;s/-[^.]*$$//') && \
git archive --prefix=cwm-$$VERSION/ -o cwm-$$VERSION.tar.gz HEAD
.include <bsd.prog.mk>
.include <bsd.xorg.mk>

24
README
View File

@ -1,24 +0,0 @@
This is a port of OpenBSD's excellent cwm[0] to Linux and other
Unices.
cwm is a window manager for X11 which contains many features that
concentrate on the efficiency and transparency of window
management. cwm also aims to maintain the simplest and most
pleasant aesthetic.
This port requires pkg-config, Xft, Xinerama and Xrandr. The included
Makefile should work with both GNU make and BSD make.
This version actively tracks changes in the OpenBSD CVS repository.
Releases are roughly coordinated.
The revision controlled version is at https://github.com/chneukirchen/cwm
Releases can be found at http://chneukirchen.org/releases
ChangeLog:
2012-05-02: First public release 5.1 of portable cwm.
--Christian Neukirchen <chneukirchen@gmail.com>
[0]: http://www.openbsd.org/cgi-bin/cvsweb/xenocara/app/cwm/

View File

@ -44,7 +44,7 @@ Cursor Cursor_resize;
struct screen_ctx_q Screenq = TAILQ_HEAD_INITIALIZER(Screenq);
struct client_ctx_q Clientq = TAILQ_HEAD_INITIALIZER(Clientq);
int HasXinerama, HasRandr, Randr_ev;
int HasRandr, Randr_ev;
struct conf Conf;
static void sigchld_cb(int);
@ -157,14 +157,17 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
Window *wins, w0, w1;
XWindowAttributes winattr;
XSetWindowAttributes rootattr;
int fake;
u_int nwins, i;
sc->which = which;
sc->rootwin = RootWindow(X_Dpy, sc->which);
xu_ewmh_net_supported(sc);
xu_ewmh_net_supported_wm_check(sc);
conf_gap(&Conf, sc);
screen_update_geometry(sc, DisplayWidth(X_Dpy, sc->which),
DisplayHeight(X_Dpy, sc->which));
screen_update_geometry(sc);
conf_color(&Conf, sc);
@ -176,8 +179,6 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
/* Initialize menu window. */
menu_init(sc);
xu_setwmname(sc);
rootattr.cursor = Cursor_normal;
rootattr.event_mask = CHILDMASK|PropertyChangeMask|EnterWindowMask|
LeaveWindowMask|ColormapChangeMask|BUTTONMASK;
@ -199,17 +200,8 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
screen_updatestackingorder(sc);
if (XineramaQueryExtension(X_Dpy, &fake, &fake) == 1 &&
((HasXinerama = XineramaIsActive(X_Dpy)) == 1))
HasXinerama = 1;
if (HasRandr)
XRRSelectInput(X_Dpy, sc->rootwin, RRScreenChangeNotifyMask);
/*
* initial setup of xinerama screens, if we're using RandR then we'll
* redo this whenever the screen changes since a CTRC may have been
* added or removed
*/
screen_init_xinerama(sc);
XSync(X_Dpy, False);
}
@ -221,6 +213,7 @@ x_wmerrorhandler(Display *dpy, XErrorEvent *e)
return (0);
}
static int
x_errorhandler(Display *dpy, XErrorEvent *e)
{

115
calmwm.h
View File

@ -21,18 +21,7 @@
#ifndef _CALMWM_H_
#define _CALMWM_H_
/* ugly stuff */
#ifndef TAILQ_END
#define TAILQ_END(head) NULL
#endif
#ifndef __dead
#define __dead
#endif
char *fgetln(FILE *, size_t *);
long long strtonum(const char *, long long, long long, const char **);
size_t strlcpy(char *, const char *, size_t);
size_t strlcat(char *, const char *, size_t);
#include <X11/XKBlib.h>
#include <X11/Xatom.h>
#include <X11/Xft/Xft.h>
#include <X11/Xlib.h>
@ -107,6 +96,13 @@ struct color {
unsigned long pixel;
};
struct geom {
int x;
int y;
int w;
int h;
};
struct gap {
int top;
int bottom;
@ -129,12 +125,7 @@ struct client_ctx {
XSizeHints *size;
Colormap cmap;
u_int bwidth; /* border width */
struct {
int x; /* x position */
int y; /* y position */
int width; /* width */
int height;/* height */
} geom, savegeom;
struct geom geom, savegeom;
struct {
int basew; /* desired width */
int baseh; /* desired height */
@ -214,9 +205,9 @@ struct screen_ctx {
Window menuwin;
struct color color[CWM_COLOR_MAX];
GC gc;
int altpersist;
int xmax;
int ymax;
int cycling;
struct geom view; /* viewable area */
struct geom work; /* workable area, gap-applied */
struct gap gap;
struct cycle_entry_q mruq;
XftColor xftcolor;
@ -318,6 +309,7 @@ __dead void usage(void);
void client_applysizehints(struct client_ctx *);
struct client_ctx *client_current(void);
void client_cycle(struct screen_ctx *, int);
void client_cycle_leave(struct screen_ctx *, struct client_ctx *);
void client_delete(struct client_ctx *);
void client_draw_border(struct client_ctx *);
struct client_ctx *client_find(Window);
@ -370,8 +362,7 @@ void search_print_client(struct menu *, int);
XineramaScreenInfo *screen_find_xinerama(struct screen_ctx *, int, int);
struct screen_ctx *screen_fromroot(Window);
void screen_init_xinerama(struct screen_ctx *);
void screen_update_geometry(struct screen_ctx *, int, int);
void screen_update_geometry(struct screen_ctx *);
void screen_updatestackingorder(struct screen_ctx *);
void kbfunc_client_cycle(struct client_ctx *, union arg *);
@ -473,7 +464,22 @@ void xu_ptr_setpos(Window, int, int);
void xu_ptr_ungrab(void);
void xu_sendmsg(Window, Atom, long);
void xu_setstate(struct client_ctx *, int);
void xu_setwmname(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_desktop_geometry(struct screen_ctx *);
void xu_ewmh_net_workarea(struct screen_ctx *);
void xu_ewmh_net_client_list(struct screen_ctx *);
void xu_ewmh_net_active_window(struct screen_ctx *, Window);
void xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *);
void xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *);
void xu_ewmh_net_showing_desktop(struct screen_ctx *);
void xu_ewmh_net_virtual_roots(struct screen_ctx *);
void xu_ewmh_net_current_desktop(struct screen_ctx *, long);
void xu_ewmh_net_desktop_names(struct screen_ctx *, unsigned char *, int);
void xu_ewmh_net_wm_desktop(struct client_ctx *);
void u_exec(char *);
void u_spawn(char *);
@ -498,34 +504,37 @@ extern struct conf Conf;
extern int HasXinerama, HasRandr, Randr_ev;
#define WM_STATE cwm_atoms[0]
#define WM_DELETE_WINDOW cwm_atoms[1]
#define WM_TAKE_FOCUS cwm_atoms[2]
#define WM_PROTOCOLS cwm_atoms[3]
#define _MOTIF_WM_HINTS cwm_atoms[4]
#define UTF8_STRING cwm_atoms[5]
/*
* please make all hints below this point netwm hints, starting with
* _NET_SUPPORTED. If you change other hints make sure you update
* CWM_NETWM_START
*/
#define _NET_SUPPORTED cwm_atoms[6]
#define _NET_SUPPORTING_WM_CHECK cwm_atoms[7]
#define _NET_WM_NAME cwm_atoms[8]
#define _NET_ACTIVE_WINDOW cwm_atoms[9]
#define _NET_CLIENT_LIST cwm_atoms[10]
#define _NET_NUMBER_OF_DESKTOPS cwm_atoms[11]
#define _NET_CURRENT_DESKTOP cwm_atoms[12]
#define _NET_DESKTOP_VIEWPORT cwm_atoms[13]
#define _NET_DESKTOP_GEOMETRY cwm_atoms[14]
#define _NET_VIRTUAL_ROOTS cwm_atoms[15]
#define _NET_SHOWING_DESKTOP cwm_atoms[16]
#define _NET_DESKTOP_NAMES cwm_atoms[17]
#define _NET_WM_DESKTOP cwm_atoms[18]
#define _NET_WORKAREA cwm_atoms[19]
#define CWM_NO_ATOMS 20
#define CWM_NETWM_START 6
extern Atom cwm_atoms[CWM_NO_ATOMS];
enum {
WM_STATE,
WM_DELETE_WINDOW,
WM_TAKE_FOCUS,
WM_PROTOCOLS,
_MOTIF_WM_HINTS,
UTF8_STRING,
CWMH_NITEMS
};
enum {
_NET_SUPPORTED,
_NET_SUPPORTING_WM_CHECK,
_NET_ACTIVE_WINDOW,
_NET_CLIENT_LIST,
_NET_NUMBER_OF_DESKTOPS,
_NET_CURRENT_DESKTOP,
_NET_DESKTOP_VIEWPORT,
_NET_DESKTOP_GEOMETRY,
_NET_VIRTUAL_ROOTS,
_NET_SHOWING_DESKTOP,
_NET_DESKTOP_NAMES,
_NET_WORKAREA,
_NET_WM_NAME,
_NET_WM_DESKTOP,
EWMH_NITEMS
};
struct atom_ctx {
char *name;
Atom atom;
};
extern struct atom_ctx cwmh[CWMH_NITEMS];
extern struct atom_ctx ewmh[EWMH_NITEMS];
#endif /* _CALMWM_H_ */

252
client.c
View File

@ -89,8 +89,8 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
XGetWindowAttributes(X_Dpy, cc->win, &wattr);
cc->geom.x = wattr.x;
cc->geom.y = wattr.y;
cc->geom.width = wattr.width;
cc->geom.height = wattr.height;
cc->geom.w = wattr.width;
cc->geom.h = wattr.height;
cc->cmap = wattr.colormap;
if (wattr.map_state != IsViewable) {
@ -126,9 +126,8 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
TAILQ_INSERT_TAIL(&sc->mruq, cc, mru_entry);
TAILQ_INSERT_TAIL(&Clientq, cc, entry);
/* append to the client list */
XChangeProperty(X_Dpy, sc->rootwin, _NET_CLIENT_LIST, XA_WINDOW, 32,
PropModeAppend, (unsigned char *)&cc->win, 1);
xu_ewmh_net_client_list(sc);
client_gethints(cc);
client_update(cc);
@ -143,10 +142,7 @@ void
client_delete(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct client_ctx *tcc;
struct winname *wn;
Window *winlist;
int i, j;
group_client_delete(cc);
@ -159,23 +155,8 @@ client_delete(struct client_ctx *cc)
TAILQ_REMOVE(&sc->mruq, cc, mru_entry);
TAILQ_REMOVE(&Clientq, cc, entry);
/*
* Sadly we can't remove just one entry from a property, so we must
* redo the whole thing from scratch. this is the stupid way, the other
* way incurs many roundtrips to the server.
*/
i = j = 0;
TAILQ_FOREACH(tcc, &Clientq, entry)
i++;
if (i > 0) {
winlist = xmalloc(i * sizeof(*winlist));
TAILQ_FOREACH(tcc, &Clientq, entry)
winlist[j++] = tcc->win;
XChangeProperty(X_Dpy, sc->rootwin, _NET_CLIENT_LIST,
XA_WINDOW, 32, PropModeReplace,
(unsigned char *)winlist, i);
xfree(winlist);
}
xu_ewmh_net_client_list(sc);
if (_curcc == cc)
client_none(sc);
@ -228,7 +209,7 @@ client_setactive(struct client_ctx *cc, int fg)
* If we're in the middle of alt-tabbing, don't change
* the order please.
*/
if (!sc->altpersist)
if (!sc->cycling)
client_mtf(cc);
} else
client_leave(cc);
@ -236,9 +217,7 @@ client_setactive(struct client_ctx *cc, int fg)
if (fg && _curcc != cc) {
client_setactive(NULL, 0);
_curcc = cc;
XChangeProperty(X_Dpy, sc->rootwin, _NET_ACTIVE_WINDOW,
XA_WINDOW, 32, PropModeReplace,
(unsigned char *)&cc->win, 1);
xu_ewmh_net_active_window(sc, cc->win);
}
cc->active = fg;
@ -253,8 +232,8 @@ client_none(struct screen_ctx *sc)
{
Window none = None;
XChangeProperty(X_Dpy, sc->rootwin, _NET_ACTIVE_WINDOW,
XA_WINDOW, 32, PropModeReplace, (unsigned char *)&none, 1);
xu_ewmh_net_active_window(sc, none);
_curcc = NULL;
}
@ -277,8 +256,8 @@ void
client_maximize(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
int xmax = sc->xmax, ymax = sc->ymax;
int x_org = 0, y_org = 0;
int x_org, y_org, xmax, ymax;
XineramaScreenInfo *xine;
if (cc->flags & CLIENT_FREEZE)
return;
@ -291,37 +270,38 @@ client_maximize(struct client_ctx *cc)
}
if ((cc->flags & CLIENT_VMAXIMIZED) == 0) {
cc->savegeom.height = cc->geom.height;
cc->savegeom.h = cc->geom.h;
cc->savegeom.y = cc->geom.y;
}
if ((cc->flags & CLIENT_HMAXIMIZED) == 0) {
cc->savegeom.width = cc->geom.width;
cc->savegeom.w = cc->geom.w;
cc->savegeom.x = cc->geom.x;
}
if (HasXinerama) {
XineramaScreenInfo *xine;
/*
* pick screen that the middle of the window is on.
* that's probably more fair than if just the origin of
* a window is poking over a boundary
*/
xine = screen_find_xinerama(sc,
cc->geom.x + cc->geom.width / 2,
cc->geom.y + cc->geom.height / 2);
if (xine == NULL)
goto calc;
/*
* pick screen that the middle of the window is on.
* that's probably more fair than if just the origin of
* a window is poking over a boundary
*/
xine = screen_find_xinerama(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2);
if (xine) {
x_org = xine->x_org;
y_org = xine->y_org;
xmax = xine->width;
ymax = xine->height;
} else {
x_org = y_org = 0;
xmax = sc->view.w;
ymax = sc->view.h;
}
calc:
cc->geom.x = x_org + sc->gap.left;
cc->geom.y = y_org + sc->gap.top;
cc->geom.height = ymax - (sc->gap.top + sc->gap.bottom);
cc->geom.width = xmax - (sc->gap.left + sc->gap.right);
cc->geom.h = ymax - (sc->gap.top + sc->gap.bottom);
cc->geom.w = xmax - (sc->gap.left + sc->gap.right);
cc->bwidth = 0;
cc->flags |= CLIENT_MAXIMIZED;
@ -333,43 +313,44 @@ void
client_vertmaximize(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
int y_org = 0, ymax = sc->ymax;
int y_org, ymax;
XineramaScreenInfo *xine;
if (cc->flags & CLIENT_FREEZE)
return;
if (cc->flags & CLIENT_VMAXIMIZED) {
cc->geom.y = cc->savegeom.y;
cc->geom.height = cc->savegeom.height;
cc->geom.h = cc->savegeom.h;
cc->bwidth = Conf.bwidth;
if (cc->flags & CLIENT_HMAXIMIZED)
cc->geom.width -= cc->bwidth * 2;
cc->geom.w -= cc->bwidth * 2;
cc->flags &= ~CLIENT_VMAXIMIZED;
goto resize;
}
cc->savegeom.y = cc->geom.y;
cc->savegeom.height = cc->geom.height;
cc->savegeom.h = cc->geom.h;
/* if this will make us fully maximized then remove boundary */
if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_HMAXIMIZED) {
cc->geom.width += Conf.bwidth * 2;
cc->geom.w += Conf.bwidth * 2;
cc->bwidth = 0;
}
if (HasXinerama) {
XineramaScreenInfo *xine;
xine = screen_find_xinerama(sc,
cc->geom.x + cc->geom.width / 2,
cc->geom.y + cc->geom.height / 2);
if (xine == NULL)
goto calc;
xine = screen_find_xinerama(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2);
if (xine) {
y_org = xine->y_org;
ymax = xine->height;
} else {
y_org = 0;
ymax = sc->view.h;
}
calc:
cc->geom.y = y_org + sc->gap.top;
cc->geom.height = ymax - (cc->bwidth * 2) - (sc->gap.top +
cc->geom.h = ymax - (cc->bwidth * 2) - (sc->gap.top +
sc->gap.bottom);
cc->flags |= CLIENT_VMAXIMIZED;
@ -381,43 +362,44 @@ void
client_horizmaximize(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
int x_org = 0, xmax = sc->xmax;
int x_org, xmax;
XineramaScreenInfo *xine;
if (cc->flags & CLIENT_FREEZE)
return;
if (cc->flags & CLIENT_HMAXIMIZED) {
cc->geom.x = cc->savegeom.x;
cc->geom.width = cc->savegeom.width;
cc->geom.w = cc->savegeom.w;
cc->bwidth = Conf.bwidth;
if (cc->flags & CLIENT_VMAXIMIZED)
cc->geom.height -= cc->bwidth * 2;
cc->geom.h -= cc->bwidth * 2;
cc->flags &= ~CLIENT_HMAXIMIZED;
goto resize;
}
}
cc->savegeom.x = cc->geom.x;
cc->savegeom.width = cc->geom.width;
cc->savegeom.w = cc->geom.w;
/* if this will make us fully maximized then remove boundary */
if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_VMAXIMIZED) {
cc->geom.height += cc->bwidth * 2;
cc->geom.h += cc->bwidth * 2;
cc->bwidth = 0;
}
if (HasXinerama) {
XineramaScreenInfo *xine;
xine = screen_find_xinerama(sc,
cc->geom.x + cc->geom.width / 2,
cc->geom.y + cc->geom.height / 2);
if (xine == NULL)
goto calc;
xine = screen_find_xinerama(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2);
if (xine) {
x_org = xine->x_org;
xmax = xine->width;
} else {
x_org = 0;
xmax = sc->view.w;
}
calc:
cc->geom.x = x_org + sc->gap.left;
cc->geom.width = xmax - (cc->bwidth * 2) - (sc->gap.left +
cc->geom.w = xmax - (cc->bwidth * 2) - (sc->gap.left +
sc->gap.right);
cc->flags |= CLIENT_HMAXIMIZED;
@ -431,7 +413,7 @@ client_resize(struct client_ctx *cc)
client_draw_border(cc);
XMoveResizeWindow(X_Dpy, cc->win, cc->geom.x,
cc->geom.y, cc->geom.width, cc->geom.height);
cc->geom.y, cc->geom.w, cc->geom.h);
xu_configure(cc);
}
@ -460,8 +442,8 @@ client_ptrwarp(struct client_ctx *cc)
int x = cc->ptr.x, y = cc->ptr.y;
if (x == -1 || y == -1) {
x = cc->geom.width / 2;
y = cc->geom.height / 2;
x = cc->geom.w / 2;
y = cc->geom.h / 2;
}
(cc->state == IconicState) ? client_unhide(cc) : client_raise(cc);
@ -540,14 +522,14 @@ client_update(struct client_ctx *cc)
int i;
long n;
if ((n = xu_getprop(cc->win, WM_PROTOCOLS,
if ((n = xu_getprop(cc->win, cwmh[WM_PROTOCOLS].atom,
XA_ATOM, 20L, (u_char **)&p)) <= 0)
return;
for (i = 0; i < n; i++)
if (p[i] == WM_DELETE_WINDOW)
if (p[i] == cwmh[WM_DELETE_WINDOW].atom)
cc->xproto |= CLIENT_PROTO_DELETE;
else if (p[i] == WM_TAKE_FOCUS)
else if (p[i] == cwmh[WM_TAKE_FOCUS].atom)
cc->xproto |= CLIENT_PROTO_TAKEFOCUS;
XFree(p);
@ -557,7 +539,8 @@ void
client_send_delete(struct client_ctx *cc)
{
if (cc->xproto & CLIENT_PROTO_DELETE)
xu_sendmsg(cc->win, WM_PROTOCOLS, WM_DELETE_WINDOW);
xu_sendmsg(cc->win,
cwmh[WM_PROTOCOLS].atom, cwmh[WM_DELETE_WINDOW].atom);
else
XKillClient(X_Dpy, cc->win);
}
@ -568,7 +551,7 @@ client_setname(struct client_ctx *cc)
struct winname *wn;
char *newname;
if (!xu_getstrprop(cc->win, _NET_WM_NAME, &newname))
if (!xu_getstrprop(cc->win, ewmh[_NET_WM_NAME].atom, &newname))
if (!xu_getstrprop(cc->win, XA_WM_NAME, &newname))
newname = emptystring;
@ -613,7 +596,8 @@ client_cycle(struct screen_ctx *sc, int flags)
return;
if (oldcc == NULL)
oldcc = (flags & CWM_RCYCLE ? TAILQ_LAST(&sc->mruq, cycle_entry_q) :
oldcc = (flags & CWM_RCYCLE ?
TAILQ_LAST(&sc->mruq, cycle_entry_q) :
TAILQ_FIRST(&sc->mruq));
newcc = oldcc;
@ -637,12 +621,24 @@ client_cycle(struct screen_ctx *sc, int flags)
}
}
/* reset when alt is released. XXX I hate this hack */
sc->altpersist = 1;
/* reset when cycling mod is released. XXX I hate this hack */
sc->cycling = 1;
client_ptrsave(oldcc);
client_ptrwarp(newcc);
}
void
client_cycle_leave(struct screen_ctx *sc, struct client_ctx *cc)
{
sc->cycling = 0;
client_mtf(NULL);
if (cc) {
group_sticky_toggle_exit(cc);
XUngrabKeyboard(X_Dpy, CurrentTime);
}
}
static struct client_ctx *
client_mrunext(struct client_ctx *cc)
{
@ -677,8 +673,8 @@ client_placecalc(struct client_ctx *cc)
* XRandR bits mean that {x,y}max shouldn't be outside what's
* currently there.
*/
xslack = sc->xmax - cc->geom.width - cc->bwidth * 2;
yslack = sc->ymax - cc->geom.height - cc->bwidth * 2;
xslack = sc->view.w - cc->geom.w - cc->bwidth * 2;
yslack = sc->view.h - cc->geom.h - cc->bwidth * 2;
if (cc->size->x > 0)
cc->geom.x = MIN(cc->size->x, xslack);
if (cc->size->y > 0)
@ -689,28 +685,25 @@ client_placecalc(struct client_ctx *cc)
int xmax, ymax;
xu_ptr_getpos(sc->rootwin, &xmouse, &ymouse);
if (HasXinerama) {
info = screen_find_xinerama(sc, xmouse, ymouse);
if (info == NULL)
goto noxine;
info = screen_find_xinerama(sc, xmouse, ymouse);
if (info) {
xorig = info->x_org;
yorig = info->y_org;
xmax = xorig + info->width;
ymax = yorig + info->height;
} else {
noxine:
xorig = yorig = 0;
xmax = sc->xmax;
ymax = sc->ymax;
xmax = sc->view.w;
ymax = sc->view.h;
}
xmouse = MAX(xmouse, xorig) - cc->geom.width / 2;
ymouse = MAX(ymouse, yorig) - cc->geom.height / 2;
xmouse = MAX(xmouse, xorig) - cc->geom.w / 2;
ymouse = MAX(ymouse, yorig) - cc->geom.h / 2;
xmouse = MAX(xmouse, xorig);
ymouse = MAX(ymouse, yorig);
xslack = xmax - cc->geom.width - cc->bwidth * 2;
yslack = ymax - cc->geom.height - cc->bwidth * 2;
xslack = xmax - cc->geom.w - cc->bwidth * 2;
yslack = ymax - cc->geom.h - cc->bwidth * 2;
if (xslack >= xorig) {
cc->geom.x = MAX(MIN(xmouse, xslack),
@ -719,7 +712,7 @@ noxine:
cc->geom.x -= sc->gap.right;
} else {
cc->geom.x = xorig + sc->gap.left;
cc->geom.width = xmax - sc->gap.left;
cc->geom.w = xmax - sc->gap.left;
}
if (yslack >= yorig) {
cc->geom.y = MAX(MIN(ymouse, yslack),
@ -728,7 +721,7 @@ noxine:
cc->geom.y -= sc->gap.bottom;
} else {
cc->geom.y = yorig + sc->gap.top;
cc->geom.height = ymax - sc->gap.top;
cc->geom.h = ymax - sc->gap.top;
}
}
}
@ -792,6 +785,7 @@ client_getsizehints(struct client_ctx *cc)
cc->size->max_aspect.y;
}
}
void
client_applysizehints(struct client_ctx *cc)
{
@ -802,43 +796,43 @@ client_applysizehints(struct client_ctx *cc)
/* temporarily remove base dimensions, ICCCM 4.1.2.3 */
if (!baseismin) {
cc->geom.width -= cc->hint.basew;
cc->geom.height -= cc->hint.baseh;
cc->geom.w -= cc->hint.basew;
cc->geom.h -= cc->hint.baseh;
}
/* adjust for aspect limits */
if (cc->hint.mina > 0 && cc->hint.maxa > 0) {
if (cc->hint.maxa <
(float)cc->geom.width / cc->geom.height)
cc->geom.width = cc->geom.height * cc->hint.maxa;
(float)cc->geom.w / cc->geom.h)
cc->geom.w = cc->geom.h * cc->hint.maxa;
else if (cc->hint.mina <
(float)cc->geom.height / cc->geom.width)
cc->geom.height = cc->geom.width * cc->hint.mina;
(float)cc->geom.h / cc->geom.w)
cc->geom.h = cc->geom.w * cc->hint.mina;
}
/* remove base dimensions for increment */
if (baseismin) {
cc->geom.width -= cc->hint.basew;
cc->geom.height -= cc->hint.baseh;
cc->geom.w -= cc->hint.basew;
cc->geom.h -= cc->hint.baseh;
}
/* adjust for increment value */
cc->geom.width -= cc->geom.width % cc->hint.incw;
cc->geom.height -= cc->geom.height % cc->hint.inch;
cc->geom.w -= cc->geom.w % cc->hint.incw;
cc->geom.h -= cc->geom.h % cc->hint.inch;
/* restore base dimensions */
cc->geom.width += cc->hint.basew;
cc->geom.height += cc->hint.baseh;
cc->geom.w += cc->hint.basew;
cc->geom.h += cc->hint.baseh;
/* adjust for min width/height */
cc->geom.width = MAX(cc->geom.width, cc->hint.minw);
cc->geom.height = MAX(cc->geom.height, cc->hint.minh);
cc->geom.w = MAX(cc->geom.w, cc->hint.minw);
cc->geom.h = MAX(cc->geom.h, cc->hint.minh);
/* adjust for max width/height */
if (cc->hint.maxw)
cc->geom.width = MIN(cc->geom.width, cc->hint.maxw);
cc->geom.w = MIN(cc->geom.w, cc->hint.maxw);
if (cc->hint.maxh)
cc->geom.height = MIN(cc->geom.height, cc->hint.maxh);
cc->geom.h = MIN(cc->geom.h, cc->hint.maxh);
}
static void
@ -854,7 +848,7 @@ client_gethints(struct client_ctx *cc)
cc->app_class = xch.res_class;
}
if (xu_getprop(cc->win, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS,
if (xu_getprop(cc->win, cwmh[_MOTIF_WM_HINTS].atom, _MOTIF_WM_HINTS,
PROP_MWM_HINTS_ELEMENTS, (u_char **)&mwmh) == MWM_NUMHINTS)
if (mwmh->flags & MWM_HINTS_DECORATIONS &&
!(mwmh->decorations & MWM_DECOR_ALL) &&
@ -889,8 +883,8 @@ client_transient(struct client_ctx *cc)
static int
client_inbound(struct client_ctx *cc, int x, int y)
{
return (x < cc->geom.width && x >= 0 &&
y < cc->geom.height && y >= 0);
return (x < cc->geom.w && x >= 0 &&
y < cc->geom.h && y >= 0);
}
int
@ -911,13 +905,13 @@ client_snapcalc(int n, int dn, int nmax, int bwidth, int snapdist)
/* possible to snap in both directions */
if (s0 != 0 && s1 != 0)
if (abs(s0) < abs(s1))
return s0;
return (s0);
else
return s1;
return (s1);
else if (s0 != 0)
return s0;
return (s0);
else if (s1 != 0)
return s1;
return (s1);
else
return 0;
return (0);
}

8
conf.c
View File

@ -361,8 +361,10 @@ static struct {
{ "nogroup", kbfunc_client_nogroup, 0, {0} },
{ "cyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_CYCLE} },
{ "rcyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_RCYCLE} },
{ "cycleingroup", kbfunc_client_cycle, KBFLAG_NEEDCLIENT, {.i = CWM_CYCLE|CWM_INGROUP} },
{ "rcycleingroup", kbfunc_client_cycle, KBFLAG_NEEDCLIENT, {.i = CWM_RCYCLE|CWM_INGROUP} },
{ "cycleingroup", kbfunc_client_cycle, KBFLAG_NEEDCLIENT,
{.i = CWM_CYCLE|CWM_INGROUP} },
{ "rcycleingroup", kbfunc_client_cycle, KBFLAG_NEEDCLIENT,
{.i = CWM_RCYCLE|CWM_INGROUP} },
{ "grouptoggle", kbfunc_client_grouptoggle, KBFLAG_NEEDCLIENT, {0}},
{ "maximize", kbfunc_client_maximize, KBFLAG_NEEDCLIENT, {0} },
{ "vmaximize", kbfunc_client_vmaximize, KBFLAG_NEEDCLIENT, {0} },
@ -640,7 +642,7 @@ conf_grab_mouse(struct client_ctx *cc)
TAILQ_FOREACH(mb, &Conf.mousebindingq, entry) {
if (mb->context != MOUSEBIND_CTX_WIN)
continue;
continue;
switch(mb->button) {
case 1:

25
cwm.1
View File

@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 25 2010 $
.Dd $Mdocdate: May 7 2012 $
.Dt CWM 1
.Os
.Sh NAME
@ -258,18 +258,6 @@ option is given.
.El
.Sh SEE ALSO
.Xr cwmrc 5
.Sh AUTHORS
.An -nosplit
.Pp
.Nm
was developed by
.An Marius Aamodt Eriksen Aq marius@monkey.org
with contributions from
.An Andy Adamson Aq dros@monkey.org ,
.An Niels Provos Aq provos@monkey.org ,
and
.An Antti Nyk\(:anen Aq aon@iki.fi .
Ideas, discussion with many others.
.Sh HISTORY
.Nm
was originally inspired by evilwm, but was rewritten from scratch
@ -280,3 +268,14 @@ has since been removed or rewritten.
.Nm
first appeared in
.Ox 4.2 .
.Sh AUTHORS
.An -nosplit
.Nm
was developed by
.An Marius Aamodt Eriksen Aq marius@monkey.org
with contributions from
.An Andy Adamson Aq dros@monkey.org ,
.An Niels Provos Aq provos@monkey.org ,
and
.An Antti Nyk\(:anen Aq aon@iki.fi .
Ideas, discussion with many others.

View File

@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: September 8 2011 $
.Dd $Mdocdate: November 6 2011 $
.Dt CWMRC 5
.Os
.Sh NAME
@ -244,6 +244,10 @@ ignore xclock
bind CM-r label
bind CS-Return "xterm -e top"
bind 4-o unmap
bind CM-equal unmap
bind CMS-equal unmap
bind C4-equal vmaximize
bind C4S-equal hmaximize
bind M-1 grouponly1
bind M-2 grouponly2
bind M-3 grouponly3

106
fgetln.c
View File

@ -1,106 +0,0 @@
/* $NetBSD: fgetln.c,v 1.9 2008/04/29 06:53:03 martin Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Christos Zoulas.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_NBTOOL_CONFIG_H
#include "nbtool_config.h"
#endif
#if !HAVE_FGETLN
#include <stdlib.h>
#ifndef HAVE_NBTOOL_CONFIG_H
/* These headers are required, but included from nbtool_config.h */
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#endif
char *
fgetln(FILE *fp, size_t *len)
{
static char *buf = NULL;
static size_t bufsiz = 0;
char *ptr;
if (buf == NULL) {
bufsiz = BUFSIZ;
if ((buf = malloc(bufsiz)) == NULL)
return NULL;
}
if (fgets(buf, bufsiz, fp) == NULL)
return NULL;
*len = 0;
while ((ptr = strchr(&buf[*len], '\n')) == NULL) {
size_t nbufsiz = bufsiz + BUFSIZ;
char *nbuf = realloc(buf, nbufsiz);
if (nbuf == NULL) {
int oerrno = errno;
free(buf);
errno = oerrno;
buf = NULL;
return NULL;
} else
buf = nbuf;
if (fgets(&buf[bufsiz], BUFSIZ, fp) == NULL) {
buf[bufsiz] = '\0';
*len = strlen(buf);
return buf;
}
*len = bufsiz;
bufsiz = nbufsiz;
}
*len = (ptr - buf) + 1;
return buf;
}
#endif
#ifdef TEST
int
main(int argc, char *argv[])
{
char *p;
size_t len;
while ((p = fgetln(stdin, &len)) != NULL) {
(void)printf("%zu %s", len, p);
free(p);
}
return 0;
}
#endif

67
group.c
View File

@ -48,38 +48,31 @@ const char *shortcut_to_name[] = {
static void
group_add(struct group_ctx *gc, struct client_ctx *cc)
{
long no;
if (cc == NULL || gc == NULL)
errx(1, "group_add: a ctx is NULL");
no = gc->shortcut - 1;
if (cc->group == gc)
return;
if (cc->group != NULL)
TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
XChangeProperty(X_Dpy, cc->win, _NET_WM_DESKTOP, XA_CARDINAL,
32, PropModeReplace, (unsigned char *)&no, 1);
TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry);
cc->group = gc;
xu_ewmh_net_wm_desktop(cc);
}
static void
group_remove(struct client_ctx *cc)
{
long no = 0xffffffff;
if (cc == NULL || cc->group == NULL)
errx(1, "group_remove: a ctx is NULL");
XChangeProperty(X_Dpy, cc->win, _NET_WM_DESKTOP, XA_CARDINAL,
32, PropModeReplace, (unsigned char *)&no, 1);
TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
cc->group = NULL;
xu_ewmh_net_wm_desktop(cc);
}
static void
@ -146,13 +139,12 @@ void
group_init(struct screen_ctx *sc)
{
int i;
long viewports[2] = {0, 0};
long ndesks = CALMWM_NGROUPS, zero = 0;
TAILQ_INIT(&sc->groupq);
sc->group_hideall = 0;
/* see if any group names have already been set and update the property
* with ours if they'll have changed.
/*
* See if any group names have already been set and update the
* property with ours if they'll have changed.
*/
group_update_names(sc);
@ -163,23 +155,11 @@ group_init(struct screen_ctx *sc)
TAILQ_INSERT_TAIL(&sc->groupq, &sc->groups[i], entry);
}
/* we don't support large desktops, so this is always (0, 0) */
XChangeProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_VIEWPORT,
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)viewports, 2);
XChangeProperty(X_Dpy, sc->rootwin, _NET_NUMBER_OF_DESKTOPS,
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&ndesks, 1);
/*
* we don't use virtual roots, so make sure it's not there from a
* previous wm.
*/
XDeleteProperty(X_Dpy, sc->rootwin, _NET_VIRTUAL_ROOTS);
/*
* We don't really have a ``showing desktop'' mode, so this is zero
* always. XXX Note that when we hide all groups, or when all groups
* are hidden we could technically set this later on.
*/
XChangeProperty(X_Dpy, sc->rootwin, _NET_SHOWING_DESKTOP,
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&zero, 1);
xu_ewmh_net_wm_desktop_viewport(sc);
xu_ewmh_net_wm_number_of_desktops(sc);
xu_ewmh_net_showing_desktop(sc);
xu_ewmh_net_virtual_roots(sc);
group_setactive(sc, 0);
}
@ -208,8 +188,8 @@ static void
group_setactive(struct screen_ctx *sc, long idx)
{
sc->group_active = &sc->groups[idx];
XChangeProperty(X_Dpy, sc->rootwin, _NET_CURRENT_DESKTOP,
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&idx, 1);
xu_ewmh_net_current_desktop(sc, idx);
}
void
@ -438,8 +418,8 @@ group_autogroup(struct client_ctx *cc)
if (cc->app_class == NULL || cc->app_name == NULL)
return;
if (xu_getprop(cc->win, _NET_WM_DESKTOP, XA_CARDINAL,
1, (unsigned char **)&grpno) > 0) {
if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP].atom,
XA_CARDINAL, 1, (unsigned char **)&grpno) > 0) {
if (*grpno == 0xffffffff)
no = 0;
else if (*grpno > CALMWM_NGROUPS || *grpno < 0)
@ -479,11 +459,12 @@ group_update_names(struct screen_ctx *sc)
char **strings, *p;
unsigned char *prop_ret;
Atom type_ret;
int format_ret, i = 0, nstrings = 0, n, setnames = 0;
int format_ret, i = 0, nstrings = 0, n = 0, setnames = 0;
unsigned long bytes_after, num_ret;
if (XGetWindowProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_NAMES, 0,
0xffffff, False, UTF8_STRING, &type_ret, &format_ret,
if (XGetWindowProperty(X_Dpy, sc->rootwin,
ewmh[_NET_DESKTOP_NAMES].atom, 0, 0xffffff, False,
cwmh[UTF8_STRING].atom, &type_ret, &format_ret,
&num_ret, &bytes_after, &prop_ret) == Success &&
prop_ret != NULL && format_ret == 8) {
/* failure, just set defaults */
@ -497,7 +478,6 @@ group_update_names(struct screen_ctx *sc)
strings = xmalloc((nstrings < CALMWM_NGROUPS ? CALMWM_NGROUPS :
nstrings) * sizeof(*strings));
i = n = 0;
p = prop_ret;
while (n < nstrings) {
strings[n++] = xstrdup(p);
@ -543,7 +523,6 @@ group_set_names(struct screen_ctx *sc)
tlen -= slen;
q += slen;
}
XChangeProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_NAMES,
UTF8_STRING, 8, PropModeReplace, p, len);
xu_ewmh_net_desktop_names(sc, p, len);
}

View File

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

6
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;
} else {
xmin = ymin = 0;
xmax = sc->xmax;
ymax = sc->ymax;
xmax = sc->view.w;
ymax = sc->view.h;
}
xsave = mc->x;
@ -466,7 +466,7 @@ menu_keycode(KeyCode kc, u_int state, enum ctltype *ctl, char *chr)
*ctl = CTL_NONE;
*chr = '\0';
ks = XKeycodeToKeysym(X_Dpy, kc, (state & ShiftMask) ? 1 : 0);
ks = XkbKeycodeToKeysym(X_Dpy, kc, 0, (state & ShiftMask) ? 1 : 0);
/* Look for control characters. */
switch (ks) {

View File

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

View File

@ -30,6 +30,8 @@
#include "calmwm.h"
static void screen_init_xinerama(struct screen_ctx *);
struct screen_ctx *
screen_fromroot(Window rootwin)
{
@ -65,24 +67,18 @@ screen_updatestackingorder(struct screen_ctx *sc)
XFree(wins);
}
/*
* If we're using RandR then we'll redo this whenever the screen
* changes since a CTRC may have been added or removed
*/
void
screen_init_xinerama(struct screen_ctx *sc)
{
XineramaScreenInfo *info;
int no;
XineramaScreenInfo *info = NULL;
int no = 0;
if (HasXinerama == 0 || XineramaIsActive(X_Dpy) == 0) {
HasXinerama = 0;
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 (XineramaIsActive(X_Dpy))
info = XineramaQueryScreens(X_Dpy, &no);
if (sc->xinerama != NULL)
XFree(sc->xinerama);
@ -99,6 +95,9 @@ screen_find_xinerama(struct screen_ctx *sc, int x, int y)
XineramaScreenInfo *info;
int i;
if (sc->xinerama == NULL)
return (NULL);
for (i = 0; i < sc->xinerama_no; i++) {
info = &sc->xinerama[i];
if (x >= info->x_org && x < info->x_org + info->width &&
@ -109,25 +108,20 @@ screen_find_xinerama(struct screen_ctx *sc, int x, int y)
}
void
screen_update_geometry(struct screen_ctx *sc, int width, int height)
screen_update_geometry(struct screen_ctx *sc)
{
long geom[2], workareas[CALMWM_NGROUPS][4];
int i;
sc->view.x = 0;
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->ymax = geom[1] = height;
XChangeProperty(X_Dpy, sc->rootwin, _NET_DESKTOP_GEOMETRY,
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)geom , 2);
sc->work.x = sc->view.x + sc->gap.left;
sc->work.y = sc->view.y + sc->gap.top;
sc->work.w = sc->view.w - (sc->gap.left + sc->gap.right);
sc->work.h = sc->view.h - (sc->gap.top + sc->gap.bottom);
/* 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);
}
screen_init_xinerama(sc);
XChangeProperty(X_Dpy, sc->rootwin, _NET_WORKAREA,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)workareas, CALMWM_NGROUPS * 4);
xu_ewmh_net_desktop_geometry(sc);
xu_ewmh_net_workarea(sc);
}

View File

@ -1,61 +0,0 @@
/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* 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.
*/
/* OPENBSD ORIGINAL: lib/libc/string/strlcat.c */
#ifndef HAVE_STRLCAT
#include <sys/types.h>
#include <string.h>
/*
* Appends src to string dst of size siz (unlike strncat, siz is the
* full size of dst, not space left). At most siz-1 characters
* will be copied. Always NUL terminates (unless siz <= strlen(dst)).
* Returns strlen(src) + MIN(siz, strlen(initial dst)).
* If retval >= siz, truncation occurred.
*/
size_t
strlcat(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}
#endif /* !HAVE_STRLCAT */

View File

@ -1,57 +0,0 @@
/* $OpenBSD: strlcpy.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */
/*
* Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
*
* 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.
*/
/* OPENBSD ORIGINAL: lib/libc/string/strlcpy.c */
#ifndef HAVE_STRLCPY
#include <sys/types.h>
#include <string.h>
/*
* Copy src to string dst of size siz. At most siz-1 characters
* will be copied. Always NUL terminates (unless siz == 0).
* Returns strlen(src); if retval >= siz, truncation occurred.
*/
size_t
strlcpy(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
/* Copy as many bytes as will fit */
if (n != 0 && --n != 0) {
do {
if ((*d++ = *s++) == 0)
break;
} while (--n != 0);
}
/* Not enough room in dst, add NUL and traverse rest of src */
if (n == 0) {
if (siz != 0)
*d = '\0'; /* NUL-terminate dst */
while (*s++)
;
}
return(s - src - 1); /* count does not include NUL */
}
#endif /* !HAVE_STRLCPY */

View File

@ -1,70 +0,0 @@
/* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */
/*
* Copyright (c) 2004 Ted Unangst and Todd Miller
* All rights reserved.
*
* 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.
*/
/* OPENBSD ORIGINAL: lib/libc/stdlib/strtonum.c */
#ifndef HAVE_STRTONUM
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#define INVALID 1
#define TOOSMALL 2
#define TOOLARGE 3
long long
strtonum(const char *numstr, long long minval, long long maxval,
const char **errstrp)
{
long long ll = 0;
char *ep;
int error = 0;
struct errval {
const char *errstr;
int err;
} ev[4] = {
{ NULL, 0 },
{ "invalid", EINVAL },
{ "too small", ERANGE },
{ "too large", ERANGE },
};
ev[0].err = errno;
errno = 0;
if (minval > maxval)
error = INVALID;
else {
ll = strtoll(numstr, &ep, 10);
if (numstr == ep || *ep != '\0')
error = INVALID;
else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
error = TOOSMALL;
else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
error = TOOLARGE;
}
if (errstrp != NULL)
*errstrp = ev[error].errstr;
errno = ev[error].err;
if (error)
ll = 0;
return (ll);
}
#endif /* HAVE_STRTONUM */

View File

@ -29,7 +29,6 @@
#include <err.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
@ -71,6 +70,9 @@ void (*xev_handlers[LASTEvent])(XEvent *) = {
[MappingNotify] = xev_handle_mappingnotify,
};
static KeySym modkeys[] = { XK_Alt_L, XK_Alt_R, XK_Super_L, XK_Super_R,
XK_Control_L, XK_Control_R };
static void
xev_handle_maprequest(XEvent *ee)
{
@ -139,9 +141,9 @@ xev_handle_configurerequest(XEvent *ee)
sc = cc->sc;
if (e->value_mask & CWWidth)
cc->geom.width = e->width;
cc->geom.w = e->width;
if (e->value_mask & CWHeight)
cc->geom.height = e->height;
cc->geom.h = e->height;
if (e->value_mask & CWX)
cc->geom.x = e->x;
if (e->value_mask & CWY)
@ -149,16 +151,16 @@ xev_handle_configurerequest(XEvent *ee)
if (e->value_mask & CWBorderWidth)
wc.border_width = e->border_width;
if (cc->geom.x == 0 && cc->geom.width >= sc->xmax)
if (cc->geom.x == 0 && cc->geom.w >= sc->view.w)
cc->geom.x -= cc->bwidth;
if (cc->geom.y == 0 && cc->geom.height >= sc->ymax)
if (cc->geom.y == 0 && cc->geom.h >= sc->view.h)
cc->geom.y -= cc->bwidth;
wc.x = cc->geom.x;
wc.y = cc->geom.y;
wc.width = cc->geom.width;
wc.height = cc->geom.height;
wc.width = cc->geom.w;
wc.height = cc->geom.h;
wc.border_width = cc->bwidth;
XConfigureWindow(X_Dpy, cc->win, e->value_mask, &wc);
@ -204,12 +206,10 @@ xev_handle_propertynotify(XEvent *ee)
if (sc->rootwin == e->window)
goto test;
return;
test:
if (e->atom == _NET_DESKTOP_NAMES)
if (e->atom == ewmh[_NET_DESKTOP_NAMES].atom)
group_update_names(sc);
}
}
static void
@ -279,8 +279,8 @@ xev_handle_keypress(XEvent *ee)
KeySym keysym, skeysym;
int modshift;
keysym = XKeycodeToKeysym(X_Dpy, e->keycode, 0);
skeysym = XKeycodeToKeysym(X_Dpy, e->keycode, 1);
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
skeysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 1);
/* we don't care about caps lock and numlock here */
e->state &= ~(LockMask | Mod2Mask);
@ -315,7 +315,7 @@ xev_handle_keypress(XEvent *ee)
}
/*
* This is only used for the alt suppression detection.
* This is only used for the modifier suppression detection.
*/
static void
xev_handle_keyrelease(XEvent *ee)
@ -323,26 +323,17 @@ xev_handle_keyrelease(XEvent *ee)
XKeyEvent *e = &ee->xkey;
struct screen_ctx *sc;
struct client_ctx *cc;
int keysym;
int i, keysym;
sc = screen_fromroot(e->root);
cc = client_current();
keysym = XKeycodeToKeysym(X_Dpy, e->keycode, 0);
if (keysym != XK_Alt_L && keysym != XK_Alt_R)
return;
sc->altpersist = 0;
/*
* XXX - better interface... xevents should not know about
* how/when to mtf.
*/
client_mtf(NULL);
if (cc != NULL) {
group_sticky_toggle_exit(cc);
XUngrabKeyboard(X_Dpy, CurrentTime);
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
for (i = 0; i < nitems(modkeys); i++) {
if (keysym == modkeys[i]) {
client_cycle_leave(sc, cc);
break;
}
}
}
@ -374,8 +365,7 @@ xev_handle_randr(XEvent *ee)
TAILQ_FOREACH(sc, &Screenq, entry) {
if (sc->which == (u_int)i) {
XRRUpdateConfiguration(ee);
screen_update_geometry(sc, rev->width, rev->height);
screen_init_xinerama(sc);
screen_update_geometry(sc);
}
}
}

238
xutil.c
View File

@ -94,8 +94,8 @@ xu_key_grab(Window win, int mask, int keysym)
int i;
code = XKeysymToKeycode(X_Dpy, keysym);
if ((XKeycodeToKeysym(X_Dpy, code, 0) != keysym) &&
(XKeycodeToKeysym(X_Dpy, code, 1) == keysym))
if ((XkbKeycodeToKeysym(X_Dpy, code, 0, 0) != keysym) &&
(XkbKeycodeToKeysym(X_Dpy, code, 0, 1) == keysym))
mask |= ShiftMask;
for (i = 0; i < nitems(ign_mods); i++)
@ -110,8 +110,8 @@ xu_key_ungrab(Window win, int mask, int keysym)
int i;
code = XKeysymToKeycode(X_Dpy, keysym);
if ((XKeycodeToKeysym(X_Dpy, code, 0) != keysym) &&
(XKeycodeToKeysym(X_Dpy, code, 1) == keysym))
if ((XkbKeycodeToKeysym(X_Dpy, code, 0, 0) != keysym) &&
(XkbKeycodeToKeysym(X_Dpy, code, 0, 1) == keysym))
mask |= ShiftMask;
for (i = 0; i < nitems(ign_mods); i++)
@ -128,8 +128,8 @@ xu_configure(struct client_ctx *cc)
ce.window = cc->win;
ce.x = cc->geom.x;
ce.y = cc->geom.y;
ce.width = cc->geom.width;
ce.height = cc->geom.height;
ce.width = cc->geom.w;
ce.height = cc->geom.h;
ce.border_width = cc->bwidth;
ce.above = None;
ce.override_redirect = 0;
@ -207,7 +207,8 @@ xu_getstate(struct client_ctx *cc, int *state)
{
long *p = NULL;
if (xu_getprop(cc->win, WM_STATE, WM_STATE, 2L, (u_char **)&p) <= 0)
if (xu_getprop(cc->win, cwmh[WM_STATE].atom, cwmh[WM_STATE].atom, 2L,
(u_char **)&p) <= 0)
return (-1);
*state = (int)*p;
@ -225,63 +226,194 @@ xu_setstate(struct client_ctx *cc, int state)
dat[1] = None;
cc->state = state;
XChangeProperty(X_Dpy, cc->win, WM_STATE, WM_STATE, 32,
XChangeProperty(X_Dpy, cc->win,
cwmh[WM_STATE].atom, cwmh[WM_STATE].atom, 32,
PropModeReplace, (unsigned char *)dat, 2);
}
Atom cwm_atoms[CWM_NO_ATOMS];
char *atoms[CWM_NO_ATOMS] = {
"WM_STATE",
"WM_DELETE_WINDOW",
"WM_TAKE_FOCUS",
"WM_PROTOCOLS",
"_MOTIF_WM_HINTS",
"UTF8_STRING",
"_NET_SUPPORTED",
"_NET_SUPPORTING_WM_CHECK",
"_NET_WM_NAME",
"_NET_ACTIVE_WINDOW",
"_NET_CLIENT_LIST",
"_NET_NUMBER_OF_DESKTOPS",
"_NET_CURRENT_DESKTOP",
"_NET_DESKTOP_VIEWPORT",
"_NET_DESKTOP_GEOMETRY",
"_NET_VIRTUAL_ROOTS",
"_NET_SHOWING_DESKTOP",
"_NET_DESKTOP_NAMES",
"_NET_WM_DESKTOP",
"_NET_WORKAREA",
struct atom_ctx cwmh[CWMH_NITEMS] = {
{"WM_STATE", None},
{"WM_DELETE_WINDOW", None},
{"WM_TAKE_FOCUS", None},
{"WM_PROTOCOLS", None},
{"_MOTIF_WM_HINTS", None},
{"UTF8_STRING", None},
};
struct atom_ctx ewmh[EWMH_NITEMS] = {
{"_NET_SUPPORTED", None},
{"_NET_SUPPORTING_WM_CHECK", None},
{"_NET_ACTIVE_WINDOW", None},
{"_NET_CLIENT_LIST", None},
{"_NET_NUMBER_OF_DESKTOPS", None},
{"_NET_CURRENT_DESKTOP", None},
{"_NET_DESKTOP_VIEWPORT", None},
{"_NET_DESKTOP_GEOMETRY", None},
{"_NET_VIRTUAL_ROOTS", None},
{"_NET_SHOWING_DESKTOP", None},
{"_NET_DESKTOP_NAMES", None},
{"_NET_WORKAREA", None},
{"_NET_WM_NAME", None},
{"_NET_WM_DESKTOP", None},
};
void
xu_getatoms(void)
{
XInternAtoms(X_Dpy, atoms, CWM_NO_ATOMS, False, cwm_atoms);
int i;
for (i = 0; i < nitems(cwmh); i++)
cwmh[i].atom = XInternAtom(X_Dpy, cwmh[i].name, False);
for (i = 0; i < nitems(ewmh); i++)
ewmh[i].atom = XInternAtom(X_Dpy, ewmh[i].name, False);
}
/* Root Window Properties */
void
xu_ewmh_net_supported(struct screen_ctx *sc)
{
Atom atom[EWMH_NITEMS];
int i;
for (i = 0; i < nitems(ewmh); i++)
atom[i] = ewmh[i].atom;
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_SUPPORTED].atom,
XA_ATOM, 32, PropModeReplace, (unsigned char *)atom, EWMH_NITEMS);
}
void
xu_setwmname(struct screen_ctx *sc)
xu_ewmh_net_supported_wm_check(struct screen_ctx *sc)
{
/*
* set up the _NET_SUPPORTED hint with all netwm atoms that we
* know about.
Window w;
w = XCreateSimpleWindow(X_Dpy, sc->rootwin, -1, -1, 1, 1, 0, 0, 0);
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_SUPPORTING_WM_CHECK].atom,
XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1);
XChangeProperty(X_Dpy, w, ewmh[_NET_SUPPORTING_WM_CHECK].atom,
XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1);
XChangeProperty(X_Dpy, w, ewmh[_NET_WM_NAME].atom,
XA_WM_NAME, 8, PropModeReplace, WMNAME, strlen(WMNAME));
}
void
xu_ewmh_net_desktop_geometry(struct screen_ctx *sc)
{
long geom[2] = { sc->view.w, sc->view.h };
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_GEOMETRY].atom,
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)geom , 2);
}
void
xu_ewmh_net_workarea(struct screen_ctx *sc)
{
long workareas[CALMWM_NGROUPS][4];
int i;
for (i = 0; i < CALMWM_NGROUPS; i++) {
workareas[i][0] = sc->work.x;
workareas[i][1] = sc->work.y;
workareas[i][2] = sc->work.w;
workareas[i][3] = sc->work.h;
}
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_WORKAREA].atom,
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)workareas,
CALMWM_NGROUPS * 4);
}
void
xu_ewmh_net_client_list(struct screen_ctx *sc)
{
struct client_ctx *cc;
Window *winlist;
int i = 0, j = 0;
TAILQ_FOREACH(cc, &Clientq, entry)
i++;
if (i == 0)
return;
winlist = xmalloc(i * sizeof(*winlist));
TAILQ_FOREACH(cc, &Clientq, entry)
winlist[j++] = cc->win;
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_CLIENT_LIST].atom,
XA_WINDOW, 32, PropModeReplace, (unsigned char *)winlist, i);
xfree(winlist);
}
void
xu_ewmh_net_active_window(struct screen_ctx *sc, Window w)
{
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_ACTIVE_WINDOW].atom,
XA_WINDOW, 32, PropModeReplace, (unsigned char *)&w, 1);
}
void
xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *sc)
{
long viewports[2] = {0, 0};
/* We don't support large desktops, so this is (0, 0). */
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_VIEWPORT].atom,
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)viewports, 2);
}
void
xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *sc)
{
long ndesks = CALMWM_NGROUPS;
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_NUMBER_OF_DESKTOPS].atom,
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&ndesks, 1);
}
void
xu_ewmh_net_showing_desktop(struct screen_ctx *sc)
{
long zero = 0;
/* We don't support `showing desktop' mode, so this is zero.
* Note that when we hide all groups, or when all groups are
* hidden we could technically set this later on.
*/
XChangeProperty(X_Dpy, sc->rootwin, _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));
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
@ -292,10 +424,10 @@ xu_getcolor(struct screen_ctx *sc, char *name)
if (!XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, sc->which),
name, &color, &tmp)) {
warnx("XAllocNamedColor error: '%s'", name);
return 0;
return (0);
}
return color.pixel;
return (color.pixel);
}
void