mirror of
https://github.com/leahneukirchen/cwm.git
synced 2023-08-10 21:13:12 +03:00
Compare commits
77 Commits
OPENBSD_4_
...
OPENBSD_4_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
590eb4f37b | ||
![]() |
f44862be9c | ||
![]() |
b13d592c57 | ||
![]() |
bcc0f73bb6 | ||
![]() |
58d12134b1 | ||
![]() |
18c7d89c98 | ||
![]() |
ee59e4a5a1 | ||
![]() |
055b244bb4 | ||
![]() |
71ad069846 | ||
![]() |
11b4b7fec6 | ||
![]() |
61f841ea58 | ||
![]() |
d7589ca80b | ||
![]() |
3eec3b3802 | ||
![]() |
d1b84c5415 | ||
![]() |
6e9fa7548b | ||
![]() |
8bbc376fd9 | ||
![]() |
2c29a1de65 | ||
![]() |
d2cfeb40b4 | ||
![]() |
382662d003 | ||
![]() |
9be7726606 | ||
![]() |
4d5dc5d9ea | ||
![]() |
5d51c8e0e5 | ||
![]() |
4c10afe2cc | ||
![]() |
eb7803269e | ||
![]() |
6df7cba24e | ||
![]() |
29cdc29c6e | ||
![]() |
3de90d44fc | ||
![]() |
fbb1edf2b3 | ||
![]() |
64f0038db7 | ||
![]() |
4f34392258 | ||
![]() |
655c33c489 | ||
![]() |
cc68490fe1 | ||
![]() |
ea96e92ac8 | ||
![]() |
8a490fc270 | ||
![]() |
8346de997f | ||
![]() |
17ae65adc5 | ||
![]() |
507b65a27f | ||
![]() |
4fe12f528c | ||
![]() |
6ad198022b | ||
![]() |
c750462d13 | ||
![]() |
9203c7e8ca | ||
![]() |
b23cef2e4a | ||
![]() |
01af04a342 | ||
![]() |
7660bf0db0 | ||
![]() |
779177a53d | ||
![]() |
87964e5c7e | ||
![]() |
e239976078 | ||
![]() |
712f3f62c7 | ||
![]() |
e2f3810fe8 | ||
![]() |
1b269199c1 | ||
![]() |
0548673f2f | ||
![]() |
bd4c4d7734 | ||
![]() |
fa87ef4a9e | ||
![]() |
399253a4ff | ||
![]() |
ec8e6052ba | ||
![]() |
5c757cc7f4 | ||
![]() |
49e218cf53 | ||
![]() |
7e110f379b | ||
![]() |
c07123ec78 | ||
![]() |
d1050afb60 | ||
![]() |
dcfae161a2 | ||
![]() |
0aca400461 | ||
![]() |
590169ce24 | ||
![]() |
99afa5091f | ||
![]() |
b47283ab41 | ||
![]() |
b523788c0e | ||
![]() |
ee0ec9a453 | ||
![]() |
d2a54bc115 | ||
![]() |
841c646a2b | ||
![]() |
25af744559 | ||
![]() |
be5dfb4ea4 | ||
![]() |
a0739c6cd4 | ||
![]() |
e2610449d1 | ||
![]() |
2bd5e53c2e | ||
![]() |
60a88f54cc | ||
![]() |
61601991b5 | ||
![]() |
a0082c58a4 |
8
Makefile
8
Makefile
@@ -4,14 +4,16 @@
|
||||
|
||||
PROG= cwm
|
||||
|
||||
SRCS= calmwm.c screen.c xmalloc.c client.c grab.c menu.c \
|
||||
SRCS= calmwm.c screen.c xmalloc.c client.c menu.c \
|
||||
search.c util.c xutil.c conf.c input.c xevents.c group.c \
|
||||
kbfunc.c mousefunc.c font.c parse.y
|
||||
|
||||
CPPFLAGS+= -I${X11BASE}/include -I${X11BASE}/include/freetype2 -I${.CURDIR}
|
||||
|
||||
LDADD+= -L${X11BASE}/lib -lXft -lXrender -lX11 -lXau -lXdmcp -lXext \
|
||||
-lfontconfig -lexpat -lfreetype -lz
|
||||
CFLAGS+= -Wall
|
||||
|
||||
LDADD+= -L${X11BASE}/lib -lXft -lXrender -lX11 -lXau -lXdmcp \
|
||||
-lfontconfig -lexpat -lfreetype -lz -lXinerama -lXrandr -lXext
|
||||
|
||||
MANDIR= ${X11BASE}/man/cat
|
||||
MAN= cwm.1 cwmrc.5
|
||||
|
2
TODO
2
TODO
@@ -16,8 +16,6 @@
|
||||
|
||||
- geographical keyboard navigation (window switching)
|
||||
|
||||
- search should ignore the current window. (not add to match list).
|
||||
|
||||
- make kbd shortcuts/events more general. the ability to associate an
|
||||
event with a mode (i.e. prioritize). gets rid of hacky-ness in
|
||||
groups, etc.
|
||||
|
174
calmwm.c
174
calmwm.c
@@ -31,21 +31,19 @@ Cursor Cursor_question;
|
||||
|
||||
struct screen_ctx_q Screenq;
|
||||
struct screen_ctx *Curscreen;
|
||||
u_int Nscreens;
|
||||
|
||||
struct client_ctx_q Clientq;
|
||||
|
||||
int Doshape, Shape_ev;
|
||||
int HasXinerama, HasRandr, Randr_ev;
|
||||
int Starting;
|
||||
struct conf Conf;
|
||||
|
||||
/* From TWM */
|
||||
#define gray_width 2
|
||||
#define gray_height 2
|
||||
static char gray_bits[] = {0x02, 0x01};
|
||||
|
||||
static void _sigchld_cb(int);
|
||||
static void sigchld_cb(int);
|
||||
static void dpy_init(const char *);
|
||||
static int x_errorhandler(Display *, XErrorEvent *);
|
||||
static void x_setup(void);
|
||||
static void x_setupscreen(struct screen_ctx *, u_int);
|
||||
static void x_teardown(void);
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
@@ -69,46 +67,30 @@ main(int argc, char **argv)
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* Ignore a few signals. */
|
||||
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
|
||||
if (signal(SIGCHLD, sigchld_cb) == SIG_ERR)
|
||||
err(1, "signal");
|
||||
|
||||
if (signal(SIGCHLD, _sigchld_cb) == SIG_ERR)
|
||||
err(1, "signal");
|
||||
|
||||
group_init();
|
||||
|
||||
Starting = 1;
|
||||
dpy_init(display_name);
|
||||
|
||||
screen_init();
|
||||
group_init();
|
||||
client_init();
|
||||
|
||||
bzero(&Conf, sizeof(Conf));
|
||||
conf_setup(&Conf, conf_file);
|
||||
client_setup();
|
||||
xu_getatoms();
|
||||
x_setup();
|
||||
Starting = 0;
|
||||
|
||||
xev_init();
|
||||
XEV_QUICK(NULL, NULL, MapRequest, xev_handle_maprequest, NULL);
|
||||
XEV_QUICK(NULL, NULL, UnmapNotify, xev_handle_unmapnotify, NULL);
|
||||
XEV_QUICK(NULL, NULL, ConfigureRequest,
|
||||
xev_handle_configurerequest, NULL);
|
||||
XEV_QUICK(NULL, NULL, PropertyNotify, xev_handle_propertynotify, NULL);
|
||||
XEV_QUICK(NULL, NULL, EnterNotify, xev_handle_enternotify, NULL);
|
||||
XEV_QUICK(NULL, NULL, LeaveNotify, xev_handle_leavenotify, NULL);
|
||||
XEV_QUICK(NULL, NULL, ButtonPress, xev_handle_buttonpress, NULL);
|
||||
XEV_QUICK(NULL, NULL, ButtonRelease, xev_handle_buttonrelease, NULL);
|
||||
XEV_QUICK(NULL, NULL, KeyPress, xev_handle_keypress, NULL);
|
||||
XEV_QUICK(NULL, NULL, KeyRelease, xev_handle_keyrelease, NULL);
|
||||
XEV_QUICK(NULL, NULL, Expose, xev_handle_expose, NULL);
|
||||
XEV_QUICK(NULL, NULL, DestroyNotify, xev_handle_destroynotify, NULL);
|
||||
XEV_QUICK(NULL, NULL, ClientMessage, xev_handle_clientmessage, NULL);
|
||||
XEV_QUICK(NULL, NULL, MappingNotify, xev_handle_mapping, NULL);
|
||||
|
||||
xev_loop();
|
||||
|
||||
x_teardown();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
dpy_init(const char *dpyname)
|
||||
{
|
||||
int i;
|
||||
@@ -119,21 +101,18 @@ dpy_init(const char *dpyname)
|
||||
|
||||
XSetErrorHandler(x_errorhandler);
|
||||
|
||||
Doshape = XShapeQueryExtension(X_Dpy, &Shape_ev, &i);
|
||||
|
||||
TAILQ_INIT(&Screenq);
|
||||
HasRandr = XRRQueryExtension(X_Dpy, &Randr_ev, &i);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
x_setup(void)
|
||||
{
|
||||
struct screen_ctx *sc;
|
||||
struct keybinding *kb;
|
||||
int i;
|
||||
|
||||
Nscreens = ScreenCount(X_Dpy);
|
||||
for (i = 0; i < (int)Nscreens; i++) {
|
||||
XMALLOC(sc, struct screen_ctx);
|
||||
for (i = 0; i < ScreenCount(X_Dpy); i++) {
|
||||
sc = xcalloc(1, sizeof(*sc));
|
||||
x_setupscreen(sc, i);
|
||||
TAILQ_INSERT_TAIL(&Screenq, sc, entry);
|
||||
}
|
||||
@@ -145,7 +124,6 @@ x_setup(void)
|
||||
TAILQ_FOREACH(kb, &Conf.keybindingq, entry)
|
||||
conf_grab(&Conf, kb);
|
||||
|
||||
|
||||
Cursor_move = XCreateFontCursor(X_Dpy, XC_fleur);
|
||||
Cursor_resize = XCreateFontCursor(X_Dpy, XC_bottom_right_corner);
|
||||
Cursor_select = XCreateFontCursor(X_Dpy, XC_hand1);
|
||||
@@ -153,67 +131,34 @@ x_setup(void)
|
||||
Cursor_question = XCreateFontCursor(X_Dpy, XC_question_arrow);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
x_teardown(void)
|
||||
{
|
||||
struct screen_ctx *sc;
|
||||
|
||||
TAILQ_FOREACH(sc, &Screenq, entry)
|
||||
XFreeGC(X_Dpy, sc->gc);
|
||||
|
||||
XCloseDisplay(X_Dpy);
|
||||
}
|
||||
|
||||
static void
|
||||
x_setupscreen(struct screen_ctx *sc, u_int which)
|
||||
{
|
||||
XColor tmp;
|
||||
XGCValues gv;
|
||||
Window *wins, w0, w1;
|
||||
XWindowAttributes winattr;
|
||||
XSetWindowAttributes rootattr;
|
||||
int fake;
|
||||
u_int nwins, i;
|
||||
|
||||
Curscreen = sc;
|
||||
|
||||
sc->display = x_screenname(which);
|
||||
sc->which = which;
|
||||
sc->rootwin = RootWindow(X_Dpy, which);
|
||||
|
||||
sc->rootwin = RootWindow(X_Dpy, sc->which);
|
||||
sc->xmax = DisplayWidth(X_Dpy, sc->which);
|
||||
sc->ymax = DisplayHeight(X_Dpy, sc->which);
|
||||
|
||||
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
|
||||
"black", &sc->fgcolor, &tmp);
|
||||
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
|
||||
"#00cc00", &sc->bgcolor, &tmp);
|
||||
XAllocNamedColor(X_Dpy,DefaultColormap(X_Dpy, which),
|
||||
"blue", &sc->fccolor, &tmp);
|
||||
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
|
||||
"red", &sc->redcolor, &tmp);
|
||||
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
|
||||
"#00ccc8", &sc->cyancolor, &tmp);
|
||||
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
|
||||
"white", &sc->whitecolor, &tmp);
|
||||
XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, which),
|
||||
"black", &sc->blackcolor, &tmp);
|
||||
|
||||
sc->blackpixl = BlackPixel(X_Dpy, sc->which);
|
||||
sc->whitepixl = WhitePixel(X_Dpy, sc->which);
|
||||
sc->bluepixl = sc->fccolor.pixel;
|
||||
sc->redpixl = sc->redcolor.pixel;
|
||||
sc->cyanpixl = sc->cyancolor.pixel;
|
||||
|
||||
sc->gray = XCreatePixmapFromBitmapData(X_Dpy, sc->rootwin,
|
||||
gray_bits, gray_width, gray_height,
|
||||
sc->blackpixl, sc->whitepixl, DefaultDepth(X_Dpy, sc->which));
|
||||
|
||||
sc->blue = XCreatePixmapFromBitmapData(X_Dpy, sc->rootwin,
|
||||
gray_bits, gray_width, gray_height,
|
||||
sc->bluepixl, sc->whitepixl, DefaultDepth(X_Dpy, sc->which));
|
||||
|
||||
sc->red = XCreatePixmapFromBitmapData(X_Dpy, sc->rootwin,
|
||||
gray_bits, gray_width, gray_height,
|
||||
sc->redpixl, sc->whitepixl, DefaultDepth(X_Dpy, sc->which));
|
||||
|
||||
gv.foreground = sc->blackpixl^sc->whitepixl;
|
||||
gv.background = sc->whitepixl;
|
||||
gv.function = GXxor;
|
||||
gv.line_width = 1;
|
||||
gv.subwindow_mode = IncludeInferiors;
|
||||
|
||||
sc->gc = XCreateGC(X_Dpy, sc->rootwin,
|
||||
GCForeground|GCBackground|GCFunction|
|
||||
GCLineWidth|GCSubwindowMode, &gv);
|
||||
conf_color(&Conf);
|
||||
|
||||
font_init(sc);
|
||||
conf_font(&Conf);
|
||||
@@ -229,11 +174,8 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
|
||||
for (i = 0; i < nwins; i++) {
|
||||
XGetWindowAttributes(X_Dpy, wins[i], &winattr);
|
||||
if (winattr.override_redirect ||
|
||||
winattr.map_state != IsViewable) {
|
||||
char *name;
|
||||
XFetchName(X_Dpy, wins[i], &name);
|
||||
winattr.map_state != IsViewable)
|
||||
continue;
|
||||
}
|
||||
client_new(wins[i], sc, winattr.map_state != IsUnmapped);
|
||||
}
|
||||
XFree(wins);
|
||||
@@ -246,38 +188,22 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
|
||||
XChangeWindowAttributes(X_Dpy, sc->rootwin,
|
||||
CWEventMask, &rootattr);
|
||||
|
||||
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);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
char *
|
||||
x_screenname(int which)
|
||||
{
|
||||
char *cp, *dstr, *sn;
|
||||
size_t snlen;
|
||||
|
||||
if (which > 9)
|
||||
errx(1, "Can't handle more than 9 screens. If you need it, "
|
||||
"tell <marius@monkey.org>. It's a trivial fix.");
|
||||
|
||||
dstr = xstrdup(DisplayString(X_Dpy));
|
||||
|
||||
if ((cp = strrchr(dstr, ':')) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if ((cp = strchr(cp, '.')) != NULL)
|
||||
*cp = '\0';
|
||||
|
||||
snlen = strlen(dstr) + 3; /* string, dot, number, null */
|
||||
sn = (char *)xmalloc(snlen);
|
||||
snprintf(sn, snlen, "%s.%d", dstr, which);
|
||||
free(dstr);
|
||||
|
||||
return (sn);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
x_errorhandler(Display *dpy, XErrorEvent *e)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@@ -303,7 +229,7 @@ x_errorhandler(Display *dpy, XErrorEvent *e)
|
||||
}
|
||||
|
||||
static void
|
||||
_sigchld_cb(int which)
|
||||
sigchld_cb(int which)
|
||||
{
|
||||
pid_t pid;
|
||||
int save_errno = errno;
|
||||
|
217
calmwm.h
217
calmwm.h
@@ -33,6 +33,27 @@
|
||||
#define ChildMask (SubstructureRedirectMask|SubstructureNotifyMask)
|
||||
#define ButtonMask (ButtonPressMask|ButtonReleaseMask)
|
||||
#define MouseMask (ButtonMask|PointerMotionMask)
|
||||
#define KeyMask (KeyPressMask|ExposureMask)
|
||||
#define MenuMask (ButtonMask|ButtonMotionMask|ExposureMask| \
|
||||
PointerMotionMask)
|
||||
#define MenuGrabMask (ButtonMask|ButtonMotionMask|StructureNotifyMask|\
|
||||
PointerMotionMask)
|
||||
#define SearchMask (KeyPressMask|ExposureMask)
|
||||
|
||||
enum cwmcolor {
|
||||
CWM_COLOR_BORDOR_ACTIVE,
|
||||
CWM_COLOR_BORDER_INACTIVE,
|
||||
CWM_COLOR_BORDER_GROUP,
|
||||
CWM_COLOR_BORDER_UNGROUP,
|
||||
CWM_COLOR_FG_MENU,
|
||||
CWM_COLOR_BG_MENU,
|
||||
CWM_COLOR_MAX
|
||||
};
|
||||
|
||||
struct color {
|
||||
unsigned long pixel;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct client_ctx;
|
||||
|
||||
@@ -44,14 +65,9 @@ struct screen_ctx {
|
||||
u_int which;
|
||||
Window rootwin;
|
||||
Window menuwin;
|
||||
Colormap colormap;
|
||||
XColor bgcolor, fgcolor, fccolor, redcolor, cyancolor,
|
||||
whitecolor, blackcolor;
|
||||
char *display;
|
||||
unsigned long blackpixl, whitepixl, redpixl, bluepixl, cyanpixl;
|
||||
GC gc;
|
||||
|
||||
Pixmap gray, blue, red;
|
||||
struct color color[CWM_COLOR_MAX];
|
||||
GC gc;
|
||||
|
||||
int altpersist;
|
||||
|
||||
@@ -62,6 +78,9 @@ struct screen_ctx {
|
||||
|
||||
XftDraw *xftdraw;
|
||||
XftColor xftcolor;
|
||||
|
||||
int xinerama_no;
|
||||
XineramaScreenInfo *xinerama;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(screen_ctx_q, screen_ctx);
|
||||
@@ -78,9 +97,8 @@ TAILQ_HEAD(screen_ctx_q, screen_ctx);
|
||||
#define CLIENT_DOVMAXIMIZE 0x10
|
||||
#define CLIENT_VMAXIMIZED 0x20
|
||||
|
||||
#define CLIENT_HIGHLIGHT_BLUE 1
|
||||
#define CLIENT_HIGHLIGHT_RED 2
|
||||
|
||||
#define CLIENT_HIGHLIGHT_GROUP 1
|
||||
#define CLIENT_HIGHLIGHT_UNGROUP 2
|
||||
|
||||
struct winname {
|
||||
TAILQ_ENTRY(winname) entry;
|
||||
@@ -101,8 +119,6 @@ struct client_ctx {
|
||||
|
||||
Colormap cmap;
|
||||
|
||||
Window pwin;
|
||||
|
||||
u_int bwidth;
|
||||
struct {
|
||||
int x, y, width, height;
|
||||
@@ -113,8 +129,6 @@ struct client_ctx {
|
||||
int x,y;
|
||||
} ptr;
|
||||
|
||||
int beepbeep;
|
||||
|
||||
int xproto;
|
||||
|
||||
int flags;
|
||||
@@ -139,15 +153,12 @@ struct client_ctx {
|
||||
|
||||
TAILQ_HEAD(client_ctx_q, client_ctx);
|
||||
|
||||
static char *shortcut_to_name[] = {
|
||||
"nogroup", "one", "two", "three",
|
||||
"four", "five", "six", "seven",
|
||||
"eight", "nine"
|
||||
};
|
||||
extern const char *shortcut_to_name[];
|
||||
|
||||
struct group_ctx {
|
||||
TAILQ_ENTRY(group_ctx) entry;
|
||||
struct client_ctx_q clients;
|
||||
const char *name;
|
||||
int shortcut;
|
||||
int hidden;
|
||||
int nhidden;
|
||||
@@ -167,18 +178,6 @@ struct autogroupwin {
|
||||
|
||||
TAILQ_HEAD(autogroupwin_q, autogroupwin);
|
||||
|
||||
/* NULL/0 values indicate match any. */
|
||||
struct xevent {
|
||||
TAILQ_ENTRY(xevent) entry;
|
||||
Window *xev_win;
|
||||
Window *xev_root;
|
||||
int xev_type;
|
||||
void (*xev_cb)(struct xevent *, XEvent *);
|
||||
void *xev_arg;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(xevent_q, xevent);
|
||||
|
||||
#define CWM_MOVE 0x01
|
||||
#define CWM_RESIZE 0x02
|
||||
#define CWM_PTRMOVE 0x04
|
||||
@@ -213,14 +212,19 @@ TAILQ_HEAD(winmatch_q, winmatch);
|
||||
|
||||
#define KBTOGROUP(X) ((X) - 1)
|
||||
|
||||
union arg {
|
||||
char *c;
|
||||
int i;
|
||||
};
|
||||
|
||||
struct keybinding {
|
||||
TAILQ_ENTRY(keybinding) entry;
|
||||
void (*callback)(struct client_ctx *, union arg *);
|
||||
union arg argument;
|
||||
int modmask;
|
||||
int keysym;
|
||||
int keycode;
|
||||
int flags;
|
||||
void (*callback)(struct client_ctx *, void *);
|
||||
void *argument;
|
||||
TAILQ_ENTRY(keybinding) entry;
|
||||
};
|
||||
|
||||
struct cmd {
|
||||
@@ -257,6 +261,18 @@ struct conf {
|
||||
|
||||
#define CONF_STICKY_GROUPS 0x0001
|
||||
int flags;
|
||||
#define CONF_BWIDTH 1
|
||||
int bwidth;
|
||||
#define CONF_MAMOUNT 1
|
||||
int mamount;
|
||||
|
||||
#define CONF_COLOR_ACTIVEBORDER "#CCCCCC"
|
||||
#define CONF_COLOR_INACTIVEBORDER "#666666"
|
||||
#define CONF_COLOR_GROUPBORDER "blue"
|
||||
#define CONF_COLOR_UNGROUPBORDER "red"
|
||||
#define CONF_COLOR_MENUFG "black"
|
||||
#define CONF_COLOR_MENUBG "white"
|
||||
struct color color[CWM_COLOR_MAX];
|
||||
|
||||
char termpath[MAXPATHLEN];
|
||||
char lockpath[MAXPATHLEN];
|
||||
@@ -308,18 +324,13 @@ struct mwm_hints {
|
||||
int input_keycodetrans(KeyCode, u_int, enum ctltype *,
|
||||
char *);
|
||||
|
||||
int x_errorhandler(Display *, XErrorEvent *);
|
||||
void x_setup(void);
|
||||
char *x_screenname(int);
|
||||
void x_setupscreen(struct screen_ctx *, u_int);
|
||||
__dead void usage(void);
|
||||
|
||||
struct client_ctx *client_find(Window);
|
||||
void client_setup(void);
|
||||
void client_init(void);
|
||||
struct client_ctx *client_new(Window, struct screen_ctx *, int);
|
||||
int client_delete(struct client_ctx *, int, int);
|
||||
int client_delete(struct client_ctx *);
|
||||
void client_setactive(struct client_ctx *, int);
|
||||
void client_gravitate(struct client_ctx *, int);
|
||||
void client_resize(struct client_ctx *);
|
||||
void client_lower(struct client_ctx *);
|
||||
void client_raise(struct client_ctx *);
|
||||
@@ -329,61 +340,28 @@ void client_send_delete(struct client_ctx *);
|
||||
struct client_ctx *client_current(void);
|
||||
void client_hide(struct client_ctx *);
|
||||
void client_unhide(struct client_ctx *);
|
||||
void client_nocurrent(void);
|
||||
void client_setname(struct client_ctx *);
|
||||
void client_warp(struct client_ctx *);
|
||||
void client_ptrwarp(struct client_ctx *);
|
||||
void client_ptrsave(struct client_ctx *);
|
||||
void client_draw_border(struct client_ctx *);
|
||||
void client_update(struct client_ctx *);
|
||||
void client_placecalc(struct client_ctx *);
|
||||
void client_maximize(struct client_ctx *);
|
||||
void client_vertmaximize(struct client_ctx *);
|
||||
u_long client_bg_pixel(struct client_ctx *);
|
||||
Pixmap client_bg_pixmap(struct client_ctx *);
|
||||
void client_map(struct client_ctx *);
|
||||
void client_mtf(struct client_ctx *);
|
||||
struct client_ctx *client_cycle(int);
|
||||
struct client_ctx *client_mrunext(struct client_ctx *);
|
||||
struct client_ctx *client_mruprev(struct client_ctx *);
|
||||
void client_gethints(struct client_ctx *);
|
||||
void client_freehints(struct client_ctx *);
|
||||
void client_do_shape(struct client_ctx *);
|
||||
|
||||
struct menu *menu_filter(struct menu_q *, char *, char *, int,
|
||||
void (*)(struct menu_q *, struct menu_q *, char *),
|
||||
void (*)(struct menu *, int));
|
||||
void menu_init(struct screen_ctx *);
|
||||
|
||||
void xev_handle_maprequest(struct xevent *, XEvent *);
|
||||
void xev_handle_unmapnotify(struct xevent *, XEvent *);
|
||||
void xev_handle_destroynotify(struct xevent *, XEvent *);
|
||||
void xev_handle_configurerequest(struct xevent *, XEvent *);
|
||||
void xev_handle_propertynotify(struct xevent *, XEvent *);
|
||||
void xev_handle_enternotify(struct xevent *, XEvent *);
|
||||
void xev_handle_leavenotify(struct xevent *, XEvent *);
|
||||
void xev_handle_buttonpress(struct xevent *, XEvent *);
|
||||
void xev_handle_buttonrelease(struct xevent *, XEvent *);
|
||||
void xev_handle_keypress(struct xevent *, XEvent *);
|
||||
void xev_handle_keyrelease(struct xevent *, XEvent *);
|
||||
void xev_handle_expose(struct xevent *, XEvent *);
|
||||
void xev_handle_clientmessage(struct xevent *, XEvent *);
|
||||
void xev_handle_shape(struct xevent *, XEvent *);
|
||||
void xev_handle_mapping(struct xevent *, XEvent *);
|
||||
|
||||
#define XEV_QUICK(a, b, c, d, e) do { \
|
||||
xev_register(xev_new(a, b, c, d, e)); \
|
||||
} while (0)
|
||||
|
||||
/* XXX should be xu_ */
|
||||
void xev_reconfig(struct client_ctx *);
|
||||
|
||||
void xev_init(void);
|
||||
struct xevent *xev_new(Window *, Window *, int,
|
||||
void (*)(struct xevent *, XEvent *), void *);
|
||||
void xev_register(struct xevent *);
|
||||
void xev_loop(void);
|
||||
|
||||
void xu_getatoms(void);
|
||||
int xu_ptr_grab(Window, int, Cursor);
|
||||
void xu_btn_grab(Window, int, u_int);
|
||||
int xu_ptr_regrab(int, Cursor);
|
||||
@@ -399,60 +377,72 @@ int xu_getprop(struct client_ctx *, Atom, Atom, long,
|
||||
char *xu_getstrprop(struct client_ctx *, Atom atm);
|
||||
void xu_setstate(struct client_ctx *, int);
|
||||
int xu_getstate(struct client_ctx *, int *);
|
||||
unsigned long xu_getcolor(struct screen_ctx *, char *);
|
||||
void xu_freecolor(struct screen_ctx *, unsigned long);
|
||||
|
||||
int u_spawn(char *);
|
||||
void u_exec(char *);
|
||||
|
||||
void grab_sweep(struct client_ctx *);
|
||||
void grab_drag(struct client_ctx *);
|
||||
|
||||
void xfree(void *);
|
||||
void *xmalloc(size_t);
|
||||
void *xcalloc(size_t, size_t);
|
||||
char *xstrdup(const char *);
|
||||
|
||||
#define XMALLOC(p, t) ((p) = (t *)xmalloc(sizeof * (p)))
|
||||
#define XCALLOC(p, t) ((p) = (t *)xcalloc(1, sizeof * (p)))
|
||||
|
||||
void screen_init(void);
|
||||
struct screen_ctx *screen_fromroot(Window);
|
||||
struct screen_ctx *screen_current(void);
|
||||
void screen_updatestackingorder(void);
|
||||
void screen_init_xinerama(struct screen_ctx *);
|
||||
XineramaScreenInfo *screen_find_xinerama(struct screen_ctx *, int, int);
|
||||
|
||||
void conf_setup(struct conf *, const char *);
|
||||
void conf_client(struct client_ctx *);
|
||||
void conf_grab(struct conf *, struct keybinding *);
|
||||
void conf_ungrab(struct conf *, struct keybinding *);
|
||||
void conf_bindname(struct conf *, char *, char *);
|
||||
void conf_unbind(struct conf *, struct keybinding *);
|
||||
void conf_mousebind(struct conf *, char *, char *);
|
||||
void conf_mouseunbind(struct conf *, struct mousebinding *);
|
||||
void conf_grab_mouse(struct client_ctx *);
|
||||
void conf_reload(struct conf *);
|
||||
void conf_font(struct conf *);
|
||||
void conf_color(struct conf *);
|
||||
void conf_init(struct conf *);
|
||||
void conf_clear(struct conf *);
|
||||
void conf_cmd_add(struct conf *, char *, char *, int);
|
||||
|
||||
void kbfunc_client_lower(struct client_ctx *, void *);
|
||||
void kbfunc_client_raise(struct client_ctx *, void *);
|
||||
void kbfunc_client_search(struct client_ctx *, void *);
|
||||
void kbfunc_client_hide(struct client_ctx *, void *);
|
||||
void kbfunc_client_cycle(struct client_ctx *, void *);
|
||||
void kbfunc_client_rcycle(struct client_ctx *, void *);
|
||||
void kbfunc_cmdexec(struct client_ctx *, void *);
|
||||
void kbfunc_client_label(struct client_ctx *, void *);
|
||||
void kbfunc_client_delete(struct client_ctx *, void *);
|
||||
void kbfunc_client_group(struct client_ctx *, void *);
|
||||
void kbfunc_client_cyclegroup(struct client_ctx *, void *);
|
||||
void kbfunc_client_nogroup(struct client_ctx *, void *);
|
||||
void kbfunc_client_grouptoggle(struct client_ctx *, void *);
|
||||
void kbfunc_client_maximize(struct client_ctx *, void *);
|
||||
void kbfunc_client_vmaximize(struct client_ctx *, void *);
|
||||
void kbfunc_reload(struct client_ctx *, void *);
|
||||
void kbfunc_quit_wm(struct client_ctx *, void *);
|
||||
void kbfunc_moveresize(struct client_ctx *, void *);
|
||||
void kbfunc_menu_search(struct client_ctx *, void *);
|
||||
void kbfunc_exec(struct client_ctx *, void *);
|
||||
void kbfunc_ssh(struct client_ctx *, void *);
|
||||
void kbfunc_term(struct client_ctx *, void *);
|
||||
void kbfunc_lock(struct client_ctx *, void *);
|
||||
int parse_config(const char *, struct conf *);
|
||||
|
||||
void kbfunc_client_lower(struct client_ctx *, union arg *);
|
||||
void kbfunc_client_raise(struct client_ctx *, union arg *);
|
||||
void kbfunc_client_search(struct client_ctx *, union arg *);
|
||||
void kbfunc_client_hide(struct client_ctx *, union arg *);
|
||||
void kbfunc_client_cycle(struct client_ctx *, union arg *);
|
||||
void kbfunc_client_rcycle(struct client_ctx *, union arg *);
|
||||
void kbfunc_cmdexec(struct client_ctx *, union arg *);
|
||||
void kbfunc_client_label(struct client_ctx *, union arg *);
|
||||
void kbfunc_client_delete(struct client_ctx *, union arg *);
|
||||
void kbfunc_client_group(struct client_ctx *, union arg *);
|
||||
void kbfunc_client_grouponly(struct client_ctx *,
|
||||
union arg *);
|
||||
void kbfunc_client_cyclegroup(struct client_ctx *,
|
||||
union arg *);
|
||||
void kbfunc_client_nogroup(struct client_ctx *,
|
||||
union arg *);
|
||||
void kbfunc_client_grouptoggle(struct client_ctx *,
|
||||
union arg *);
|
||||
void kbfunc_client_movetogroup(struct client_ctx *,
|
||||
union arg *);
|
||||
void kbfunc_client_maximize(struct client_ctx *,
|
||||
union arg *);
|
||||
void kbfunc_client_vmaximize(struct client_ctx *,
|
||||
union arg *);
|
||||
void kbfunc_reload(struct client_ctx *, union arg *);
|
||||
void kbfunc_quit_wm(struct client_ctx *, union arg *);
|
||||
void kbfunc_moveresize(struct client_ctx *, union arg *);
|
||||
void kbfunc_menu_search(struct client_ctx *, union arg *);
|
||||
void kbfunc_exec(struct client_ctx *, union arg *);
|
||||
void kbfunc_ssh(struct client_ctx *, union arg *);
|
||||
void kbfunc_term(struct client_ctx *, union arg *);
|
||||
void kbfunc_lock(struct client_ctx *, union arg *);
|
||||
|
||||
void mousefunc_window_resize(struct client_ctx *, void *);
|
||||
void mousefunc_window_move(struct client_ctx *, void *);
|
||||
@@ -474,6 +464,7 @@ void search_match_exec(struct menu_q *, struct menu_q *,
|
||||
|
||||
void group_init(void);
|
||||
void group_hidetoggle(int);
|
||||
void group_only(int);
|
||||
void group_cycle(int);
|
||||
void group_sticky(struct client_ctx *);
|
||||
void group_client_delete(struct client_ctx *);
|
||||
@@ -482,6 +473,7 @@ void group_alltoggle(void);
|
||||
void group_sticky_toggle_enter(struct client_ctx *);
|
||||
void group_sticky_toggle_exit(struct client_ctx *);
|
||||
void group_autogroup(struct client_ctx *);
|
||||
void group_movetogroup(struct client_ctx *, int);
|
||||
|
||||
void font_init(struct screen_ctx *);
|
||||
int font_width(const char *, int);
|
||||
@@ -507,11 +499,20 @@ extern Cursor Cursor_question;
|
||||
|
||||
extern struct screen_ctx_q Screenq;
|
||||
extern struct screen_ctx *curscreen;
|
||||
extern u_int Nscreens;
|
||||
|
||||
extern struct client_ctx_q Clientq;
|
||||
|
||||
extern int Doshape, Shape_ev;
|
||||
extern int HasXinerama, HasRandr, Randr_ev;
|
||||
extern struct conf Conf;
|
||||
|
||||
#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 _CWM_GRP cwm_atoms[5]
|
||||
#define CWM_NO_ATOMS 6
|
||||
|
||||
extern Atom cwm_atoms[CWM_NO_ATOMS];
|
||||
|
||||
#endif /* _CALMWM_H_ */
|
||||
|
408
client.c
408
client.c
@@ -21,14 +21,19 @@
|
||||
#include "headers.h"
|
||||
#include "calmwm.h"
|
||||
|
||||
int _inwindowbounds(struct client_ctx *, int, int);
|
||||
static struct client_ctx *client_mrunext(struct client_ctx *);
|
||||
static struct client_ctx *client_mruprev(struct client_ctx *);
|
||||
static void client_placecalc(struct client_ctx *);
|
||||
static void client_update(struct client_ctx *);
|
||||
static void client_gethints(struct client_ctx *);
|
||||
static void client_freehints(struct client_ctx *);
|
||||
static int client_inbound(struct client_ctx *, int, int);
|
||||
|
||||
static char emptystring[] = "";
|
||||
|
||||
struct client_ctx *_curcc = NULL;
|
||||
|
||||
void
|
||||
client_setup(void)
|
||||
client_init(void)
|
||||
{
|
||||
TAILQ_INIT(&Clientq);
|
||||
}
|
||||
@@ -39,7 +44,7 @@ client_find(Window win)
|
||||
struct client_ctx *cc;
|
||||
|
||||
TAILQ_FOREACH(cc, &Clientq, entry)
|
||||
if (cc->pwin == win || cc->win == win)
|
||||
if (cc->win == win)
|
||||
return (cc);
|
||||
|
||||
return (NULL);
|
||||
@@ -49,16 +54,15 @@ struct client_ctx *
|
||||
client_new(Window win, struct screen_ctx *sc, int mapped)
|
||||
{
|
||||
struct client_ctx *cc;
|
||||
XSetWindowAttributes pxattr;
|
||||
XWindowAttributes wattr;
|
||||
XWMHints *wmhints;
|
||||
long tmp;
|
||||
int x, y, height, width, state;
|
||||
int state;
|
||||
|
||||
if (win == None)
|
||||
return (NULL);
|
||||
|
||||
XCALLOC(cc, struct client_ctx);
|
||||
cc = xcalloc(1, sizeof(*cc));
|
||||
|
||||
XGrabServer(X_Dpy);
|
||||
|
||||
@@ -66,22 +70,8 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
|
||||
cc->sc = sc;
|
||||
cc->win = win;
|
||||
cc->size = XAllocSizeHints();
|
||||
if (cc->size->width_inc == 0)
|
||||
cc->size->width_inc = 1;
|
||||
if (cc->size->height_inc == 0)
|
||||
cc->size->height_inc = 1;
|
||||
|
||||
TAILQ_INIT(&cc->nameq);
|
||||
client_setname(cc);
|
||||
|
||||
/*
|
||||
* conf_client() needs at least cc->win and cc->name
|
||||
*/
|
||||
conf_client(cc);
|
||||
|
||||
XGetWMNormalHints(X_Dpy, cc->win, cc->size, &tmp);
|
||||
XGetWindowAttributes(X_Dpy, cc->win, &wattr);
|
||||
|
||||
if (cc->size->flags & PBaseSize) {
|
||||
cc->geom.min_dx = cc->size->base_width;
|
||||
cc->geom.min_dy = cc->size->base_height;
|
||||
@@ -90,12 +80,16 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
|
||||
cc->geom.min_dy = cc->size->min_height;
|
||||
}
|
||||
|
||||
TAILQ_INIT(&cc->nameq);
|
||||
client_setname(cc);
|
||||
|
||||
conf_client(cc);
|
||||
|
||||
/* Saved pointer position */
|
||||
cc->ptr.x = -1;
|
||||
cc->ptr.y = -1;
|
||||
|
||||
client_gravitate(cc, 1);
|
||||
|
||||
XGetWindowAttributes(X_Dpy, cc->win, &wattr);
|
||||
cc->geom.x = wattr.x;
|
||||
cc->geom.y = wattr.y;
|
||||
cc->geom.width = wattr.width;
|
||||
@@ -110,7 +104,9 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
|
||||
|
||||
XFree(wmhints);
|
||||
}
|
||||
client_move(cc);
|
||||
}
|
||||
client_draw_border(cc);
|
||||
|
||||
if (xu_getstate(cc, &state) < 0)
|
||||
state = NormalState;
|
||||
@@ -118,42 +114,12 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
|
||||
XSelectInput(X_Dpy, cc->win, ColormapChangeMask | EnterWindowMask |
|
||||
PropertyChangeMask | KeyReleaseMask);
|
||||
|
||||
x = cc->geom.x - cc->bwidth;
|
||||
y = cc->geom.y - cc->bwidth;
|
||||
|
||||
width = cc->geom.width;
|
||||
height = cc->geom.height;
|
||||
if (cc->bwidth > 1) {
|
||||
width += (cc->bwidth)*2;
|
||||
height += (cc->bwidth)*2;
|
||||
}
|
||||
pxattr.override_redirect = True;
|
||||
pxattr.background_pixel = sc->bgcolor.pixel;
|
||||
pxattr.event_mask = ChildMask | ButtonPressMask | ButtonReleaseMask |
|
||||
ExposureMask | EnterWindowMask;
|
||||
|
||||
cc->pwin = XCreateWindow(X_Dpy, sc->rootwin, x, y,
|
||||
width, height, 0, /* XXX */
|
||||
DefaultDepth(X_Dpy, sc->which), CopyFromParent,
|
||||
DefaultVisual(X_Dpy, sc->which),
|
||||
CWOverrideRedirect | CWBackPixel | CWEventMask, &pxattr);
|
||||
|
||||
cc->active = 0;
|
||||
|
||||
XAddToSaveSet(X_Dpy, cc->win);
|
||||
XSetWindowBorderWidth(X_Dpy, cc->win, 0);
|
||||
XReparentWindow(X_Dpy, cc->win, cc->pwin, cc->bwidth, cc->bwidth);
|
||||
|
||||
/* Notify client of its configuration. */
|
||||
xev_reconfig(cc);
|
||||
|
||||
if (state == IconicState)
|
||||
client_hide(cc);
|
||||
else {
|
||||
XMapRaised(X_Dpy, cc->pwin);
|
||||
XMapWindow(X_Dpy, cc->win);
|
||||
}
|
||||
|
||||
(state == IconicState) ? client_hide(cc) : client_unhide(cc);
|
||||
xu_setstate(cc, cc->state);
|
||||
|
||||
XSync(X_Dpy, False);
|
||||
@@ -171,51 +137,18 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
|
||||
return (cc);
|
||||
}
|
||||
|
||||
void
|
||||
client_do_shape(struct client_ctx *cc)
|
||||
{
|
||||
/* Windows not rectangular require more effort */
|
||||
XRectangle *r;
|
||||
int n, tmp;
|
||||
|
||||
if (Doshape) {
|
||||
XShapeSelectInput(X_Dpy, cc->win, ShapeNotifyMask);
|
||||
|
||||
r = XShapeGetRectangles(X_Dpy, cc->win, ShapeBounding,
|
||||
&n, &tmp);
|
||||
|
||||
if (n > 1)
|
||||
XShapeCombineShape(X_Dpy, cc->pwin, ShapeBounding,
|
||||
cc->bwidth, cc->bwidth, cc->win, ShapeBounding,
|
||||
ShapeSet);
|
||||
XFree(r);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
client_delete(struct client_ctx *cc, int sendevent, int ignorewindow)
|
||||
client_delete(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
struct winname *wn;
|
||||
|
||||
if (cc->state == IconicState && !sendevent)
|
||||
return (1);
|
||||
|
||||
group_client_delete(cc);
|
||||
|
||||
XGrabServer(X_Dpy);
|
||||
xu_setstate(cc, WithdrawnState);
|
||||
XRemoveFromSaveSet(X_Dpy, cc->win);
|
||||
|
||||
if (!ignorewindow) {
|
||||
client_gravitate(cc, 0);
|
||||
XSetWindowBorderWidth(X_Dpy, cc->win, 1); /* XXX */
|
||||
XReparentWindow(X_Dpy, cc->win,
|
||||
sc->rootwin, cc->geom.x, cc->geom.y);
|
||||
}
|
||||
if (cc->pwin)
|
||||
XDestroyWindow(X_Dpy, cc->pwin);
|
||||
|
||||
XSync(X_Dpy, False);
|
||||
XUngrabServer(X_Dpy);
|
||||
|
||||
@@ -235,7 +168,6 @@ client_delete(struct client_ctx *cc, int sendevent, int ignorewindow)
|
||||
}
|
||||
|
||||
client_freehints(cc);
|
||||
|
||||
xfree(cc);
|
||||
|
||||
return (0);
|
||||
@@ -296,42 +228,40 @@ client_current(void)
|
||||
return (_curcc);
|
||||
}
|
||||
|
||||
void
|
||||
client_gravitate(struct client_ctx *cc, int yes)
|
||||
{
|
||||
int dx = 0, dy = 0, mult = yes ? 1 : -1;
|
||||
int gravity = (cc->size->flags & PWinGravity) ?
|
||||
cc->size->win_gravity : NorthWestGravity;
|
||||
|
||||
switch (gravity) {
|
||||
case NorthWestGravity:
|
||||
case SouthWestGravity:
|
||||
case NorthEastGravity:
|
||||
case StaticGravity:
|
||||
dx = cc->bwidth;
|
||||
case NorthGravity:
|
||||
dy = cc->bwidth;
|
||||
break;
|
||||
}
|
||||
|
||||
cc->geom.x += mult * dx;
|
||||
cc->geom.y += mult * dy;
|
||||
}
|
||||
|
||||
void
|
||||
client_maximize(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
int xmax = sc->xmax, ymax = sc->ymax;
|
||||
int x_org = 0, y_org = 0;
|
||||
|
||||
if (cc->flags & CLIENT_MAXIMIZED) {
|
||||
cc->geom = cc->savegeom;
|
||||
} else {
|
||||
if (!(cc->flags & CLIENT_VMAXIMIZED))
|
||||
cc->savegeom = cc->geom;
|
||||
cc->geom.x = Conf.gap_left;
|
||||
cc->geom.y = Conf.gap_top;
|
||||
cc->geom.height = sc->ymax - (Conf.gap_top + Conf.gap_bottom);
|
||||
cc->geom.width = sc->xmax - (Conf.gap_left + Conf.gap_right);
|
||||
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(CCTOSC(cc),
|
||||
cc->geom.x + cc->geom.width / 2,
|
||||
cc->geom.y + cc->geom.height / 2);
|
||||
if (xine == NULL)
|
||||
goto calc;
|
||||
x_org = xine->x_org;
|
||||
y_org = xine->y_org;
|
||||
xmax = xine->width;
|
||||
ymax = xine->height;
|
||||
}
|
||||
calc:
|
||||
cc->geom.x = x_org - cc->bwidth + Conf.gap_left;
|
||||
cc->geom.y = y_org - cc->bwidth + Conf.gap_top;
|
||||
cc->geom.height = ymax - (Conf.gap_top + Conf.gap_bottom);
|
||||
cc->geom.width = xmax - (Conf.gap_left + Conf.gap_right);
|
||||
cc->flags |= CLIENT_DOMAXIMIZE;
|
||||
}
|
||||
|
||||
@@ -342,15 +272,27 @@ void
|
||||
client_vertmaximize(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
int y_org = 0, ymax = sc->ymax;
|
||||
|
||||
if (cc->flags & CLIENT_VMAXIMIZED) {
|
||||
cc->geom = cc->savegeom;
|
||||
} else {
|
||||
if (!(cc->flags & CLIENT_MAXIMIZED))
|
||||
cc->savegeom = cc->geom;
|
||||
cc->geom.y = cc->bwidth + Conf.gap_top;
|
||||
cc->geom.height = (sc->ymax - cc->bwidth * 2) -
|
||||
(Conf.gap_top + Conf.gap_bottom);
|
||||
if (HasXinerama) {
|
||||
XineramaScreenInfo *xine;
|
||||
xine = screen_find_xinerama(CCTOSC(cc),
|
||||
cc->geom.x + cc->geom.width / 2,
|
||||
cc->geom.y + cc->geom.height / 2);
|
||||
if (xine == NULL)
|
||||
goto calc;
|
||||
y_org = xine->y_org;
|
||||
ymax = xine->height;
|
||||
}
|
||||
calc:
|
||||
cc->geom.y = y_org + Conf.gap_top;
|
||||
cc->geom.height = ymax - (cc->bwidth * 2) - (Conf.gap_top +
|
||||
Conf.gap_bottom);
|
||||
cc->flags |= CLIENT_DOVMAXIMIZE;
|
||||
}
|
||||
|
||||
@@ -371,32 +313,28 @@ client_resize(struct client_ctx *cc)
|
||||
cc->flags |= CLIENT_VMAXIMIZED;
|
||||
}
|
||||
|
||||
XMoveResizeWindow(X_Dpy, cc->pwin, cc->geom.x - cc->bwidth,
|
||||
cc->geom.y - cc->bwidth, cc->geom.width + cc->bwidth*2,
|
||||
cc->geom.height + cc->bwidth*2);
|
||||
XMoveResizeWindow(X_Dpy, cc->win, cc->bwidth, cc->bwidth,
|
||||
cc->geom.width, cc->geom.height);
|
||||
XMoveResizeWindow(X_Dpy, cc->win, cc->geom.x,
|
||||
cc->geom.y, cc->geom.width, cc->geom.height);
|
||||
xev_reconfig(cc);
|
||||
}
|
||||
|
||||
void
|
||||
client_move(struct client_ctx *cc)
|
||||
{
|
||||
XMoveWindow(X_Dpy, cc->pwin,
|
||||
cc->geom.x - cc->bwidth, cc->geom.y - cc->bwidth);
|
||||
XMoveWindow(X_Dpy, cc->win, cc->geom.x, cc->geom.y);
|
||||
xev_reconfig(cc);
|
||||
}
|
||||
|
||||
void
|
||||
client_lower(struct client_ctx *cc)
|
||||
{
|
||||
XLowerWindow(X_Dpy, cc->pwin);
|
||||
XLowerWindow(X_Dpy, cc->win);
|
||||
}
|
||||
|
||||
void
|
||||
client_raise(struct client_ctx *cc)
|
||||
{
|
||||
XRaiseWindow(X_Dpy, cc->pwin);
|
||||
XRaiseWindow(X_Dpy, cc->win);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -409,12 +347,8 @@ client_ptrwarp(struct client_ctx *cc)
|
||||
y = cc->geom.height / 2;
|
||||
}
|
||||
|
||||
if (cc->state == IconicState)
|
||||
client_unhide(cc);
|
||||
else
|
||||
client_raise(cc);
|
||||
|
||||
xu_ptr_setpos(cc->pwin, x, y);
|
||||
(cc->state == IconicState) ? client_unhide(cc) : client_raise(cc);
|
||||
xu_ptr_setpos(cc->win, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -422,8 +356,8 @@ client_ptrsave(struct client_ctx *cc)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
xu_ptr_getpos(cc->pwin, &x, &y);
|
||||
if (_inwindowbounds(cc, x, y)) {
|
||||
xu_ptr_getpos(cc->win, &x, &y);
|
||||
if (client_inbound(cc, x, y)) {
|
||||
cc->ptr.x = x;
|
||||
cc->ptr.y = y;
|
||||
}
|
||||
@@ -433,7 +367,7 @@ void
|
||||
client_hide(struct client_ctx *cc)
|
||||
{
|
||||
/* XXX - add wm_state stuff */
|
||||
XUnmapWindow(X_Dpy, cc->pwin);
|
||||
XUnmapWindow(X_Dpy, cc->win);
|
||||
|
||||
cc->active = 0;
|
||||
cc->flags |= CLIENT_HIDDEN;
|
||||
@@ -446,97 +380,54 @@ client_hide(struct client_ctx *cc)
|
||||
void
|
||||
client_unhide(struct client_ctx *cc)
|
||||
{
|
||||
XMapRaised(X_Dpy, cc->pwin);
|
||||
XMapRaised(X_Dpy, cc->win);
|
||||
|
||||
cc->highlight = 0;
|
||||
cc->flags &= ~CLIENT_HIDDEN;
|
||||
xu_setstate(cc, NormalState);
|
||||
client_draw_border(cc);
|
||||
}
|
||||
|
||||
void
|
||||
client_draw_border(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
unsigned long pixel;
|
||||
|
||||
if (cc->active) {
|
||||
XSetWindowBackground(X_Dpy, cc->pwin, client_bg_pixel(cc));
|
||||
XClearWindow(X_Dpy, cc->pwin);
|
||||
if (cc->active)
|
||||
switch (cc->highlight) {
|
||||
case CLIENT_HIGHLIGHT_GROUP:
|
||||
pixel = sc->color[CWM_COLOR_BORDER_GROUP].pixel;
|
||||
break;
|
||||
case CLIENT_HIGHLIGHT_UNGROUP:
|
||||
pixel = sc->color[CWM_COLOR_BORDER_UNGROUP].pixel;
|
||||
break;
|
||||
default:
|
||||
pixel = sc->color[CWM_COLOR_BORDOR_ACTIVE].pixel;
|
||||
break;
|
||||
}
|
||||
else
|
||||
pixel = sc->color[CWM_COLOR_BORDER_INACTIVE].pixel;
|
||||
|
||||
if (!cc->highlight && cc->bwidth > 1)
|
||||
XDrawRectangle(X_Dpy, cc->pwin, sc->gc, 1, 1,
|
||||
cc->geom.width + cc->bwidth,
|
||||
cc->geom.height + cc->bwidth);
|
||||
} else {
|
||||
if (cc->bwidth > 1)
|
||||
XSetWindowBackgroundPixmap(X_Dpy,
|
||||
cc->pwin, client_bg_pixmap(cc));
|
||||
|
||||
XClearWindow(X_Dpy, cc->pwin);
|
||||
}
|
||||
XSetWindowBorderWidth(X_Dpy, cc->win, cc->bwidth);
|
||||
XSetWindowBorder(X_Dpy, cc->win, pixel);
|
||||
}
|
||||
|
||||
u_long
|
||||
client_bg_pixel(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
u_long pixl;
|
||||
|
||||
switch (cc->highlight) {
|
||||
case CLIENT_HIGHLIGHT_BLUE:
|
||||
pixl = sc->bluepixl;
|
||||
break;
|
||||
case CLIENT_HIGHLIGHT_RED:
|
||||
pixl = sc->redpixl;
|
||||
break;
|
||||
default:
|
||||
pixl = sc->blackpixl;
|
||||
break;
|
||||
}
|
||||
|
||||
return (pixl);
|
||||
}
|
||||
|
||||
Pixmap
|
||||
client_bg_pixmap(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
Pixmap pix;
|
||||
|
||||
switch (cc->highlight) {
|
||||
case CLIENT_HIGHLIGHT_BLUE:
|
||||
pix = sc->blue;
|
||||
break;
|
||||
case CLIENT_HIGHLIGHT_RED:
|
||||
pix = sc->red;
|
||||
break;
|
||||
default:
|
||||
pix = sc->gray;
|
||||
break;
|
||||
}
|
||||
|
||||
return (pix);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
client_update(struct client_ctx *cc)
|
||||
{
|
||||
Atom *p, wm_delete, wm_protocols, wm_take_focus;
|
||||
Atom *p;
|
||||
int i;
|
||||
long n;
|
||||
|
||||
/* XXX cache these. */
|
||||
wm_delete = XInternAtom(X_Dpy, "WM_DELETE_WINDOW", False);
|
||||
wm_protocols = XInternAtom(X_Dpy, "WM_PROTOCOLS", False);
|
||||
wm_take_focus = XInternAtom(X_Dpy, "WM_TAKE_FOCUS", False);
|
||||
|
||||
if ((n = xu_getprop(cc, wm_protocols,
|
||||
if ((n = xu_getprop(cc, WM_PROTOCOLS,
|
||||
XA_ATOM, 20L, (u_char **)&p)) <= 0)
|
||||
return;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
if (p[i] == wm_delete)
|
||||
if (p[i] == WM_DELETE_WINDOW)
|
||||
cc->xproto |= CLIENT_PROTO_DELETE;
|
||||
else if (p[i] == wm_take_focus)
|
||||
else if (p[i] == WM_TAKE_FOCUS)
|
||||
cc->xproto |= CLIENT_PROTO_TAKEFOCUS;
|
||||
|
||||
XFree(p);
|
||||
@@ -545,14 +436,8 @@ client_update(struct client_ctx *cc)
|
||||
void
|
||||
client_send_delete(struct client_ctx *cc)
|
||||
{
|
||||
Atom wm_delete, wm_protocols;
|
||||
|
||||
/* XXX - cache */
|
||||
wm_delete = XInternAtom(X_Dpy, "WM_DELETE_WINDOW", False);
|
||||
wm_protocols = XInternAtom(X_Dpy, "WM_PROTOCOLS", False);
|
||||
|
||||
if (cc->xproto & CLIENT_PROTO_DELETE)
|
||||
xu_sendmsg(cc, wm_protocols, wm_delete);
|
||||
xu_sendmsg(cc, WM_PROTOCOLS, WM_DELETE_WINDOW);
|
||||
else
|
||||
XKillClient(X_Dpy, cc->win);
|
||||
}
|
||||
@@ -575,7 +460,7 @@ client_setname(struct client_ctx *cc)
|
||||
goto match;
|
||||
}
|
||||
|
||||
XMALLOC(wn, struct winname);
|
||||
wn = xmalloc(sizeof(*wn));
|
||||
wn->name = newname;
|
||||
TAILQ_INSERT_TAIL(&cc->nameq, wn, entry);
|
||||
cc->nameqlen++;
|
||||
@@ -643,7 +528,7 @@ client_cycle(int reverse)
|
||||
return (newcc);
|
||||
}
|
||||
|
||||
struct client_ctx *
|
||||
static struct client_ctx *
|
||||
client_mrunext(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
@@ -653,7 +538,7 @@ client_mrunext(struct client_ctx *cc)
|
||||
ccc : TAILQ_FIRST(&sc->mruq));
|
||||
}
|
||||
|
||||
struct client_ctx *
|
||||
static struct client_ctx *
|
||||
client_mruprev(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
@@ -663,50 +548,72 @@ client_mruprev(struct client_ctx *cc)
|
||||
ccc : TAILQ_LAST(&sc->mruq, cycle_entry_q));
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
client_placecalc(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
int yslack, xslack, xmouse, ymouse;
|
||||
|
||||
yslack = sc->ymax - cc->geom.height - cc->bwidth;
|
||||
xslack = sc->xmax - cc->geom.width - cc->bwidth;
|
||||
|
||||
xu_ptr_getpos(sc->rootwin, &xmouse, &ymouse);
|
||||
|
||||
xmouse = MAX(xmouse, cc->bwidth) - cc->geom.width / 2;
|
||||
ymouse = MAX(ymouse, cc->bwidth) - cc->geom.height / 2;
|
||||
|
||||
xmouse = MAX(xmouse, (int)cc->bwidth);
|
||||
ymouse = MAX(ymouse, (int)cc->bwidth);
|
||||
int xslack, yslack;
|
||||
|
||||
if (cc->size->flags & USPosition) {
|
||||
if (cc->size->x >= 0)
|
||||
cc->geom.x = MAX(MIN(cc->size->x, xslack), cc->bwidth);
|
||||
else
|
||||
cc->geom.x = cc->bwidth;
|
||||
if (cc->size->y >= 0)
|
||||
cc->geom.y = MAX(MIN(cc->size->y, yslack), cc->bwidth);
|
||||
else
|
||||
cc->geom.y = cc->bwidth;
|
||||
/*
|
||||
* Ignore XINERAMA screens, just make sure it's somewhere
|
||||
* in the virtual desktop. else it stops people putting xterms
|
||||
* at startup in the screen the mouse doesn't start in *sigh*.
|
||||
* 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;
|
||||
if (cc->size->x > 0)
|
||||
cc->geom.x = MIN(cc->size->x, xslack);
|
||||
if (cc->size->y > 0)
|
||||
cc->geom.y = MIN(cc->size->y, yslack);
|
||||
} else {
|
||||
if (xslack >= 0) {
|
||||
XineramaScreenInfo *info;
|
||||
int xmouse, ymouse, xorig, yorig;
|
||||
int xmax, ymax;
|
||||
|
||||
xu_ptr_getpos(sc->rootwin, &xmouse, &ymouse);
|
||||
if (HasXinerama) {
|
||||
info = screen_find_xinerama(sc, xmouse, ymouse);
|
||||
if (info == NULL)
|
||||
goto noxine;
|
||||
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;
|
||||
}
|
||||
xmouse = MAX(xmouse, xorig) - cc->geom.width / 2;
|
||||
ymouse = MAX(ymouse, yorig) - cc->geom.height / 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;
|
||||
|
||||
if (xslack >= xorig) {
|
||||
cc->geom.x = MAX(MIN(xmouse, xslack),
|
||||
Conf.gap_left + cc->bwidth);
|
||||
xorig + Conf.gap_left);
|
||||
if (cc->geom.x > (xslack - Conf.gap_right))
|
||||
cc->geom.x -= Conf.gap_right;
|
||||
} else {
|
||||
cc->geom.x = cc->bwidth + Conf.gap_left;
|
||||
cc->geom.width = sc->xmax - Conf.gap_left;
|
||||
cc->geom.x = xorig + Conf.gap_left;
|
||||
cc->geom.width = xmax - Conf.gap_left;
|
||||
}
|
||||
if (yslack >= 0) {
|
||||
if (yslack >= yorig) {
|
||||
cc->geom.y = MAX(MIN(ymouse, yslack),
|
||||
Conf.gap_top + cc->bwidth);
|
||||
yorig + Conf.gap_top);
|
||||
if (cc->geom.y > (yslack - Conf.gap_bottom))
|
||||
cc->geom.y -= Conf.gap_bottom;
|
||||
} else {
|
||||
cc->geom.y = cc->bwidth + Conf.gap_top;
|
||||
cc->geom.height = sc->ymax - Conf.gap_top;
|
||||
cc->geom.y = yorig + Conf.gap_top;
|
||||
cc->geom.height = ymax - Conf.gap_top;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -728,13 +635,12 @@ client_mtf(struct client_ctx *cc)
|
||||
TAILQ_INSERT_HEAD(&sc->mruq, cc, mru_entry);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
client_gethints(struct client_ctx *cc)
|
||||
{
|
||||
XClassHint xch;
|
||||
int argc;
|
||||
char **argv;
|
||||
Atom mha;
|
||||
struct mwm_hints *mwmh;
|
||||
|
||||
if (XGetClassHint(X_Dpy, cc->win, &xch)) {
|
||||
@@ -744,9 +650,8 @@ client_gethints(struct client_ctx *cc)
|
||||
cc->app_class = xch.res_class;
|
||||
}
|
||||
|
||||
mha = XInternAtom(X_Dpy, "_MOTIF_WM_HINTS", False);
|
||||
if (xu_getprop(cc, mha, mha, PROP_MWM_HINTS_ELEMENTS,
|
||||
(u_char **)&mwmh) == MWM_NUMHINTS)
|
||||
if (xu_getprop(cc, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS,
|
||||
PROP_MWM_HINTS_ELEMENTS, (u_char **)&mwmh) == MWM_NUMHINTS)
|
||||
if (mwmh->flags & MWM_HINTS_DECORATIONS &&
|
||||
!(mwmh->decorations & MWM_DECOR_ALL) &&
|
||||
!(mwmh->decorations & MWM_DECOR_BORDER))
|
||||
@@ -776,19 +681,18 @@ client_gethints(struct client_ctx *cc)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
client_freehints(struct client_ctx *cc)
|
||||
{
|
||||
if (cc->app_name != NULL)
|
||||
XFree(cc->app_name);
|
||||
if (cc->app_class != NULL)
|
||||
XFree(cc->app_class);
|
||||
if (cc->app_cliarg != NULL)
|
||||
xfree(cc->app_cliarg);
|
||||
xfree(cc->app_cliarg);
|
||||
}
|
||||
|
||||
int
|
||||
_inwindowbounds(struct client_ctx *cc, int x, int y)
|
||||
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);
|
||||
|
269
conf.c
269
conf.c
@@ -28,6 +28,9 @@
|
||||
((tsp)->tv_sec cmp (usp)->tv_sec))
|
||||
#endif
|
||||
|
||||
static void conf_mouseunbind(struct conf *, struct mousebinding *);
|
||||
static void conf_unbind(struct conf *, struct keybinding *);
|
||||
|
||||
extern struct screen_ctx *Curscreen;
|
||||
|
||||
/* Add an command menu entry to the end of the menu */
|
||||
@@ -41,8 +44,7 @@ conf_cmd_add(struct conf *c, char *image, char *label, int flags)
|
||||
else if (strcmp(label, "lock") == 0)
|
||||
strlcpy(c->lockpath, image, sizeof(c->lockpath));
|
||||
else {
|
||||
struct cmd *cmd;
|
||||
XMALLOC(cmd, struct cmd);
|
||||
struct cmd *cmd = xmalloc(sizeof(*cmd));
|
||||
cmd->flags = flags;
|
||||
strlcpy(cmd->image, image, sizeof(cmd->image));
|
||||
strlcpy(cmd->label, label, sizeof(cmd->label));
|
||||
@@ -57,18 +59,37 @@ conf_font(struct conf *c)
|
||||
|
||||
sc = screen_current();
|
||||
|
||||
c->DefaultFont = font_make(sc, Conf.DefaultFontName);
|
||||
c->DefaultFont = font_make(sc, c->DefaultFontName);
|
||||
c->FontHeight = font_ascent() + font_descent() + 1;
|
||||
}
|
||||
|
||||
void
|
||||
conf_color(struct conf *c)
|
||||
{
|
||||
struct screen_ctx *sc;
|
||||
int i;
|
||||
|
||||
sc = screen_current();
|
||||
|
||||
for (i = 0; i < CWM_COLOR_MAX; i++) {
|
||||
xu_freecolor(sc, sc->color[i].pixel);
|
||||
sc->color[i].pixel = xu_getcolor(sc, c->color[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
conf_reload(struct conf *c)
|
||||
{
|
||||
struct client_ctx *cc;
|
||||
|
||||
if (parse_config(c->conf_path, c) == -1) {
|
||||
warnx("config file %s has errors, not reloading", c->conf_path);
|
||||
return;
|
||||
}
|
||||
|
||||
conf_color(c);
|
||||
TAILQ_FOREACH(cc, &Clientq, entry)
|
||||
client_draw_border(cc);
|
||||
conf_font(c);
|
||||
}
|
||||
|
||||
@@ -76,6 +97,8 @@ void
|
||||
conf_init(struct conf *c)
|
||||
{
|
||||
c->flags = 0;
|
||||
c->bwidth = CONF_BWIDTH;
|
||||
c->mamount = CONF_MAMOUNT;
|
||||
|
||||
TAILQ_INIT(&c->ignoreq);
|
||||
TAILQ_INIT(&c->cmdq);
|
||||
@@ -155,9 +178,67 @@ conf_init(struct conf *c)
|
||||
strlcpy(c->termpath, "xterm", sizeof(c->termpath));
|
||||
strlcpy(c->lockpath, "xlock", sizeof(c->lockpath));
|
||||
|
||||
c->color[CWM_COLOR_BORDOR_ACTIVE].name =
|
||||
xstrdup(CONF_COLOR_ACTIVEBORDER);
|
||||
c->color[CWM_COLOR_BORDER_INACTIVE].name =
|
||||
xstrdup(CONF_COLOR_INACTIVEBORDER);
|
||||
c->color[CWM_COLOR_BORDER_GROUP].name =
|
||||
xstrdup(CONF_COLOR_GROUPBORDER);
|
||||
c->color[CWM_COLOR_BORDER_UNGROUP].name =
|
||||
xstrdup(CONF_COLOR_UNGROUPBORDER);
|
||||
c->color[CWM_COLOR_FG_MENU].name =
|
||||
xstrdup(CONF_COLOR_MENUFG);
|
||||
c->color[CWM_COLOR_BG_MENU].name =
|
||||
xstrdup(CONF_COLOR_MENUBG);
|
||||
|
||||
c->DefaultFontName = xstrdup(DEFAULTFONTNAME);
|
||||
}
|
||||
|
||||
void
|
||||
conf_clear(struct conf *c)
|
||||
{
|
||||
struct autogroupwin *ag;
|
||||
struct keybinding *kb;
|
||||
struct winmatch *wm;
|
||||
struct cmd *cmd;
|
||||
struct mousebinding *mb;
|
||||
int i;
|
||||
|
||||
while ((cmd = TAILQ_FIRST(&c->cmdq)) != NULL) {
|
||||
TAILQ_REMOVE(&c->cmdq, cmd, entry);
|
||||
xfree(cmd);
|
||||
}
|
||||
|
||||
while ((kb = TAILQ_FIRST(&c->keybindingq)) != NULL) {
|
||||
TAILQ_REMOVE(&c->keybindingq, kb, entry);
|
||||
xfree(kb);
|
||||
}
|
||||
|
||||
while ((ag = TAILQ_FIRST(&c->autogroupq)) != NULL) {
|
||||
TAILQ_REMOVE(&c->autogroupq, ag, entry);
|
||||
xfree(ag->class);
|
||||
if (ag->name)
|
||||
xfree(ag->name);
|
||||
xfree(ag->group);
|
||||
xfree(ag);
|
||||
}
|
||||
|
||||
while ((wm = TAILQ_FIRST(&c->ignoreq)) != NULL) {
|
||||
TAILQ_REMOVE(&c->ignoreq, wm, entry);
|
||||
xfree(wm);
|
||||
}
|
||||
|
||||
while ((mb = TAILQ_FIRST(&c->mousebindingq)) != NULL) {
|
||||
TAILQ_REMOVE(&c->mousebindingq, mb, entry);
|
||||
xfree(mb);
|
||||
}
|
||||
|
||||
for (i = 0; i < CWM_COLOR_MAX; i++)
|
||||
xfree(c->color[i].name);
|
||||
|
||||
xfree(c->DefaultFontName);
|
||||
}
|
||||
|
||||
void
|
||||
conf_setup(struct conf *c, const char *conf_file)
|
||||
{
|
||||
@@ -189,105 +270,127 @@ conf_client(struct client_ctx *cc)
|
||||
char *wname = cc->name;
|
||||
int ignore = 0;
|
||||
|
||||
/* Can wname be NULL? */
|
||||
if (wname != NULL) {
|
||||
TAILQ_FOREACH(wm, &Conf.ignoreq, entry) {
|
||||
if (strncasecmp(wm->title, wname, strlen(wm->title))
|
||||
== 0) {
|
||||
ignore = 1;
|
||||
break;
|
||||
}
|
||||
TAILQ_FOREACH(wm, &Conf.ignoreq, entry) {
|
||||
if (strncasecmp(wm->title, wname, strlen(wm->title)) == 0) {
|
||||
ignore = 1;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
ignore = 1;
|
||||
}
|
||||
|
||||
cc->bwidth = ignore ? 0 : 3;
|
||||
cc->bwidth = ignore ? 0 : Conf.bwidth;
|
||||
cc->flags |= ignore ? CLIENT_IGNORE : 0;
|
||||
}
|
||||
|
||||
struct {
|
||||
char *tag;
|
||||
void (*handler)(struct client_ctx *, void *);
|
||||
int flags;
|
||||
void *argument;
|
||||
static struct {
|
||||
char *tag;
|
||||
void (*handler)(struct client_ctx *, union arg *);
|
||||
int flags;
|
||||
union arg argument;
|
||||
} name_to_kbfunc[] = {
|
||||
{ "lower", kbfunc_client_lower, KBFLAG_NEEDCLIENT, 0 },
|
||||
{ "raise", kbfunc_client_raise, KBFLAG_NEEDCLIENT, 0 },
|
||||
{ "search", kbfunc_client_search, 0, 0 },
|
||||
{ "menusearch", kbfunc_menu_search, 0, 0 },
|
||||
{ "hide", kbfunc_client_hide, KBFLAG_NEEDCLIENT, 0 },
|
||||
{ "cycle", kbfunc_client_cycle, 0, (void *)CWM_CYCLE },
|
||||
{ "rcycle", kbfunc_client_cycle, 0, (void *)CWM_RCYCLE },
|
||||
{ "label", kbfunc_client_label, KBFLAG_NEEDCLIENT, 0 },
|
||||
{ "delete", kbfunc_client_delete, KBFLAG_NEEDCLIENT, 0 },
|
||||
{ "group1", kbfunc_client_group, 0, (void *)1 },
|
||||
{ "group2", kbfunc_client_group, 0, (void *)2 },
|
||||
{ "group3", kbfunc_client_group, 0, (void *)3 },
|
||||
{ "group4", kbfunc_client_group, 0, (void *)4 },
|
||||
{ "group5", kbfunc_client_group, 0, (void *)5 },
|
||||
{ "group6", kbfunc_client_group, 0, (void *)6 },
|
||||
{ "group7", kbfunc_client_group, 0, (void *)7 },
|
||||
{ "group8", kbfunc_client_group, 0, (void *)8 },
|
||||
{ "group9", kbfunc_client_group, 0, (void *)9 },
|
||||
{ "nogroup", kbfunc_client_nogroup, 0, 0 },
|
||||
{ "cyclegroup", kbfunc_client_cyclegroup, 0, (void *)CWM_CYCLEGROUP },
|
||||
{ "rcyclegroup", kbfunc_client_cyclegroup, 0, (void *)CWM_RCYCLEGROUP },
|
||||
{ "grouptoggle", kbfunc_client_grouptoggle, KBFLAG_NEEDCLIENT, 0},
|
||||
{ "maximize", kbfunc_client_maximize, KBFLAG_NEEDCLIENT, 0 },
|
||||
{ "vmaximize", kbfunc_client_vmaximize, KBFLAG_NEEDCLIENT, 0 },
|
||||
{ "reload", kbfunc_reload, 0, 0 },
|
||||
{ "quit", kbfunc_quit_wm, 0, 0 },
|
||||
{ "exec", kbfunc_exec, 0, (void *)CWM_EXEC_PROGRAM },
|
||||
{ "exec_wm", kbfunc_exec, 0, (void *)CWM_EXEC_WM },
|
||||
{ "ssh", kbfunc_ssh, 0, 0 },
|
||||
{ "terminal", kbfunc_term, 0, 0 },
|
||||
{ "lock", kbfunc_lock, 0, 0 },
|
||||
{ "lower", kbfunc_client_lower, KBFLAG_NEEDCLIENT, {0} },
|
||||
{ "raise", kbfunc_client_raise, KBFLAG_NEEDCLIENT, {0} },
|
||||
{ "search", kbfunc_client_search, 0, {0} },
|
||||
{ "menusearch", kbfunc_menu_search, 0, {0} },
|
||||
{ "hide", kbfunc_client_hide, KBFLAG_NEEDCLIENT, {0} },
|
||||
{ "cycle", kbfunc_client_cycle, 0, {.i = CWM_CYCLE} },
|
||||
{ "rcycle", kbfunc_client_cycle, 0, {.i = CWM_RCYCLE} },
|
||||
{ "label", kbfunc_client_label, KBFLAG_NEEDCLIENT, {0} },
|
||||
{ "delete", kbfunc_client_delete, KBFLAG_NEEDCLIENT, {0} },
|
||||
{ "group1", kbfunc_client_group, 0, {.i = 1} },
|
||||
{ "group2", kbfunc_client_group, 0, {.i = 2} },
|
||||
{ "group3", kbfunc_client_group, 0, {.i = 3} },
|
||||
{ "group4", kbfunc_client_group, 0, {.i = 4} },
|
||||
{ "group5", kbfunc_client_group, 0, {.i = 5} },
|
||||
{ "group6", kbfunc_client_group, 0, {.i = 6} },
|
||||
{ "group7", kbfunc_client_group, 0, {.i = 7} },
|
||||
{ "group8", kbfunc_client_group, 0, {.i = 8} },
|
||||
{ "group9", kbfunc_client_group, 0, {.i = 9} },
|
||||
{ "grouponly1", kbfunc_client_grouponly, 0, {.i = 1} },
|
||||
{ "grouponly2", kbfunc_client_grouponly, 0, {.i = 2} },
|
||||
{ "grouponly3", kbfunc_client_grouponly, 0, {.i = 3} },
|
||||
{ "grouponly4", kbfunc_client_grouponly, 0, {.i = 4} },
|
||||
{ "grouponly5", kbfunc_client_grouponly, 0, {.i = 5} },
|
||||
{ "grouponly6", kbfunc_client_grouponly, 0, {.i = 6} },
|
||||
{ "grouponly7", kbfunc_client_grouponly, 0, {.i = 7} },
|
||||
{ "grouponly8", kbfunc_client_grouponly, 0, {.i = 8} },
|
||||
{ "grouponly9", kbfunc_client_grouponly, 0, {.i = 9} },
|
||||
{ "movetogroup1", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
|
||||
{.i = 1} },
|
||||
{ "movetogroup2", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
|
||||
{.i = 2} },
|
||||
{ "movetogroup3", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
|
||||
{.i = 3} },
|
||||
{ "movetogroup4", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
|
||||
{.i = 4} },
|
||||
{ "movetogroup5", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
|
||||
{.i = 5} },
|
||||
{ "movetogroup6", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
|
||||
{.i = 6} },
|
||||
{ "movetogroup7", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
|
||||
{.i = 7} },
|
||||
{ "movetogroup8", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
|
||||
{.i = 8} },
|
||||
{ "movetogroup9", kbfunc_client_movetogroup, KBFLAG_NEEDCLIENT,
|
||||
{.i = 9} },
|
||||
{ "nogroup", kbfunc_client_nogroup, 0, {0} },
|
||||
{ "cyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_CYCLEGROUP} },
|
||||
{ "rcyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_RCYCLEGROUP} },
|
||||
{ "grouptoggle", kbfunc_client_grouptoggle, KBFLAG_NEEDCLIENT, {0}},
|
||||
{ "maximize", kbfunc_client_maximize, KBFLAG_NEEDCLIENT, {0} },
|
||||
{ "vmaximize", kbfunc_client_vmaximize, KBFLAG_NEEDCLIENT, {0} },
|
||||
{ "reload", kbfunc_reload, 0, {0} },
|
||||
{ "quit", kbfunc_quit_wm, 0, {0} },
|
||||
{ "exec", kbfunc_exec, 0, {.i = CWM_EXEC_PROGRAM} },
|
||||
{ "exec_wm", kbfunc_exec, 0, {.i = CWM_EXEC_WM} },
|
||||
{ "ssh", kbfunc_ssh, 0, {0} },
|
||||
{ "terminal", kbfunc_term, 0, {0} },
|
||||
{ "lock", kbfunc_lock, 0, {0} },
|
||||
{ "moveup", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_UP|CWM_MOVE) },
|
||||
{.i = (CWM_UP|CWM_MOVE)} },
|
||||
{ "movedown", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_DOWN|CWM_MOVE) },
|
||||
{.i = (CWM_DOWN|CWM_MOVE)} },
|
||||
{ "moveright", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_RIGHT|CWM_MOVE) },
|
||||
{.i = (CWM_RIGHT|CWM_MOVE)} },
|
||||
{ "moveleft", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_LEFT|CWM_MOVE) },
|
||||
{.i = (CWM_LEFT|CWM_MOVE)} },
|
||||
{ "bigmoveup", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_UP|CWM_MOVE|CWM_BIGMOVE) },
|
||||
{.i = (CWM_UP|CWM_MOVE|CWM_BIGMOVE)} },
|
||||
{ "bigmovedown", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_DOWN|CWM_MOVE|CWM_BIGMOVE) },
|
||||
{.i = (CWM_DOWN|CWM_MOVE|CWM_BIGMOVE)} },
|
||||
{ "bigmoveright", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_RIGHT|CWM_MOVE|CWM_BIGMOVE) },
|
||||
{.i = (CWM_RIGHT|CWM_MOVE|CWM_BIGMOVE)} },
|
||||
{ "bigmoveleft", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_LEFT|CWM_MOVE|CWM_BIGMOVE) },
|
||||
{.i = (CWM_LEFT|CWM_MOVE|CWM_BIGMOVE)} },
|
||||
{ "resizeup", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_UP|CWM_RESIZE) },
|
||||
{.i = (CWM_UP|CWM_RESIZE)} },
|
||||
{ "resizedown", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_DOWN|CWM_RESIZE) },
|
||||
{.i = (CWM_DOWN|CWM_RESIZE)} },
|
||||
{ "resizeright", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_RIGHT|CWM_RESIZE) },
|
||||
{.i = (CWM_RIGHT|CWM_RESIZE)} },
|
||||
{ "resizeleft", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_LEFT|CWM_RESIZE) },
|
||||
{.i = (CWM_LEFT|CWM_RESIZE)} },
|
||||
{ "bigresizeup", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_UP|CWM_RESIZE|CWM_BIGMOVE) },
|
||||
{.i = (CWM_UP|CWM_RESIZE|CWM_BIGMOVE)} },
|
||||
{ "bigresizedown", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_DOWN|CWM_RESIZE|CWM_BIGMOVE) },
|
||||
{.i = (CWM_DOWN|CWM_RESIZE|CWM_BIGMOVE)} },
|
||||
{ "bigresizeright", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_RIGHT|CWM_RESIZE|CWM_BIGMOVE) },
|
||||
{.i = (CWM_RIGHT|CWM_RESIZE|CWM_BIGMOVE)} },
|
||||
{ "bigresizeleft", kbfunc_moveresize, KBFLAG_NEEDCLIENT,
|
||||
(void *)(CWM_LEFT|CWM_RESIZE|CWM_BIGMOVE) },
|
||||
{ "ptrmoveup", kbfunc_moveresize, 0, (void *)(CWM_UP|CWM_PTRMOVE) },
|
||||
{ "ptrmovedown", kbfunc_moveresize, 0, (void *)(CWM_DOWN|CWM_PTRMOVE) },
|
||||
{ "ptrmoveleft", kbfunc_moveresize, 0, (void *)(CWM_LEFT|CWM_PTRMOVE) },
|
||||
{.i = (CWM_LEFT|CWM_RESIZE|CWM_BIGMOVE)} },
|
||||
{ "ptrmoveup", kbfunc_moveresize, 0, {.i = (CWM_UP|CWM_PTRMOVE)} },
|
||||
{ "ptrmovedown", kbfunc_moveresize, 0, {.i = (CWM_DOWN|CWM_PTRMOVE)} },
|
||||
{ "ptrmoveleft", kbfunc_moveresize, 0, {.i = (CWM_LEFT|CWM_PTRMOVE)} },
|
||||
{ "ptrmoveright", kbfunc_moveresize, 0,
|
||||
(void *)(CWM_RIGHT|CWM_PTRMOVE) },
|
||||
{.i = (CWM_RIGHT|CWM_PTRMOVE)} },
|
||||
{ "bigptrmoveup", kbfunc_moveresize, 0,
|
||||
(void *)(CWM_UP|CWM_PTRMOVE|CWM_BIGMOVE) },
|
||||
{.i = (CWM_UP|CWM_PTRMOVE|CWM_BIGMOVE)} },
|
||||
{ "bigptrmovedown", kbfunc_moveresize, 0,
|
||||
(void *)(CWM_DOWN|CWM_PTRMOVE|CWM_BIGMOVE) },
|
||||
{.i = (CWM_DOWN|CWM_PTRMOVE|CWM_BIGMOVE)} },
|
||||
{ "bigptrmoveleft", kbfunc_moveresize, 0,
|
||||
(void *)(CWM_LEFT|CWM_PTRMOVE|CWM_BIGMOVE) },
|
||||
{.i = (CWM_LEFT|CWM_PTRMOVE|CWM_BIGMOVE)} },
|
||||
{ "bigptrmoveright", kbfunc_moveresize, 0,
|
||||
(void *)(CWM_RIGHT|CWM_PTRMOVE|CWM_BIGMOVE) },
|
||||
{ NULL, NULL, 0, 0},
|
||||
{.i = (CWM_RIGHT|CWM_PTRMOVE|CWM_BIGMOVE)} },
|
||||
{ NULL, NULL, 0, {0}},
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -306,7 +409,6 @@ conf_grab(struct conf *c, struct keybinding *kb)
|
||||
|
||||
TAILQ_FOREACH(sc, &Screenq, entry)
|
||||
xu_key_grab(sc->rootwin, kb->modmask, kb->keysym);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -329,7 +431,7 @@ conf_bindname(struct conf *c, char *name, char *binding)
|
||||
char *substring;
|
||||
int iter;
|
||||
|
||||
XCALLOC(current_binding, struct keybinding);
|
||||
current_binding = xcalloc(1, sizeof(*current_binding));
|
||||
|
||||
if (strchr(name, 'C') != NULL &&
|
||||
strchr(name, 'C') < strchr(name, '-'))
|
||||
@@ -387,14 +489,14 @@ conf_bindname(struct conf *c, char *name, char *binding)
|
||||
}
|
||||
|
||||
current_binding->callback = kbfunc_cmdexec;
|
||||
current_binding->argument = xstrdup(binding);
|
||||
current_binding->argument.c = xstrdup(binding);
|
||||
current_binding->flags = 0;
|
||||
conf_grab(c, current_binding);
|
||||
TAILQ_INSERT_TAIL(&c->keybindingq, current_binding, entry);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
conf_unbind(struct conf *c, struct keybinding *unbind)
|
||||
{
|
||||
struct keybinding *key = NULL, *keynxt;
|
||||
@@ -416,7 +518,7 @@ conf_unbind(struct conf *c, struct keybinding *unbind)
|
||||
}
|
||||
}
|
||||
|
||||
struct {
|
||||
static struct {
|
||||
char *tag;
|
||||
void (*handler)(struct client_ctx *, void *);
|
||||
int context;
|
||||
@@ -441,7 +543,7 @@ conf_mousebind(struct conf *c, char *name, char *binding)
|
||||
const char *errstr;
|
||||
int iter;
|
||||
|
||||
XCALLOC(current_binding, struct mousebinding);
|
||||
current_binding = xcalloc(1, sizeof(*current_binding));
|
||||
|
||||
if (strchr(name, 'C') != NULL &&
|
||||
strchr(name, 'C') < strchr(name, '-'))
|
||||
@@ -484,7 +586,7 @@ conf_mousebind(struct conf *c, char *name, char *binding)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
conf_mouseunbind(struct conf *c, struct mousebinding *unbind)
|
||||
{
|
||||
struct mousebinding *mb = NULL, *mbnxt;
|
||||
@@ -528,7 +630,8 @@ conf_grab_mouse(struct client_ctx *cc)
|
||||
break;
|
||||
default:
|
||||
warnx("strange button in mousebinding\n");
|
||||
continue;
|
||||
}
|
||||
xu_btn_grab(cc->pwin, mb->modmask, button);
|
||||
xu_btn_grab(cc->win, mb->modmask, button);
|
||||
}
|
||||
}
|
||||
|
106
cwm.1
106
cwm.1
@@ -14,8 +14,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.\" The following requests are required for all man pages.
|
||||
.Dd $Mdocdate: July 11 2008 $
|
||||
.Dd $Mdocdate: June 18 2009 $
|
||||
.Dt CWM 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -37,29 +36,29 @@ The following notation is used throughout this page:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -offset indent -compact
|
||||
.It Ic C
|
||||
Control
|
||||
Control.
|
||||
.It Ic M
|
||||
Meta
|
||||
Meta.
|
||||
.It Ic S
|
||||
Shift
|
||||
Shift.
|
||||
.It Ic M1
|
||||
Left mouse button
|
||||
Left mouse button.
|
||||
.It Ic M2
|
||||
Middle mouse button
|
||||
Middle mouse button.
|
||||
.It Ic M3
|
||||
Right mouse button
|
||||
Right mouse button.
|
||||
.El
|
||||
.Pp
|
||||
.Nm
|
||||
is very simple in its use.
|
||||
Most of the actions are initiated via keybindings.
|
||||
The current keybindings are described below;
|
||||
Most of the actions are initiated via key bindings.
|
||||
The current key bindings are described below;
|
||||
their functionality is described in more detail later.
|
||||
.Pp
|
||||
.Bl -tag -width "C-M-EscapeXXX" -offset indent -compact
|
||||
.It Ic C-M-Return
|
||||
.Bl -tag -width "CM-EscapeXXXXX" -offset indent -compact
|
||||
.It Ic CM-Return
|
||||
Spawn a new terminal.
|
||||
.It Ic C-M-Delete
|
||||
.It Ic CM-Delete
|
||||
Lock the screen.
|
||||
.It Ic M-Return
|
||||
Hide current window.
|
||||
@@ -71,50 +70,50 @@ Raise current window.
|
||||
Search for windows.
|
||||
.It Ic C-/
|
||||
Search for applications.
|
||||
.It Ic C-M-n
|
||||
.It Ic CM-n
|
||||
Label current window.
|
||||
.It Ic M-Tab
|
||||
Cycle through currently visible windows.
|
||||
.It Ic M-S-Tab
|
||||
.It Ic MS-Tab
|
||||
Reverse cycle through currently visible windows.
|
||||
.It Ic C-M-x
|
||||
.It Ic CM-x
|
||||
Delete current window.
|
||||
.It Ic C-M-[n]
|
||||
.It Ic CM-[n]
|
||||
Select group n, where n is 1-9.
|
||||
.It Ic C-M-0
|
||||
.It Ic CM-0
|
||||
Select all groups.
|
||||
.It Ic C-M-g
|
||||
.It Ic CM-g
|
||||
Toggle group membership of current window.
|
||||
.It Ic M-Right
|
||||
Cycle through active groups.
|
||||
.It Ic M-Left
|
||||
Reverse cycle through active groups.
|
||||
.It Ic C-M-f
|
||||
.It Ic CM-f
|
||||
Toggle full-screen size of current window.
|
||||
.It Ic C-M-=
|
||||
.It Ic CM-=
|
||||
Toggle vertical maximization of current window.
|
||||
.It Ic M-?
|
||||
Spawn
|
||||
.Dq Exec program
|
||||
.Dq exec program
|
||||
dialog.
|
||||
.It Ic M-.
|
||||
Spawn
|
||||
.Dq Ssh to
|
||||
.Dq ssh to
|
||||
dialog.
|
||||
This parses
|
||||
.Pa $HOME/.ssh/known_hosts
|
||||
to provide host auto-completion.
|
||||
.Xr ssh 1
|
||||
will be executed via the configured terminal emulator.
|
||||
.It Ic C-M-w
|
||||
.It Ic CM-w
|
||||
Spawn
|
||||
.Dq Exec WindowManager
|
||||
.Dq exec WindowManager
|
||||
dialog; allows you to switch from
|
||||
.Nm
|
||||
to another window manager without restarting the X server.
|
||||
.It Ic C-M-S-r
|
||||
.It Ic CMS-r
|
||||
Reload configuration.
|
||||
.It Ic C-M-S-q
|
||||
.It Ic CMS-q
|
||||
Quit
|
||||
.Nm .
|
||||
.El
|
||||
@@ -122,15 +121,15 @@ Quit
|
||||
The mouse bindings are also important, they are:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -offset indent -compact
|
||||
.It M-M1
|
||||
.It Ic M-M1
|
||||
Move current window.
|
||||
.It C-M-M1
|
||||
.It Ic CM-M1
|
||||
Toggle group membership of current window.
|
||||
.It M-M2
|
||||
.It Ic M-M2
|
||||
Resize current window
|
||||
.It M-M3
|
||||
.It Ic M-M3
|
||||
Lower current window.
|
||||
.It CMS-M3
|
||||
.It Ic CMS-M3
|
||||
Hide current window.
|
||||
.El
|
||||
.Pp
|
||||
@@ -146,22 +145,34 @@ Specify the display to use.
|
||||
.El
|
||||
.Sh POINTER MOVEMENT
|
||||
The pointer can be moved with the use of the keyboard through bindings.
|
||||
C-[UP|DOWN|LEFT|RIGHT] moves the pointer a small amount, while
|
||||
C-shift-[UP|DOWN|LEFT|RIGHT] moves the pointer a larger amount.
|
||||
.Ic C-[Up|Down|Left|Right]
|
||||
moves the pointer a small amount, while
|
||||
.Ic CS-[Up|Down|Left|Right]
|
||||
moves the pointer a larger amount.
|
||||
For example, to move the pointer to the left by a small amount,
|
||||
press C-LEFT.
|
||||
To move the pointer down by a larger amount, press C-shift-DOWN.
|
||||
press
|
||||
.Ic C-Left .
|
||||
To move the pointer down by a larger amount, press
|
||||
.Ic CS-Down .
|
||||
.Sh WINDOW MOVEMENT AND RESIZING
|
||||
.Nm
|
||||
windows can be moved with the use of the keyboard through Vi-like bindings.
|
||||
M-[hjkl] moves the current window a small amount, while M-shift-[hjkl] moves
|
||||
the current window a larger amount.
|
||||
For example, to move the current window to the left a small amount, press M-h.
|
||||
To move the current window down by a larger amount, press M-shift-j.
|
||||
windows can be moved with the use of the keyboard through
|
||||
.Cm vi Ns -like
|
||||
bindings.
|
||||
.Ic M-[hjkl]
|
||||
moves the current window a small amount, while
|
||||
.Ic MS-[hjkl]
|
||||
moves the current window a larger amount.
|
||||
For example, to move the current window to the left a small amount, press
|
||||
.Ic M-h .
|
||||
To move the current window down by a larger amount, press
|
||||
.Ic MS-j .
|
||||
.Pp
|
||||
Similarly, windows may be resized with the same keybindings with the addition
|
||||
Similarly, windows may be resized with the same key bindings with the addition
|
||||
of the Control key.
|
||||
C-M-[hjkl] resizes the window a small amount and C-M-shift-[hjkl]
|
||||
.Ic CM-[hjkl]
|
||||
resizes the window a small amount and
|
||||
.Ic CMS-[hjkl]
|
||||
resizes by a larger increment.
|
||||
.Sh SEARCH
|
||||
.Nm
|
||||
@@ -182,7 +193,7 @@ The window is the currently focused window.
|
||||
The window is hidden.
|
||||
.El
|
||||
.Pp
|
||||
The following keybindings may be used to navigate the result list:
|
||||
The following key bindings may be used to navigate the result list:
|
||||
.Pp
|
||||
.Bl -tag -width "[Down] or C-s or M-j" -offset indent -compact
|
||||
.It Ic [Down], C-s No or Ic M-j
|
||||
@@ -218,13 +229,13 @@ and a red border will be shown on those just removed.
|
||||
Menus are recalled by clicking the mouse on the root window:
|
||||
.Pp
|
||||
.Bl -tag -width 10n -offset -indent -compact
|
||||
.It M1
|
||||
.It Ic M1
|
||||
Show list of currently hidden windows.
|
||||
Clicking on an item will unhide that window.
|
||||
.It M2
|
||||
.It Ic M2
|
||||
Show list of currently defined groups.
|
||||
Clicking on an item will hide/unhide that group.
|
||||
.It M3
|
||||
.It Ic M3
|
||||
Show list of applications as defined in
|
||||
.Pa ~/.cwmrc .
|
||||
Clicking on an item will spawn that application.
|
||||
@@ -240,6 +251,7 @@ option is given.
|
||||
.Sh FILES
|
||||
.Bl -tag -width Ds
|
||||
.It Pa ~/.cwmrc
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr cwmrc 5
|
||||
.Sh AUTHORS
|
||||
|
147
cwmrc.5
147
cwmrc.5
@@ -14,8 +14,7 @@
|
||||
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
.\"
|
||||
.\" The following requests are required for all man pages.
|
||||
.Dd $Mdocdate: July 11 2008 $
|
||||
.Dd $Mdocdate: May 17 2009 $
|
||||
.Dt CWMRC 5
|
||||
.Os
|
||||
.Sh NAME
|
||||
@@ -35,7 +34,7 @@ properties, where
|
||||
.Ar group
|
||||
is a number between 0 and 9.
|
||||
If the group number is 0, then the window will not be grouped; this to
|
||||
allow for
|
||||
allow for
|
||||
.Dq sticky
|
||||
windows in sticky group mode.
|
||||
.Pp
|
||||
@@ -81,6 +80,22 @@ can be used to remove the named keybinding.
|
||||
This can be used to remove a binding which conflicts with an
|
||||
application.
|
||||
.Pp
|
||||
.It Ic borderwidth Ar pixels
|
||||
Set the window border width to
|
||||
.Ar pixels .
|
||||
.Pp
|
||||
.It Ic color activeborder Ar color
|
||||
Set the color of the active border.
|
||||
.Pp
|
||||
.It Ic color groupborder Ar color
|
||||
Set the color of the border while grouping a window.
|
||||
.Pp
|
||||
.It Ic color inactiveborder Ar color
|
||||
Set the color of the inactive border.
|
||||
.Pp
|
||||
.It Ic color ungroupborder Ar color
|
||||
Set the color of the border while ungrouping a window.
|
||||
.Pp
|
||||
.It Ic command Ar name Ar path
|
||||
Every
|
||||
.Ar name
|
||||
@@ -123,8 +138,9 @@ can be used for applications such as
|
||||
where the user may wish to remain visible.
|
||||
.Pp
|
||||
.It Ic ignore Ar windowname
|
||||
Ignore drawing borders around a window with the name
|
||||
.Ar windowname .
|
||||
Ignore windows with the name
|
||||
.Ar windowname
|
||||
when drawing borders and cycling through windows.
|
||||
.Pp
|
||||
.It Ic mousebind Ar buttons Ar command
|
||||
Cause the creation of a mouse binding, or replacement of a default
|
||||
@@ -135,7 +151,7 @@ The modifier keys come first, followed by a
|
||||
The following modifiers are recognised:
|
||||
.Pp
|
||||
.Bl -tag -width Ds -offset indent -compact
|
||||
.It C
|
||||
.It C
|
||||
The Control key.
|
||||
.It M
|
||||
The Meta key.
|
||||
@@ -154,9 +170,9 @@ should be followed by number:
|
||||
.It 1
|
||||
Left mouse button.
|
||||
.It 2
|
||||
Right mouse button.
|
||||
.It 3
|
||||
Middle mouse button.
|
||||
.It 3
|
||||
Right mouse button.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
@@ -165,6 +181,11 @@ may be taken from the
|
||||
.Sx MOUSEBIND COMMAND LIST
|
||||
(see below).
|
||||
.Pp
|
||||
.It Ic moveamount Ar pixels
|
||||
Set a default size for the keyboard movement bindings,
|
||||
in pixels.
|
||||
The default is 1.
|
||||
.Pp
|
||||
.It Ic sticky Ic yes Ns \&| Ns Ic no
|
||||
Toggle sticky group mode.
|
||||
The default behavior for new windows is to not assign any group.
|
||||
@@ -199,6 +220,12 @@ ignore xclock
|
||||
bind CM-r label
|
||||
bind CS-Return "xterm -e top"
|
||||
bind 4-o unmap
|
||||
bind M-1 grouponly1
|
||||
bind M-2 grouponly2
|
||||
bind M-3 grouponly3
|
||||
bind MS-1 movetogroup1
|
||||
bind MS-2 movetogroup2
|
||||
bind MS-3 movetogroup3
|
||||
|
||||
# Mousebindings
|
||||
mousebind M-2 window_lower
|
||||
@@ -233,10 +260,16 @@ Launch
|
||||
menu.
|
||||
.It group[n]
|
||||
Select group n, where n is 1-9.
|
||||
.It grouponly[n]
|
||||
Like
|
||||
.Ar group[n]
|
||||
but also hides the other groups.
|
||||
.It nogroup
|
||||
Select all groups.
|
||||
.It grouptoggle
|
||||
Toggle group membership of current window.
|
||||
.It movetogroup[n]
|
||||
Hide current window from display and move to group n, where n is 1-9.
|
||||
.It cyclegroup
|
||||
Forward cycle through groups.
|
||||
.It rcyclegroup
|
||||
@@ -260,53 +293,101 @@ Maximize current window full-screen.
|
||||
.It vmaximize
|
||||
Maximize current window vertically.
|
||||
.It moveup
|
||||
Move window 1 pixel up.
|
||||
Move window
|
||||
.Ar moveamount
|
||||
pixels up.
|
||||
.It movedown
|
||||
Move window 1 pixel down.
|
||||
Move window
|
||||
.Ar moveamount
|
||||
pixels down.
|
||||
.It moveright
|
||||
Move window 1 pixel right.
|
||||
Move window
|
||||
.Ar moveamount
|
||||
pixels right.
|
||||
.It moveleft
|
||||
Move window 1 pixel left.
|
||||
Move window
|
||||
.Ar moveamount
|
||||
pixels left.
|
||||
.It bigmoveup
|
||||
Move window 10 pixels up.
|
||||
Move window 10 times
|
||||
.Ar moveamount
|
||||
pixels up.
|
||||
.It bigmovedown
|
||||
Move window 10 pixels down.
|
||||
Move window 10 times
|
||||
.Ar moveamount
|
||||
pixels down.
|
||||
.It bigmoveright
|
||||
Move window 10 pixels right.
|
||||
Move window 10 times
|
||||
.Ar moveamount
|
||||
pixels right.
|
||||
.It bigmoveleft
|
||||
Move window 10 pixels left.
|
||||
Move window 10 times
|
||||
.Ar moveamount
|
||||
pixels left.
|
||||
.It resizeup
|
||||
Resize window 1 pixel up.
|
||||
Resize window
|
||||
.Ar moveamount
|
||||
pixels up.
|
||||
.It resizedown
|
||||
Resize window 1 pixel down.
|
||||
Resize window
|
||||
.Ar moveamount
|
||||
pixels down.
|
||||
.It resizeright
|
||||
Resize window 1 pixel right.
|
||||
Resize window
|
||||
.Ar moveamount
|
||||
pixels right.
|
||||
.It resizeleft
|
||||
Resize window 1 pixel left.
|
||||
Resize window
|
||||
.Ar moveamount
|
||||
pixels left.
|
||||
.It bigresizeup
|
||||
Resize window 10 pixels up.
|
||||
Resize window 10 times
|
||||
.Ar moveamount
|
||||
pixels up.
|
||||
.It bigresizedown
|
||||
Resize window 10 pixels down.
|
||||
Resize window 10 times
|
||||
.Ar moveamount
|
||||
pixels down.
|
||||
.It bigresizeright
|
||||
Resize window 10 pixels right.
|
||||
Resize window 10 times
|
||||
.Ar moveamount
|
||||
pixels right.
|
||||
.It bigresizeleft
|
||||
Resize window 10 pixels left.
|
||||
Resize window 10 times
|
||||
.Ar moveamount
|
||||
pixels left.
|
||||
.It ptrmoveup
|
||||
Move pointer 1 pixel up.
|
||||
Move pointer
|
||||
.Ar moveamount
|
||||
pixels up.
|
||||
.It ptrmovedown
|
||||
Move pointer 1 pixel down.
|
||||
Move pointer
|
||||
.Ar moveamount
|
||||
pixels down.
|
||||
.It ptrmoveright
|
||||
Move pointer 1 pixel right.
|
||||
Move pointer
|
||||
.Ar moveamount
|
||||
pixels right.
|
||||
.It ptrmoveleft
|
||||
Move pointer 1 pixel left.
|
||||
Move pointer
|
||||
.Ar moveamount
|
||||
pixels left.
|
||||
.It bigptrmoveup
|
||||
Move pointer 10 pixels up.
|
||||
Move pointer 10 times
|
||||
.Ar moveamount
|
||||
pixels up.
|
||||
.It bigptrmovedown
|
||||
Move pointer 10 pixels down.
|
||||
Move pointer 10 times
|
||||
.Ar moveamount
|
||||
pixels down.
|
||||
.It bigptrmoveright
|
||||
Move pointer 10 pixels right.
|
||||
Move pointer 10 times
|
||||
.Ar moveamount
|
||||
pixels right.
|
||||
.It bigptrmoveleft
|
||||
Move pointer 10 pixels left.
|
||||
Move pointer 10 times
|
||||
.Ar moveamount
|
||||
pixels left.
|
||||
.El
|
||||
.Sh MOUSEBIND COMMAND LIST
|
||||
.Bl -tag -width 18n -compact
|
||||
@@ -323,7 +404,7 @@ Toggle group membership of current window.
|
||||
.It menu_group
|
||||
Launch group list.
|
||||
.It menu_unhide
|
||||
Launch group list.
|
||||
Launch hidden window list.
|
||||
.It menu_cmd
|
||||
Launch command list.
|
||||
.El
|
||||
|
16
font.c
16
font.c
@@ -22,22 +22,14 @@
|
||||
void
|
||||
font_init(struct screen_ctx *sc)
|
||||
{
|
||||
XColor xcolor, tmp;
|
||||
|
||||
sc->xftdraw = XftDrawCreate(X_Dpy, sc->rootwin,
|
||||
DefaultVisual(X_Dpy, sc->which), DefaultColormap(X_Dpy, sc->which));
|
||||
if (sc->xftdraw == NULL)
|
||||
errx(1, "XftDrawCreate");
|
||||
|
||||
if (!XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, sc->which),
|
||||
"black", &xcolor, &tmp))
|
||||
errx(1, "XAllocNamedColor");
|
||||
|
||||
sc->xftcolor.color.red = xcolor.red;
|
||||
sc->xftcolor.color.green = xcolor.green;
|
||||
sc->xftcolor.color.blue = xcolor.blue;
|
||||
sc->xftcolor.color.alpha = 0x00ff00;
|
||||
sc->xftcolor.pixel = xcolor.pixel;
|
||||
if (!XftColorAllocName(X_Dpy, DefaultVisual(X_Dpy, sc->which),
|
||||
DefaultColormap(X_Dpy, sc->which), "black", &sc->xftcolor))
|
||||
errx(1, "XftColorAllocName");
|
||||
}
|
||||
|
||||
int
|
||||
@@ -68,7 +60,7 @@ font_make(struct screen_ctx *sc, const char *name)
|
||||
FcPattern *pat, *patx;
|
||||
XftResult res;
|
||||
|
||||
if ((pat = FcNameParse(name)) == NULL)
|
||||
if ((pat = FcNameParse((const FcChar8*)name)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if ((patx = XftFontMatch(X_Dpy, sc->which, pat, &res)) != NULL)
|
||||
|
184
grab.c
184
grab.c
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* calmwm - the calm window manager
|
||||
*
|
||||
* Copyright (c) 2004 Marius Aamodt Eriksen <marius@monkey.org>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include "headers.h"
|
||||
#include "calmwm.h"
|
||||
|
||||
static int _sweepcalc(struct client_ctx *, int, int, int, int);
|
||||
|
||||
#define ADJUST_HEIGHT(cc, dy) ((cc->geom.height - cc->geom.min_dy)/ dy)
|
||||
#define ADJUST_WIDTH(cc, dx) ((cc->geom.width - cc->geom.min_dx)/ dx)
|
||||
|
||||
void
|
||||
grab_sweep_draw(struct client_ctx *cc, int dx, int dy)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
char asize[10]; /* fits "nnnnxnnnn\0" */
|
||||
int wide, height, wide_size, wide_name;
|
||||
int x = cc->geom.x, y = cc->geom.y;
|
||||
|
||||
snprintf(asize, sizeof(asize), "%dx%d",
|
||||
ADJUST_WIDTH(cc, dx), ADJUST_HEIGHT(cc, dy));
|
||||
wide_size = font_width(asize, strlen(asize)) + 4;
|
||||
wide_name = font_width(cc->name, strlen(cc->name)) + 4;
|
||||
wide = MAX(wide_size, wide_name);
|
||||
height = font_ascent() + font_descent() + 1;
|
||||
|
||||
XMoveResizeWindow(X_Dpy, sc->menuwin, x, y, wide, height * 2);
|
||||
XMapWindow(X_Dpy, sc->menuwin);
|
||||
XReparentWindow(X_Dpy, sc->menuwin, cc->win, 0, 0);
|
||||
XClearWindow(X_Dpy, sc->menuwin);
|
||||
font_draw(sc, cc->name, strlen(cc->name), sc->menuwin,
|
||||
2, font_ascent() + 1);
|
||||
font_draw(sc, asize, strlen(asize), sc->menuwin,
|
||||
wide / 2 - wide_size / 2, height + font_ascent() + 1);
|
||||
}
|
||||
|
||||
void
|
||||
grab_sweep(struct client_ctx *cc)
|
||||
{
|
||||
XEvent ev;
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
int x = cc->geom.x, y = cc->geom.y, dx, dy;
|
||||
|
||||
dx = MAX(1, cc->size->width_inc);
|
||||
dy = MAX(1, cc->size->height_inc);
|
||||
|
||||
client_raise(cc);
|
||||
client_ptrsave(cc);
|
||||
|
||||
if (xu_ptr_grab(sc->rootwin, MouseMask, Cursor_resize) < 0)
|
||||
return;
|
||||
|
||||
xu_ptr_setpos(cc->win, cc->geom.width, cc->geom.height);
|
||||
grab_sweep_draw(cc, dx, dy);
|
||||
|
||||
for (;;) {
|
||||
/* Look for changes in ptr position. */
|
||||
XMaskEvent(X_Dpy, MouseMask|ExposureMask, &ev);
|
||||
|
||||
switch (ev.type) {
|
||||
case Expose:
|
||||
client_draw_border(cc);
|
||||
break;
|
||||
case MotionNotify:
|
||||
if (_sweepcalc(cc, x, y, ev.xmotion.x, ev.xmotion.y))
|
||||
/* Recompute window output */
|
||||
grab_sweep_draw(cc, dx, dy);
|
||||
|
||||
XMoveResizeWindow(X_Dpy, cc->pwin,
|
||||
cc->geom.x - cc->bwidth,
|
||||
cc->geom.y - cc->bwidth,
|
||||
cc->geom.width + cc->bwidth*2,
|
||||
cc->geom.height + cc->bwidth*2);
|
||||
XMoveResizeWindow(X_Dpy, cc->win,
|
||||
cc->bwidth, cc->bwidth,
|
||||
cc->geom.width, cc->geom.height);
|
||||
|
||||
client_do_shape(cc);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
XUnmapWindow(X_Dpy, sc->menuwin);
|
||||
XReparentWindow(X_Dpy, sc->menuwin, sc->rootwin, 0, 0);
|
||||
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;
|
||||
client_ptrwarp(cc);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
grab_drag(struct client_ctx *cc)
|
||||
{
|
||||
XEvent ev;
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
int x = cc->geom.x, y = cc->geom.y, xm, ym;
|
||||
|
||||
client_raise(cc);
|
||||
|
||||
if (xu_ptr_grab(sc->rootwin, MouseMask, Cursor_move) < 0)
|
||||
return;
|
||||
|
||||
xu_ptr_getpos(sc->rootwin, &xm, &ym);
|
||||
|
||||
for (;;) {
|
||||
XMaskEvent(X_Dpy, MouseMask|ExposureMask, &ev);
|
||||
|
||||
switch (ev.type) {
|
||||
case Expose:
|
||||
client_draw_border(cc);
|
||||
break;
|
||||
case MotionNotify:
|
||||
cc->geom.x = x + (ev.xmotion.x - xm);
|
||||
cc->geom.y = y + (ev.xmotion.y - ym);
|
||||
|
||||
XMoveWindow(X_Dpy, cc->pwin,
|
||||
cc->geom.x - cc->bwidth, cc->geom.y - cc->bwidth);
|
||||
|
||||
break;
|
||||
case ButtonRelease:
|
||||
xu_ptr_ungrab();
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static int
|
||||
_sweepcalc(struct client_ctx *cc, int x, int y, int motionx, int motiony)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
width = cc->geom.width;
|
||||
height = cc->geom.height;
|
||||
|
||||
cc->geom.width = abs(x - motionx);
|
||||
cc->geom.height = abs(y - motiony);
|
||||
|
||||
if (cc->size->flags & PResizeInc) {
|
||||
cc->geom.width -=
|
||||
(cc->geom.width - cc->geom.min_dx) % cc->size->width_inc;
|
||||
cc->geom.height -=
|
||||
(cc->geom.height - cc->geom.min_dy) % cc->size->height_inc;
|
||||
}
|
||||
|
||||
if (cc->size->flags & PMinSize) {
|
||||
cc->geom.width = MAX(cc->geom.width, cc->size->min_width);
|
||||
cc->geom.height = MAX(cc->geom.height, cc->size->min_height);
|
||||
}
|
||||
|
||||
if (cc->size->flags & PMaxSize) {
|
||||
cc->geom.width = MIN(cc->geom.width, cc->size->max_width);
|
||||
cc->geom.height = MIN(cc->geom.height, cc->size->max_height);
|
||||
}
|
||||
|
||||
cc->geom.x = x <= motionx ? x : x - cc->geom.width;
|
||||
cc->geom.y = y <= motiony ? y : y - cc->geom.height;
|
||||
|
||||
return (width != cc->geom.width || height != cc->geom.height);
|
||||
}
|
128
group.c
128
group.c
@@ -24,16 +24,27 @@
|
||||
|
||||
#define CALMWM_NGROUPS 9
|
||||
|
||||
static void group_add(struct group_ctx *, struct client_ctx *);
|
||||
static void group_remove(struct client_ctx *);
|
||||
static void group_hide(struct group_ctx *);
|
||||
static void group_show(struct group_ctx *);
|
||||
static void group_fix_hidden_state(struct group_ctx *);
|
||||
|
||||
struct group_ctx *Group_active = NULL;
|
||||
struct group_ctx Groups[CALMWM_NGROUPS];
|
||||
int Grouphideall = 0;
|
||||
struct group_ctx_q Groupq;
|
||||
|
||||
const char *shortcut_to_name[] = {
|
||||
"nogroup", "one", "two", "three", "four", "five", "six",
|
||||
"seven", "eight", "nine"
|
||||
};
|
||||
|
||||
static void
|
||||
_group_add(struct group_ctx *gc, struct client_ctx *cc)
|
||||
group_add(struct group_ctx *gc, struct client_ctx *cc)
|
||||
{
|
||||
if (cc == NULL || gc == NULL)
|
||||
errx(1, "_group_add: a ctx is NULL");
|
||||
errx(1, "group_add: a ctx is NULL");
|
||||
|
||||
if (cc->group == gc)
|
||||
return;
|
||||
@@ -41,22 +52,29 @@ _group_add(struct group_ctx *gc, struct client_ctx *cc)
|
||||
if (cc->group != NULL)
|
||||
TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
|
||||
|
||||
XChangeProperty(X_Dpy, cc->win, _CWM_GRP, XA_STRING,
|
||||
8, PropModeReplace, gc->name, strlen(gc->name));
|
||||
|
||||
TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry);
|
||||
cc->group = gc;
|
||||
}
|
||||
|
||||
static void
|
||||
_group_remove(struct client_ctx *cc)
|
||||
group_remove(struct client_ctx *cc)
|
||||
{
|
||||
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, _CWM_GRP, XA_STRING, 8,
|
||||
PropModeReplace, shortcut_to_name[0],
|
||||
strlen(shortcut_to_name[0]));
|
||||
|
||||
TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
|
||||
cc->group = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
_group_hide(struct group_ctx *gc)
|
||||
group_hide(struct group_ctx *gc)
|
||||
{
|
||||
struct client_ctx *cc;
|
||||
|
||||
@@ -74,7 +92,7 @@ _group_hide(struct group_ctx *gc)
|
||||
}
|
||||
|
||||
static void
|
||||
_group_show(struct group_ctx *gc)
|
||||
group_show(struct group_ctx *gc)
|
||||
{
|
||||
struct client_ctx *cc;
|
||||
Window *winlist;
|
||||
@@ -88,7 +106,7 @@ _group_show(struct group_ctx *gc)
|
||||
* top-to-bottom.
|
||||
*/
|
||||
TAILQ_FOREACH(cc, &gc->clients, group_entry) {
|
||||
winlist[gc->highstack - cc->stackingorder] = cc->pwin;
|
||||
winlist[gc->highstack - cc->stackingorder] = cc->win;
|
||||
client_unhide(cc);
|
||||
}
|
||||
|
||||
@@ -121,12 +139,24 @@ group_init(void)
|
||||
TAILQ_INIT(&Groups[i].clients);
|
||||
Groups[i].hidden = 0;
|
||||
Groups[i].shortcut = i + 1;
|
||||
Groups[i].name = shortcut_to_name[Groups[i].shortcut];
|
||||
TAILQ_INSERT_TAIL(&Groupq, &Groups[i], entry);
|
||||
}
|
||||
|
||||
Group_active = &Groups[0];
|
||||
}
|
||||
|
||||
void
|
||||
group_movetogroup(struct client_ctx *cc, int idx)
|
||||
{
|
||||
if (idx < 0 || idx >= CALMWM_NGROUPS)
|
||||
err(1, "group_movetogroup: index out of range (%d)", idx);
|
||||
|
||||
if(Group_active != &Groups[idx])
|
||||
client_hide(cc);
|
||||
group_add(&Groups[idx], cc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Colouring for groups upon add/remove.
|
||||
*/
|
||||
@@ -138,11 +168,11 @@ group_sticky_toggle_enter(struct client_ctx *cc)
|
||||
gc = Group_active;
|
||||
|
||||
if (gc == cc->group) {
|
||||
_group_remove(cc);
|
||||
cc->highlight = CLIENT_HIGHLIGHT_RED;
|
||||
group_remove(cc);
|
||||
cc->highlight = CLIENT_HIGHLIGHT_UNGROUP;
|
||||
} else {
|
||||
_group_add(gc, cc);
|
||||
cc->highlight = CLIENT_HIGHLIGHT_BLUE;
|
||||
group_add(gc, cc);
|
||||
cc->highlight = CLIENT_HIGHLIGHT_GROUP;
|
||||
}
|
||||
|
||||
client_draw_border(cc);
|
||||
@@ -156,13 +186,10 @@ group_sticky_toggle_exit(struct client_ctx *cc)
|
||||
}
|
||||
|
||||
/*
|
||||
* selection list display
|
||||
* if group_hidetoggle would produce no effect, toggle the group's hidden state
|
||||
*/
|
||||
|
||||
/* if group_hidetoggle would produce no effect, toggle the group's hidden state
|
||||
*/
|
||||
void
|
||||
_group_fix_hidden_state(struct group_ctx *gc)
|
||||
static void
|
||||
group_fix_hidden_state(struct group_ctx *gc)
|
||||
{
|
||||
struct client_ctx *cc;
|
||||
int same = 0;
|
||||
@@ -186,17 +213,33 @@ group_hidetoggle(int idx)
|
||||
|
||||
gc = &Groups[idx];
|
||||
|
||||
_group_fix_hidden_state(gc);
|
||||
group_fix_hidden_state(gc);
|
||||
|
||||
if (gc->hidden)
|
||||
_group_show(gc);
|
||||
group_show(gc);
|
||||
else {
|
||||
_group_hide(gc);
|
||||
group_hide(gc);
|
||||
if (TAILQ_EMPTY(&gc->clients))
|
||||
Group_active = gc;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
group_only(int idx)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (idx < 0 || idx >= CALMWM_NGROUPS)
|
||||
err(1, "group_only: index out of range (%d)", idx);
|
||||
|
||||
for (i = 0; i < CALMWM_NGROUPS; i++) {
|
||||
if (i == idx)
|
||||
group_show(&Groups[i]);
|
||||
else
|
||||
group_hide(&Groups[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Cycle through active groups. If none exist, then just stay put.
|
||||
*/
|
||||
@@ -220,16 +263,16 @@ group_cycle(int reverse)
|
||||
if (!TAILQ_EMPTY(&gc->clients) && showgroup == NULL)
|
||||
showgroup = gc;
|
||||
else if (!gc->hidden)
|
||||
_group_hide(gc);
|
||||
group_hide(gc);
|
||||
}
|
||||
|
||||
if (showgroup == NULL)
|
||||
return;
|
||||
|
||||
_group_hide(Group_active);
|
||||
group_hide(Group_active);
|
||||
|
||||
if (showgroup->hidden)
|
||||
_group_show(showgroup);
|
||||
group_show(showgroup);
|
||||
else
|
||||
Group_active = showgroup;
|
||||
}
|
||||
@@ -261,7 +304,7 @@ group_menu(XButtonEvent *e)
|
||||
if (TAILQ_EMPTY(&gc->clients))
|
||||
continue;
|
||||
|
||||
XCALLOC(mi, struct menu);
|
||||
mi = xcalloc(1, sizeof(*mi));
|
||||
if (gc->hidden)
|
||||
snprintf(mi->text, sizeof(mi->text), "%d: [%s]",
|
||||
gc->shortcut, shortcut_to_name[gc->shortcut]);
|
||||
@@ -282,10 +325,7 @@ group_menu(XButtonEvent *e)
|
||||
|
||||
gc = (struct group_ctx *)mi->ctx;
|
||||
|
||||
if (gc->hidden)
|
||||
_group_show(gc);
|
||||
else
|
||||
_group_hide(gc);
|
||||
(gc->hidden) ? group_show(gc) : group_hide(gc);
|
||||
|
||||
cleanup:
|
||||
while ((mi = TAILQ_FIRST(&menuq)) != NULL) {
|
||||
@@ -301,15 +341,12 @@ group_alltoggle(void)
|
||||
|
||||
for (i = 0; i < CALMWM_NGROUPS; i++) {
|
||||
if (Grouphideall)
|
||||
_group_show(&Groups[i]);
|
||||
group_show(&Groups[i]);
|
||||
else
|
||||
_group_hide(&Groups[i]);
|
||||
group_hide(&Groups[i]);
|
||||
}
|
||||
|
||||
if (Grouphideall)
|
||||
Grouphideall = 0;
|
||||
else
|
||||
Grouphideall = 1;
|
||||
Grouphideall = (Grouphideall) ? 0 : 1;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -317,16 +354,23 @@ group_autogroup(struct client_ctx *cc)
|
||||
{
|
||||
struct autogroupwin *aw;
|
||||
struct group_ctx *gc;
|
||||
unsigned char *grpstr = NULL;
|
||||
char group[CALMWM_MAXNAMELEN];
|
||||
|
||||
if (cc->app_class == NULL || cc->app_name == NULL)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(aw, &Conf.autogroupq, entry) {
|
||||
if (strcmp(aw->class, cc->app_class) == 0 &&
|
||||
(aw->name == NULL || strcmp(aw->name, cc->app_name) == 0)) {
|
||||
strlcpy(group, aw->group, sizeof(group));
|
||||
break;
|
||||
if (xu_getprop(cc, _CWM_GRP, XA_STRING,
|
||||
(CALMWM_MAXNAMELEN - 1)/sizeof(long), &grpstr) > 0) {
|
||||
strlcpy(group, grpstr, sizeof(group));
|
||||
XFree(grpstr);
|
||||
} else {
|
||||
TAILQ_FOREACH(aw, &Conf.autogroupq, entry) {
|
||||
if (strcmp(aw->class, cc->app_class) == 0 &&
|
||||
(aw->name == NULL ||
|
||||
strcmp(aw->name, cc->app_name) == 0)) {
|
||||
strlcpy(group, aw->group, sizeof(group));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,12 +379,12 @@ group_autogroup(struct client_ctx *cc)
|
||||
|
||||
TAILQ_FOREACH(gc, &Groupq, entry) {
|
||||
if (strcmp(shortcut_to_name[gc->shortcut], group) == 0) {
|
||||
_group_add(gc, cc);
|
||||
group_add(gc, cc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Conf.flags & CONF_STICKY_GROUPS)
|
||||
_group_add(Group_active, cc);
|
||||
group_add(Group_active, cc);
|
||||
|
||||
}
|
||||
|
36
headers.h
36
headers.h
@@ -21,35 +21,33 @@
|
||||
#ifndef _CALMWM_HEADERS_H_
|
||||
#define _CALMWM_HEADERS_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <sys/queue.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <getopt.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/extensions/shape.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/keysym.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Intrinsic.h>
|
||||
#include <X11/Xos.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xft/Xft.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xos.h>
|
||||
#include <X11/Xproto.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
#include <X11/keysym.h>
|
||||
|
||||
#endif /* _CALMWM_HEADERS_H_ */
|
||||
|
5
input.c
5
input.c
@@ -29,10 +29,7 @@ input_keycodetrans(KeyCode kc, u_int state, enum ctltype *ctl, char *chr)
|
||||
*ctl = CTL_NONE;
|
||||
*chr = '\0';
|
||||
|
||||
if (state & ShiftMask)
|
||||
ks = XKeycodeToKeysym(X_Dpy, kc, 1);
|
||||
else
|
||||
ks = XKeycodeToKeysym(X_Dpy, kc, 0);
|
||||
ks = XKeycodeToKeysym(X_Dpy, kc, (state & ShiftMask) ? 1 : 0);
|
||||
|
||||
/* Look for control characters. */
|
||||
switch (ks) {
|
||||
|
102
kbfunc.c
102
kbfunc.c
@@ -25,18 +25,17 @@
|
||||
|
||||
#define KNOWN_HOSTS ".ssh/known_hosts"
|
||||
#define HASH_MARKER "|1|"
|
||||
#define MOVE_AMOUNT 1
|
||||
|
||||
extern int _xev_quit;
|
||||
|
||||
void
|
||||
kbfunc_client_lower(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_lower(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
client_lower(cc);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_raise(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_raise(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
client_raise(cc);
|
||||
}
|
||||
@@ -44,7 +43,7 @@ kbfunc_client_raise(struct client_ctx *cc, void *arg)
|
||||
#define typemask (CWM_MOVE | CWM_RESIZE | CWM_PTRMOVE)
|
||||
#define movemask (CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)
|
||||
void
|
||||
kbfunc_moveresize(struct client_ctx *cc, void *arg)
|
||||
kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
struct screen_ctx *sc;
|
||||
int x, y, flags, amt;
|
||||
@@ -53,8 +52,8 @@ kbfunc_moveresize(struct client_ctx *cc, void *arg)
|
||||
sc = screen_current();
|
||||
mx = my = 0;
|
||||
|
||||
flags = (int)arg;
|
||||
amt = MOVE_AMOUNT;
|
||||
flags = arg->i;
|
||||
amt = Conf.mamount;
|
||||
|
||||
if (flags & CWM_BIGMOVE) {
|
||||
flags -= CWM_BIGMOVE;
|
||||
@@ -80,17 +79,17 @@ kbfunc_moveresize(struct client_ctx *cc, void *arg)
|
||||
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)
|
||||
cc->geom.y = cc->sc->ymax;
|
||||
if (cc->geom.y > cc->sc->ymax - 1)
|
||||
cc->geom.y = cc->sc->ymax - 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)
|
||||
cc->geom.x = cc->sc->xmax;
|
||||
if (cc->geom.x > cc->sc->xmax - 1)
|
||||
cc->geom.x = cc->sc->xmax - 1;
|
||||
|
||||
client_move(cc);
|
||||
xu_ptr_getpos(cc->pwin, &x, &y);
|
||||
xu_ptr_getpos(cc->win, &x, &y);
|
||||
cc->ptr.y = y + my;
|
||||
cc->ptr.x = x + mx;
|
||||
client_ptrwarp(cc);
|
||||
@@ -103,7 +102,7 @@ kbfunc_moveresize(struct client_ctx *cc, void *arg)
|
||||
client_resize(cc);
|
||||
|
||||
/* Make sure the pointer stays within the window. */
|
||||
xu_ptr_getpos(cc->pwin, &cc->ptr.x, &cc->ptr.y);
|
||||
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)
|
||||
@@ -112,8 +111,8 @@ kbfunc_moveresize(struct client_ctx *cc, void *arg)
|
||||
break;
|
||||
case CWM_PTRMOVE:
|
||||
if (cc) {
|
||||
xu_ptr_getpos(cc->pwin, &x, &y);
|
||||
xu_ptr_setpos(cc->pwin, x + mx, y + my);
|
||||
xu_ptr_getpos(cc->win, &x, &y);
|
||||
xu_ptr_setpos(cc->win, x + mx, y + my);
|
||||
} else {
|
||||
xu_ptr_getpos(sc->rootwin, &x, &y);
|
||||
xu_ptr_setpos(sc->rootwin, x + mx, y + my);
|
||||
@@ -125,7 +124,7 @@ kbfunc_moveresize(struct client_ctx *cc, void *arg)
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_search(struct client_ctx *scratch, void *arg)
|
||||
kbfunc_client_search(struct client_ctx *scratch, union arg *arg)
|
||||
{
|
||||
struct client_ctx *cc, *old_cc;
|
||||
struct menu *mi;
|
||||
@@ -136,7 +135,7 @@ kbfunc_client_search(struct client_ctx *scratch, void *arg)
|
||||
TAILQ_INIT(&menuq);
|
||||
|
||||
TAILQ_FOREACH(cc, &Clientq, entry) {
|
||||
XCALLOC(mi, struct menu);
|
||||
mi = xcalloc(1, sizeof(*mi));
|
||||
strlcpy(mi->text, cc->name, sizeof(mi->text));
|
||||
mi->ctx = cc;
|
||||
TAILQ_INSERT_TAIL(&menuq, mi, entry);
|
||||
@@ -160,7 +159,7 @@ kbfunc_client_search(struct client_ctx *scratch, void *arg)
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_menu_search(struct client_ctx *scratch, void *arg)
|
||||
kbfunc_menu_search(struct client_ctx *scratch, union arg *arg)
|
||||
{
|
||||
struct cmd *cmd;
|
||||
struct menu *mi;
|
||||
@@ -169,7 +168,7 @@ kbfunc_menu_search(struct client_ctx *scratch, void *arg)
|
||||
TAILQ_INIT(&menuq);
|
||||
|
||||
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
|
||||
XCALLOC(mi, struct menu);
|
||||
mi = xcalloc(1, sizeof(*mi));
|
||||
strlcpy(mi->text, cmd->label, sizeof(mi->text));
|
||||
mi->ctx = cmd;
|
||||
TAILQ_INSERT_TAIL(&menuq, mi, entry);
|
||||
@@ -186,7 +185,7 @@ kbfunc_menu_search(struct client_ctx *scratch, void *arg)
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_cycle(struct client_ctx *scratch, void *arg)
|
||||
kbfunc_client_cycle(struct client_ctx *scratch, union arg *arg)
|
||||
{
|
||||
struct screen_ctx *sc;
|
||||
|
||||
@@ -196,35 +195,35 @@ kbfunc_client_cycle(struct client_ctx *scratch, void *arg)
|
||||
XGrabKeyboard(X_Dpy, sc->rootwin, True,
|
||||
GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
|
||||
client_cycle((int)arg);
|
||||
client_cycle(arg->i);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_hide(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_hide(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
client_hide(cc);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_cmdexec(struct client_ctx *cc, void *arg)
|
||||
kbfunc_cmdexec(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
u_spawn((char *)arg);
|
||||
u_spawn(arg->c);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_term(struct client_ctx *cc, void *arg)
|
||||
kbfunc_term(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
u_spawn(Conf.termpath);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_lock(struct client_ctx *cc, void *arg)
|
||||
kbfunc_lock(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
u_spawn(Conf.lockpath);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_exec(struct client_ctx *scratch, void *arg)
|
||||
kbfunc_exec(struct client_ctx *scratch, union arg *arg)
|
||||
{
|
||||
#define NPATHS 256
|
||||
char **ap, *paths[NPATHS], *path, *pathcpy, *label;
|
||||
@@ -238,7 +237,7 @@ kbfunc_exec(struct client_ctx *scratch, void *arg)
|
||||
struct menu_q menuq;
|
||||
struct stat sb;
|
||||
|
||||
int cmd = (int)arg;
|
||||
int cmd = arg->i;
|
||||
switch (cmd) {
|
||||
case CWM_EXEC_PROGRAM:
|
||||
label = "exec";
|
||||
@@ -305,7 +304,7 @@ kbfunc_exec(struct client_ctx *scratch, void *arg)
|
||||
continue;
|
||||
executable:
|
||||
/* the thing in tpath, we may execute */
|
||||
XCALLOC(mi, struct menu);
|
||||
mi = xcalloc(1, sizeof(*mi));
|
||||
strlcpy(mi->text, dp->d_name, sizeof(mi->text));
|
||||
TAILQ_INSERT_TAIL(&menuq, mi, entry);
|
||||
}
|
||||
@@ -338,7 +337,7 @@ kbfunc_exec(struct client_ctx *scratch, void *arg)
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_ssh(struct client_ctx *scratch, void *arg)
|
||||
kbfunc_ssh(struct client_ctx *scratch, union arg *arg)
|
||||
{
|
||||
struct menu *mi;
|
||||
struct menu_q menuq;
|
||||
@@ -381,7 +380,7 @@ kbfunc_ssh(struct client_ctx *scratch, void *arg)
|
||||
if (p - buf + 1 > sizeof(hostbuf))
|
||||
continue;
|
||||
(void) strlcpy(hostbuf, buf, p - buf + 1);
|
||||
XCALLOC(mi, struct menu);
|
||||
mi = xcalloc(1, sizeof(*mi));
|
||||
(void) strlcpy(mi->text, hostbuf, sizeof(mi->text));
|
||||
TAILQ_INSERT_TAIL(&menuq, mi, entry);
|
||||
}
|
||||
@@ -405,7 +404,7 @@ kbfunc_ssh(struct client_ctx *scratch, void *arg)
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_label(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_label(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
struct menu *mi;
|
||||
struct menu_q menuq;
|
||||
@@ -413,10 +412,7 @@ kbfunc_client_label(struct client_ctx *cc, void *arg)
|
||||
|
||||
TAILQ_INIT(&menuq);
|
||||
|
||||
if (cc->label != NULL)
|
||||
current = cc->label;
|
||||
else
|
||||
current = NULL;
|
||||
current = cc->label;
|
||||
|
||||
if ((mi = menu_filter(&menuq, "label", current, 1,
|
||||
search_match_text, NULL)) != NULL) {
|
||||
@@ -428,59 +424,71 @@ kbfunc_client_label(struct client_ctx *cc, void *arg)
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_delete(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_delete(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
client_send_delete(cc);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_group(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_group(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
group_hidetoggle(KBTOGROUP((int)arg));
|
||||
group_hidetoggle(KBTOGROUP(arg->i));
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_cyclegroup(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_grouponly(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
group_cycle((int)arg);
|
||||
group_only(KBTOGROUP(arg->i));
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_nogroup(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_cyclegroup(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
group_cycle(arg->i);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_nogroup(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
group_alltoggle();
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_grouptoggle(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_grouptoggle(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
/* XXX for stupid X apps like xpdf and gvim */
|
||||
XGrabKeyboard(X_Dpy, cc->pwin, True,
|
||||
XGrabKeyboard(X_Dpy, cc->win, True,
|
||||
GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
|
||||
group_sticky_toggle_enter(cc);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_maximize(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_movetogroup(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
group_movetogroup(cc, KBTOGROUP(arg->i));
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_maximize(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
client_maximize(cc);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_vmaximize(struct client_ctx *cc, void *arg)
|
||||
kbfunc_client_vmaximize(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
client_vertmaximize(cc);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_quit_wm(struct client_ctx *cc, void *arg)
|
||||
kbfunc_quit_wm(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
_xev_quit = 1;
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_reload(struct client_ctx *cc, void *arg)
|
||||
kbfunc_reload(struct client_ctx *cc, union arg *arg)
|
||||
{
|
||||
conf_reload(&Conf);
|
||||
}
|
||||
|
40
menu.c
40
menu.c
@@ -18,11 +18,6 @@
|
||||
#include "headers.h"
|
||||
#include "calmwm.h"
|
||||
|
||||
#define KeyMask (KeyPressMask|ExposureMask)
|
||||
#define MenuMask (ButtonMask|ButtonMotionMask|ExposureMask| \
|
||||
PointerMotionMask)
|
||||
#define MenuGrabMask (ButtonMask|ButtonMotionMask|StructureNotifyMask|\
|
||||
PointerMotionMask)
|
||||
#define PROMPT_SCHAR '<27>'
|
||||
#define PROMPT_ECHAR '<27>'
|
||||
|
||||
@@ -48,7 +43,7 @@ static struct menu *menu_handle_key(XEvent *, struct menu_ctx *,
|
||||
struct menu_q *, struct menu_q *);
|
||||
static void menu_handle_move(XEvent *, struct menu_ctx *,
|
||||
struct screen_ctx *);
|
||||
struct menu *menu_handle_release(XEvent *, struct menu_ctx *,
|
||||
static struct menu *menu_handle_release(XEvent *, struct menu_ctx *,
|
||||
struct screen_ctx *, struct menu_q *);
|
||||
static void menu_draw(struct screen_ctx *, struct menu_ctx *,
|
||||
struct menu_q *, struct menu_q *);
|
||||
@@ -58,8 +53,19 @@ static int menu_calc_entry(struct screen_ctx *, struct menu_ctx *,
|
||||
void
|
||||
menu_init(struct screen_ctx *sc)
|
||||
{
|
||||
sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0,
|
||||
1, 1, 1, sc->blackpixl, sc->whitepixl);
|
||||
XGCValues gv;
|
||||
|
||||
sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1, 0,
|
||||
sc->color[CWM_COLOR_BG_MENU].pixel,
|
||||
sc->color[CWM_COLOR_BG_MENU].pixel);
|
||||
|
||||
gv.foreground =
|
||||
sc->color[CWM_COLOR_FG_MENU].pixel^sc->color[CWM_COLOR_BG_MENU].pixel;
|
||||
gv.background = sc->color[CWM_COLOR_BG_MENU].pixel;
|
||||
gv.function = GXxor;
|
||||
|
||||
sc->gc = XCreateGC(X_Dpy, sc->menuwin,
|
||||
GCForeground|GCBackground|GCFunction, &gv);
|
||||
}
|
||||
|
||||
struct menu *
|
||||
@@ -73,7 +79,7 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
||||
struct menu *mi = NULL;
|
||||
XEvent e;
|
||||
Window focuswin;
|
||||
int Mask, focusrevert;
|
||||
int evmask, focusrevert;
|
||||
|
||||
sc = screen_current();
|
||||
|
||||
@@ -84,11 +90,11 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
||||
xu_ptr_getpos(sc->rootwin, &mc.x, &mc.y);
|
||||
|
||||
if (prompt == NULL) {
|
||||
Mask = MenuMask;
|
||||
evmask = MenuMask;
|
||||
mc.promptstr[0] = '\0';
|
||||
mc.list = 1;
|
||||
} else {
|
||||
Mask = MenuMask | KeyMask; /* only accept keys if prompt */
|
||||
evmask = MenuMask | KeyMask; /* only accept keys if prompt */
|
||||
snprintf(mc.promptstr, sizeof(mc.promptstr), "%s%c", prompt,
|
||||
PROMPT_SCHAR);
|
||||
snprintf(mc.dispstr, sizeof(mc.dispstr), "%s%s%c", mc.promptstr,
|
||||
@@ -108,7 +114,7 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
||||
|
||||
XMoveResizeWindow(X_Dpy, sc->menuwin, mc.x, mc.y, mc.width,
|
||||
font_height());
|
||||
XSelectInput(X_Dpy, sc->menuwin, Mask);
|
||||
XSelectInput(X_Dpy, sc->menuwin, evmask);
|
||||
XMapRaised(X_Dpy, sc->menuwin);
|
||||
|
||||
if (xu_ptr_grab(sc->menuwin, MenuGrabMask, Cursor_question) < 0) {
|
||||
@@ -126,7 +132,7 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
||||
for (;;) {
|
||||
mc.changed = 0;
|
||||
|
||||
XWindowEvent(X_Dpy, sc->menuwin, Mask, &e);
|
||||
XWindowEvent(X_Dpy, sc->menuwin, evmask, &e);
|
||||
|
||||
switch (e.type) {
|
||||
default:
|
||||
@@ -150,7 +156,7 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
||||
}
|
||||
}
|
||||
out:
|
||||
if ((dummy == 0 && mi->dummy) || (mi->text[0] == '\0')) { /* no match */
|
||||
if (dummy == 0 && mi->dummy) { /* no match */
|
||||
xfree (mi);
|
||||
mi = NULL;
|
||||
xu_ptr_ungrab();
|
||||
@@ -343,7 +349,7 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
|
||||
0, 0, mc->width, font_height());
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
menu_handle_move(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc)
|
||||
{
|
||||
mc->prev = mc->entry;
|
||||
@@ -360,7 +366,7 @@ menu_handle_move(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc)
|
||||
xu_ptr_regrab(MenuGrabMask, Cursor_default);
|
||||
}
|
||||
|
||||
struct menu *
|
||||
static struct menu *
|
||||
menu_handle_release(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc,
|
||||
struct menu_q *resultq)
|
||||
{
|
||||
@@ -377,7 +383,7 @@ menu_handle_release(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc,
|
||||
if (entry == i++)
|
||||
break;
|
||||
if (mi == NULL) {
|
||||
XMALLOC(mi, struct menu);
|
||||
mi = xmalloc(sizeof(*mi));
|
||||
mi->text[0] = '\0';
|
||||
mi->dummy = 1;
|
||||
}
|
||||
|
171
mousefunc.c
171
mousefunc.c
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* calmwm - the calm window manager
|
||||
*
|
||||
* Copyright (c) 2004 Marius Aamodt Eriksen <marius@monkey.org>
|
||||
* Copyright (c) 2008 rivo nurges <rix@estpak.ee>
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -21,18 +22,170 @@
|
||||
#include "headers.h"
|
||||
#include "calmwm.h"
|
||||
|
||||
static int mousefunc_sweep_calc(struct client_ctx *, int, int, int, int);
|
||||
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;
|
||||
|
||||
cc->geom.width = abs(x - mx) - cc->bwidth;
|
||||
cc->geom.height = abs(y - my) - cc->bwidth;
|
||||
|
||||
if (cc->size->flags & PResizeInc) {
|
||||
cc->geom.width -=
|
||||
(cc->geom.width - cc->geom.min_dx) % cc->size->width_inc;
|
||||
cc->geom.height -=
|
||||
(cc->geom.height - cc->geom.min_dy) % cc->size->height_inc;
|
||||
}
|
||||
|
||||
if (cc->size->flags & PMinSize) {
|
||||
cc->geom.width = MAX(cc->geom.width, cc->size->min_width);
|
||||
cc->geom.height = MAX(cc->geom.height, cc->size->min_height);
|
||||
}
|
||||
|
||||
if (cc->size->flags & PMaxSize) {
|
||||
cc->geom.width = MIN(cc->geom.width, cc->size->max_width);
|
||||
cc->geom.height = MIN(cc->geom.height, cc->size->max_height);
|
||||
}
|
||||
|
||||
cc->geom.x = x <= mx ? x : x - cc->geom.width;
|
||||
cc->geom.y = y <= my ? y : y - cc->geom.height;
|
||||
|
||||
return (width != cc->geom.width || height != cc->geom.height);
|
||||
}
|
||||
|
||||
static void
|
||||
mousefunc_sweep_draw(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
char asize[10]; /* fits "nnnnxnnnn\0" */
|
||||
int width, height, width_size, width_name;
|
||||
|
||||
snprintf(asize, sizeof(asize), "%dx%d",
|
||||
(cc->geom.width - cc->geom.min_dx) / cc->size->width_inc,
|
||||
(cc->geom.height - cc->geom.min_dy) / cc->size->height_inc);
|
||||
width_size = font_width(asize, strlen(asize)) + 4;
|
||||
width_name = font_width(cc->name, strlen(cc->name)) + 4;
|
||||
width = MAX(width_size, width_name);
|
||||
height = font_ascent() + font_descent() + 1;
|
||||
|
||||
XMoveResizeWindow(X_Dpy, sc->menuwin, cc->geom.x, cc->geom.y,
|
||||
width, height * 2);
|
||||
XMapWindow(X_Dpy, sc->menuwin);
|
||||
XReparentWindow(X_Dpy, sc->menuwin, cc->win, 0, 0);
|
||||
XClearWindow(X_Dpy, sc->menuwin);
|
||||
font_draw(sc, cc->name, strlen(cc->name), sc->menuwin,
|
||||
2, font_ascent() + 1);
|
||||
font_draw(sc, asize, strlen(asize), sc->menuwin,
|
||||
width / 2 - width_size / 2, height + font_ascent() + 1);
|
||||
}
|
||||
|
||||
void
|
||||
mousefunc_window_resize(struct client_ctx *cc, void *arg)
|
||||
{
|
||||
grab_sweep(cc);
|
||||
client_resize(cc);
|
||||
XEvent ev;
|
||||
Time time = 0;
|
||||
struct screen_ctx *sc = CCTOSC(cc);
|
||||
int x = cc->geom.x, y = cc->geom.y;
|
||||
|
||||
cc->size->width_inc = MAX(1, cc->size->width_inc);
|
||||
cc->size->height_inc = MAX(1, cc->size->height_inc);
|
||||
|
||||
client_raise(cc);
|
||||
client_ptrsave(cc);
|
||||
|
||||
if (xu_ptr_grab(cc->win, MouseMask, Cursor_resize) < 0)
|
||||
return;
|
||||
|
||||
xu_ptr_setpos(cc->win, cc->geom.width, cc->geom.height);
|
||||
mousefunc_sweep_draw(cc);
|
||||
|
||||
for (;;) {
|
||||
XMaskEvent(X_Dpy, MouseMask|ExposureMask, &ev);
|
||||
|
||||
switch (ev.type) {
|
||||
case Expose:
|
||||
client_draw_border(cc);
|
||||
break;
|
||||
case MotionNotify:
|
||||
if (mousefunc_sweep_calc(cc, x, y,
|
||||
ev.xmotion.x_root, ev.xmotion.y_root))
|
||||
/* Recompute window output */
|
||||
mousefunc_sweep_draw(cc);
|
||||
|
||||
/* don't sync more than 60 times / second */
|
||||
if ((ev.xmotion.time - time) > (1000 / 60)) {
|
||||
time = ev.xmotion.time;
|
||||
XSync(X_Dpy, False);
|
||||
client_resize(cc);
|
||||
}
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (time) {
|
||||
XSync(X_Dpy, False);
|
||||
client_resize(cc);
|
||||
}
|
||||
XUnmapWindow(X_Dpy, sc->menuwin);
|
||||
XReparentWindow(X_Dpy, sc->menuwin, sc->rootwin, 0, 0);
|
||||
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;
|
||||
client_ptrwarp(cc);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
mousefunc_window_move(struct client_ctx *cc, void *arg)
|
||||
{
|
||||
grab_drag(cc);
|
||||
client_move(cc);
|
||||
XEvent ev;
|
||||
Time time = 0;
|
||||
int px, py;
|
||||
|
||||
client_raise(cc);
|
||||
|
||||
if (xu_ptr_grab(cc->win, MouseMask, Cursor_move) < 0)
|
||||
return;
|
||||
|
||||
xu_ptr_getpos(cc->win, &px, &py);
|
||||
|
||||
for (;;) {
|
||||
XMaskEvent(X_Dpy, MouseMask|ExposureMask, &ev);
|
||||
|
||||
switch (ev.type) {
|
||||
case Expose:
|
||||
client_draw_border(cc);
|
||||
break;
|
||||
case MotionNotify:
|
||||
cc->geom.x = ev.xmotion.x_root - px;
|
||||
cc->geom.y = ev.xmotion.y_root - py;
|
||||
|
||||
/* don't sync more than 60 times / second */
|
||||
if ((ev.xmotion.time - time) > (1000 / 60)) {
|
||||
time = ev.xmotion.time;
|
||||
XSync(X_Dpy, False);
|
||||
client_move(cc);
|
||||
}
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (time) {
|
||||
XSync(X_Dpy, False);
|
||||
client_move(cc);
|
||||
}
|
||||
xu_ptr_ungrab();
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
void
|
||||
@@ -73,15 +226,11 @@ mousefunc_menu_unhide(struct client_ctx *cc, void *arg)
|
||||
TAILQ_INIT(&menuq);
|
||||
TAILQ_FOREACH(cc, &Clientq, entry)
|
||||
if (cc->flags & CLIENT_HIDDEN) {
|
||||
if (cc->label != NULL)
|
||||
wname = cc->label;
|
||||
else
|
||||
wname = cc->name;
|
||||
|
||||
wname = (cc->label) ? cc->label : cc->name;
|
||||
if (wname == NULL)
|
||||
continue;
|
||||
|
||||
XCALLOC(mi, struct menu);
|
||||
mi = xcalloc(1, sizeof(*mi));
|
||||
strlcpy(mi->text, wname, sizeof(mi->text));
|
||||
mi->ctx = cc;
|
||||
TAILQ_INSERT_TAIL(&menuq, mi, entry);
|
||||
@@ -115,7 +264,7 @@ mousefunc_menu_cmd(struct client_ctx *cc, void *arg)
|
||||
|
||||
TAILQ_INIT(&menuq);
|
||||
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
|
||||
XCALLOC(mi, struct menu);
|
||||
mi = xcalloc(1, sizeof(*mi));
|
||||
strlcpy(mi->text, cmd->label, sizeof(mi->text));
|
||||
mi->ctx = cmd;
|
||||
TAILQ_INSERT_TAIL(&menuq, mi, entry);
|
||||
|
108
parse.y
108
parse.y
@@ -54,8 +54,6 @@ int findeol(void);
|
||||
|
||||
static struct conf *conf;
|
||||
|
||||
extern char *shortcut_to_name[];
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
int64_t number;
|
||||
@@ -68,7 +66,10 @@ typedef struct {
|
||||
|
||||
%token FONTNAME STICKY GAP MOUSEBIND
|
||||
%token AUTOGROUP BIND COMMAND IGNORE
|
||||
%token YES NO
|
||||
%token YES NO BORDERWIDTH MOVEAMOUNT
|
||||
%token COLOR
|
||||
%token ACTIVEBORDER INACTIVEBORDER
|
||||
%token GROUPBORDER UNGROUPBORDER
|
||||
%token ERROR
|
||||
%token <v.string> STRING
|
||||
%token <v.number> NUMBER
|
||||
@@ -79,6 +80,7 @@ typedef struct {
|
||||
grammar : /* empty */
|
||||
| grammar '\n'
|
||||
| grammar main '\n'
|
||||
| grammar color '\n'
|
||||
| grammar error '\n' { file->errors++; }
|
||||
;
|
||||
|
||||
@@ -109,6 +111,12 @@ main : FONTNAME STRING {
|
||||
else
|
||||
conf->flags |= CONF_STICKY_GROUPS;
|
||||
}
|
||||
| BORDERWIDTH NUMBER {
|
||||
conf->bwidth = $2;
|
||||
}
|
||||
| MOVEAMOUNT NUMBER {
|
||||
conf->mamount = $2;
|
||||
}
|
||||
| COMMAND STRING string {
|
||||
conf_cmd_add(conf, $3, $2, 0);
|
||||
free($2);
|
||||
@@ -124,7 +132,7 @@ main : FONTNAME STRING {
|
||||
YYERROR;
|
||||
}
|
||||
|
||||
XCALLOC(aw, struct autogroupwin);
|
||||
aw = xcalloc(1, sizeof(*aw));
|
||||
|
||||
if ((p = strchr($3, ',')) == NULL) {
|
||||
aw->name = NULL;
|
||||
@@ -143,7 +151,7 @@ main : FONTNAME STRING {
|
||||
| IGNORE STRING {
|
||||
struct winmatch *wm;
|
||||
|
||||
XCALLOC(wm, struct winmatch);
|
||||
wm = xcalloc(1, sizeof(*wm));
|
||||
strlcpy(wm->title, $2, sizeof(wm->title));
|
||||
TAILQ_INSERT_TAIL(&conf->ignoreq, wm, entry);
|
||||
|
||||
@@ -166,6 +174,27 @@ main : FONTNAME STRING {
|
||||
free($3);
|
||||
}
|
||||
;
|
||||
|
||||
color : COLOR colors
|
||||
;
|
||||
|
||||
colors : ACTIVEBORDER STRING {
|
||||
free(conf->color[CWM_COLOR_BORDOR_ACTIVE].name);
|
||||
conf->color[CWM_COLOR_BORDOR_ACTIVE].name = $2;
|
||||
}
|
||||
| INACTIVEBORDER STRING {
|
||||
free(conf->color[CWM_COLOR_BORDER_INACTIVE].name);
|
||||
conf->color[CWM_COLOR_BORDER_INACTIVE].name = $2;
|
||||
}
|
||||
| GROUPBORDER STRING {
|
||||
free(conf->color[CWM_COLOR_BORDER_GROUP].name);
|
||||
conf->color[CWM_COLOR_BORDER_GROUP].name = $2;
|
||||
}
|
||||
| UNGROUPBORDER STRING {
|
||||
free(conf->color[CWM_COLOR_BORDER_UNGROUP].name);
|
||||
conf->color[CWM_COLOR_BORDER_UNGROUP].name = $2;
|
||||
}
|
||||
;
|
||||
%%
|
||||
|
||||
struct keywords {
|
||||
@@ -198,15 +227,22 @@ lookup(char *s)
|
||||
{
|
||||
/* this has to be sorted always */
|
||||
static const struct keywords keywords[] = {
|
||||
{ "activeborder", ACTIVEBORDER},
|
||||
{ "autogroup", AUTOGROUP},
|
||||
{ "bind", BIND},
|
||||
{ "borderwidth", BORDERWIDTH},
|
||||
{ "color", COLOR},
|
||||
{ "command", COMMAND},
|
||||
{ "fontname", FONTNAME},
|
||||
{ "gap", GAP},
|
||||
{ "groupborder", GROUPBORDER},
|
||||
{ "ignore", IGNORE},
|
||||
{ "inactiveborder", INACTIVEBORDER},
|
||||
{ "mousebind", MOUSEBIND},
|
||||
{ "moveamount", MOVEAMOUNT},
|
||||
{ "no", NO},
|
||||
{ "sticky", STICKY},
|
||||
{ "ungroupborder", UNGROUPBORDER},
|
||||
{ "yes", YES}
|
||||
};
|
||||
const struct keywords *p;
|
||||
@@ -462,56 +498,12 @@ popfile(void)
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
void
|
||||
conf_clear(struct conf *c)
|
||||
{
|
||||
struct autogroupwin *ag;
|
||||
struct keybinding *kb;
|
||||
struct winmatch *wm;
|
||||
struct cmd *cmd;
|
||||
struct mousebinding *mb;
|
||||
|
||||
while (cmd = TAILQ_FIRST(&c->cmdq)) {
|
||||
TAILQ_REMOVE(&c->cmdq, cmd, entry);
|
||||
free(cmd);
|
||||
}
|
||||
|
||||
while (kb = TAILQ_FIRST(&c->keybindingq)) {
|
||||
TAILQ_REMOVE(&c->keybindingq, kb, entry);
|
||||
free(kb);
|
||||
}
|
||||
|
||||
while (ag = TAILQ_FIRST(&c->autogroupq)) {
|
||||
TAILQ_REMOVE(&c->autogroupq, ag, entry);
|
||||
free(ag->class);
|
||||
if (ag->name)
|
||||
free(ag->name);
|
||||
free(ag->group);
|
||||
free(ag);
|
||||
}
|
||||
|
||||
while (wm = TAILQ_FIRST(&c->ignoreq)) {
|
||||
TAILQ_REMOVE(&c->ignoreq, wm, entry);
|
||||
free(wm);
|
||||
}
|
||||
|
||||
while (mb = TAILQ_FIRST(&c->mousebindingq)) {
|
||||
TAILQ_REMOVE(&c->mousebindingq, mb, entry);
|
||||
free(mb);
|
||||
}
|
||||
|
||||
if (c->DefaultFontName != NULL &&
|
||||
c->DefaultFontName != DEFAULTFONTNAME)
|
||||
free(c->DefaultFontName);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
parse_config(const char *filename, struct conf *xconf)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
XCALLOC(conf, struct conf);
|
||||
conf = xcalloc(1, sizeof(*conf));
|
||||
|
||||
if ((file = pushfile(filename)) == NULL) {
|
||||
free(conf);
|
||||
@@ -536,32 +528,35 @@ parse_config(const char *filename, struct conf *xconf)
|
||||
struct winmatch *wm;
|
||||
struct cmd *cmd;
|
||||
struct mousebinding *mb;
|
||||
int i;
|
||||
|
||||
conf_clear(xconf);
|
||||
|
||||
xconf->flags = conf->flags;
|
||||
xconf->bwidth = conf->bwidth;
|
||||
xconf->mamount = conf->mamount;
|
||||
|
||||
while (cmd = TAILQ_FIRST(&conf->cmdq)) {
|
||||
while ((cmd = TAILQ_FIRST(&conf->cmdq)) != NULL) {
|
||||
TAILQ_REMOVE(&conf->cmdq, cmd, entry);
|
||||
TAILQ_INSERT_TAIL(&xconf->cmdq, cmd, entry);
|
||||
}
|
||||
|
||||
while (kb = TAILQ_FIRST(&conf->keybindingq)) {
|
||||
while ((kb = TAILQ_FIRST(&conf->keybindingq)) != NULL) {
|
||||
TAILQ_REMOVE(&conf->keybindingq, kb, entry);
|
||||
TAILQ_INSERT_TAIL(&xconf->keybindingq, kb, entry);
|
||||
}
|
||||
|
||||
while (ag = TAILQ_FIRST(&conf->autogroupq)) {
|
||||
while ((ag = TAILQ_FIRST(&conf->autogroupq)) != NULL) {
|
||||
TAILQ_REMOVE(&conf->autogroupq, ag, entry);
|
||||
TAILQ_INSERT_TAIL(&xconf->autogroupq, ag, entry);
|
||||
}
|
||||
|
||||
while (wm = TAILQ_FIRST(&conf->ignoreq)) {
|
||||
while ((wm = TAILQ_FIRST(&conf->ignoreq)) != NULL) {
|
||||
TAILQ_REMOVE(&conf->ignoreq, wm, entry);
|
||||
TAILQ_INSERT_TAIL(&xconf->ignoreq, wm, entry);
|
||||
}
|
||||
|
||||
while (mb = TAILQ_FIRST(&conf->mousebindingq)) {
|
||||
while ((mb = TAILQ_FIRST(&conf->mousebindingq)) != NULL) {
|
||||
TAILQ_REMOVE(&conf->mousebindingq, mb, entry);
|
||||
TAILQ_INSERT_TAIL(&xconf->mousebindingq, mb, entry);
|
||||
}
|
||||
@@ -571,6 +566,9 @@ parse_config(const char *filename, struct conf *xconf)
|
||||
strlcpy(xconf->lockpath, conf->lockpath,
|
||||
sizeof(xconf->lockpath));
|
||||
|
||||
for (i = 0; i < CWM_COLOR_MAX; i++)
|
||||
xconf->color[i].name = conf->color[i].name;
|
||||
|
||||
xconf->DefaultFontName = conf->DefaultFontName;
|
||||
|
||||
bcopy(&(conf->gap_top), &(xconf->gap_top), sizeof(int) * 4);
|
||||
|
50
screen.c
50
screen.c
@@ -21,9 +21,14 @@
|
||||
#include "headers.h"
|
||||
#include "calmwm.h"
|
||||
|
||||
extern struct screen_ctx_q Screenq;
|
||||
extern struct screen_ctx *Curscreen;
|
||||
|
||||
void
|
||||
screen_init(void)
|
||||
{
|
||||
TAILQ_INIT(&Screenq);
|
||||
}
|
||||
|
||||
struct screen_ctx *
|
||||
screen_fromroot(Window rootwin)
|
||||
{
|
||||
@@ -67,3 +72,46 @@ screen_updatestackingorder(void)
|
||||
|
||||
XFree(wins);
|
||||
}
|
||||
|
||||
void
|
||||
screen_init_xinerama(struct screen_ctx *sc)
|
||||
{
|
||||
XineramaScreenInfo *info;
|
||||
int no;
|
||||
|
||||
if (HasXinerama == 0 || XineramaIsActive(X_Dpy) == 0) {
|
||||
HasXinerama = 0;
|
||||
sc->xinerama_no = 0;
|
||||
}
|
||||
|
||||
info = XineramaQueryScreens(X_Dpy, &no);
|
||||
if (info == NULL) {
|
||||
/*is xinerama is actually off, instead of a malloc failure? */
|
||||
if (sc->xinerama == NULL)
|
||||
HasXinerama = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (sc->xinerama != NULL)
|
||||
XFree(sc->xinerama);
|
||||
sc->xinerama = info;
|
||||
sc->xinerama_no = no;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find which xinerama screen the coordinates (x,y) is on.
|
||||
*/
|
||||
XineramaScreenInfo *
|
||||
screen_find_xinerama(struct screen_ctx *sc, int x, int y)
|
||||
{
|
||||
XineramaScreenInfo *info;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < sc->xinerama_no; i++) {
|
||||
info = &sc->xinerama[i];
|
||||
if (x > info->x_org && x < info->x_org + info->width &&
|
||||
y > info->y_org && y < info->y_org + info->height)
|
||||
return (info);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
34
search.c
34
search.c
@@ -17,12 +17,11 @@
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <fnmatch.h>
|
||||
#include "headers.h"
|
||||
#include "calmwm.h"
|
||||
|
||||
#define SearchMask (KeyPressMask|ExposureMask)
|
||||
|
||||
static int _strsubmatch(char *, char *, int);
|
||||
static int strsubmatch(char *, char *, int);
|
||||
|
||||
/*
|
||||
* Match: label, title, class.
|
||||
@@ -54,7 +53,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
|
||||
struct client_ctx *cc = mi->ctx;
|
||||
|
||||
/* First, try to match on labels. */
|
||||
if (cc->label != NULL && _strsubmatch(search, cc->label, 0)) {
|
||||
if (cc->label != NULL && strsubmatch(search, cc->label, 0)) {
|
||||
cc->matchname = cc->label;
|
||||
tier = 0;
|
||||
}
|
||||
@@ -62,7 +61,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
|
||||
/* Then, on window names. */
|
||||
if (tier < 0) {
|
||||
TAILQ_FOREACH_REVERSE(wn, &cc->nameq, winname_q, entry)
|
||||
if (_strsubmatch(search, wn->name, 0)) {
|
||||
if (strsubmatch(search, wn->name, 0)) {
|
||||
cc->matchname = wn->name;
|
||||
tier = 2;
|
||||
break;
|
||||
@@ -74,7 +73,7 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
|
||||
* name.
|
||||
*/
|
||||
|
||||
if (tier < 0 && _strsubmatch(search, cc->app_class, 0)) {
|
||||
if (tier < 0 && strsubmatch(search, cc->app_class, 0)) {
|
||||
cc->matchname = cc->app_class;
|
||||
tier = 3;
|
||||
}
|
||||
@@ -132,7 +131,7 @@ search_print_client(struct menu *mi, int list)
|
||||
flag = '&';
|
||||
|
||||
if (list)
|
||||
cc->matchname = TAILQ_FIRST(&cc->nameq)->name;
|
||||
cc->matchname = cc->name;
|
||||
|
||||
snprintf(mi->print, sizeof(mi->print), "%c%s", flag, cc->matchname);
|
||||
|
||||
@@ -168,24 +167,35 @@ search_match_text(struct menu_q *menuq, struct menu_q *resultq, char *search)
|
||||
TAILQ_INIT(resultq);
|
||||
|
||||
TAILQ_FOREACH(mi, menuq, entry)
|
||||
if (_strsubmatch(search, mi->text, 0))
|
||||
if (strsubmatch(search, mi->text, 0))
|
||||
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
|
||||
}
|
||||
|
||||
void
|
||||
search_match_exec(struct menu_q *menuq, struct menu_q *resultq, char *search)
|
||||
{
|
||||
struct menu *mi;
|
||||
struct menu *mi, *mj;
|
||||
|
||||
TAILQ_INIT(resultq);
|
||||
|
||||
TAILQ_FOREACH(mi, menuq, entry)
|
||||
if (_strsubmatch(search, mi->text, 1))
|
||||
TAILQ_FOREACH(mi, menuq, entry) {
|
||||
if (strsubmatch(search, mi->text, 1) == 0 &&
|
||||
fnmatch(search, mi->text, 0) == FNM_NOMATCH)
|
||||
continue;
|
||||
for (mj = TAILQ_FIRST(resultq); mj != NULL;
|
||||
mj = TAILQ_NEXT(mj, resultentry)) {
|
||||
if (strcasecmp(mi->text, mj->text) < 0) {
|
||||
TAILQ_INSERT_BEFORE(mj, mi, resultentry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (mj == NULL)
|
||||
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
_strsubmatch(char *sub, char *str, int zeroidx)
|
||||
strsubmatch(char *sub, char *str, int zeroidx)
|
||||
{
|
||||
size_t len, sublen;
|
||||
u_int n, flen;
|
||||
|
398
xevents.c
398
xevents.c
@@ -27,22 +27,46 @@
|
||||
#include "headers.h"
|
||||
#include "calmwm.h"
|
||||
|
||||
/*
|
||||
* NOTE: in reality, many of these should move to client.c now that
|
||||
* we've got this nice event layer.
|
||||
*/
|
||||
static void xev_handle_maprequest(XEvent *);
|
||||
static void xev_handle_unmapnotify(XEvent *);
|
||||
static void xev_handle_destroynotify(XEvent *);
|
||||
static void xev_handle_configurerequest(XEvent *);
|
||||
static void xev_handle_propertynotify(XEvent *);
|
||||
static void xev_handle_enternotify(XEvent *);
|
||||
static void xev_handle_leavenotify(XEvent *);
|
||||
static void xev_handle_buttonpress(XEvent *);
|
||||
static void xev_handle_buttonrelease(XEvent *);
|
||||
static void xev_handle_keypress(XEvent *);
|
||||
static void xev_handle_keyrelease(XEvent *);
|
||||
static void xev_handle_expose(XEvent *);
|
||||
static void xev_handle_clientmessage(XEvent *);
|
||||
static void xev_handle_randr(XEvent *);
|
||||
static void xev_handle_mappingnotify(XEvent *);
|
||||
|
||||
void
|
||||
xev_handle_maprequest(struct xevent *xev, XEvent *ee)
|
||||
|
||||
void (*xev_handlers[LASTEvent])(XEvent *) = {
|
||||
[MapRequest] = xev_handle_maprequest,
|
||||
[UnmapNotify] = xev_handle_unmapnotify,
|
||||
[ConfigureRequest] = xev_handle_configurerequest,
|
||||
[PropertyNotify] = xev_handle_propertynotify,
|
||||
[EnterNotify] = xev_handle_enternotify,
|
||||
[LeaveNotify] = xev_handle_leavenotify,
|
||||
[ButtonPress] = xev_handle_buttonpress,
|
||||
[ButtonRelease] = xev_handle_buttonrelease,
|
||||
[KeyPress] = xev_handle_keypress,
|
||||
[KeyRelease] = xev_handle_keyrelease,
|
||||
[Expose] = xev_handle_expose,
|
||||
[DestroyNotify] = xev_handle_destroynotify,
|
||||
[ClientMessage] = xev_handle_clientmessage,
|
||||
[MappingNotify] = xev_handle_mappingnotify,
|
||||
};
|
||||
|
||||
static void
|
||||
xev_handle_maprequest(XEvent *ee)
|
||||
{
|
||||
XMapRequestEvent *e = &ee->xmaprequest;
|
||||
XWindowAttributes xattr;
|
||||
struct client_ctx *cc = NULL, *old_cc;
|
||||
struct screen_ctx *sc;
|
||||
|
||||
#ifdef notyet
|
||||
int state;
|
||||
#endif
|
||||
XWindowAttributes xattr;
|
||||
|
||||
if ((old_cc = client_current()) != NULL)
|
||||
client_ptrsave(old_cc);
|
||||
@@ -50,46 +74,50 @@ xev_handle_maprequest(struct xevent *xev, XEvent *ee)
|
||||
if ((cc = client_find(e->window)) == NULL) {
|
||||
XGetWindowAttributes(X_Dpy, e->window, &xattr);
|
||||
cc = client_new(e->window, screen_fromroot(xattr.root), 1);
|
||||
sc = CCTOSC(cc);
|
||||
} else
|
||||
cc->beepbeep = 1;
|
||||
|
||||
#ifdef notyet /* XXX - possibly, we shouldn't map if
|
||||
* the window is withdrawn. */
|
||||
if (xu_getstate(cc, &state) == 0 && state == WithdrawnState)
|
||||
warnx("WITHDRAWNSTATE for %s", cc->name);
|
||||
#endif
|
||||
}
|
||||
|
||||
client_ptrwarp(cc);
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_unmapnotify(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_unmapnotify(XEvent *ee)
|
||||
{
|
||||
XUnmapEvent *e = &ee->xunmap;
|
||||
XEvent ev;
|
||||
struct client_ctx *cc;
|
||||
|
||||
if ((cc = client_find(e->window)) != NULL)
|
||||
client_delete(cc, e->send_event, 0);
|
||||
|
||||
xev_register(xev);
|
||||
/* XXX, we need a recursive locking wrapper around grab server */
|
||||
XGrabServer(X_Dpy);
|
||||
if ((cc = client_find(e->window)) != NULL) {
|
||||
/*
|
||||
* If it's going to die anyway, nuke it.
|
||||
*
|
||||
* Else, if it's a synthetic event delete state, since they
|
||||
* want it to be withdrawn. ICCM recommends you withdraw on
|
||||
* this even if we haven't alredy been told to iconify, to
|
||||
* deal with legacy clients.
|
||||
*/
|
||||
if (XCheckTypedWindowEvent(X_Dpy, cc->win,
|
||||
DestroyNotify, &ev) || e->send_event != 0) {
|
||||
client_delete(cc);
|
||||
} else
|
||||
client_hide(cc);
|
||||
}
|
||||
XUngrabServer(X_Dpy);
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_destroynotify(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_destroynotify(XEvent *ee)
|
||||
{
|
||||
XDestroyWindowEvent *e = &ee->xdestroywindow;
|
||||
struct client_ctx *cc;
|
||||
|
||||
if ((cc = client_find(e->window)) != NULL)
|
||||
client_delete(cc, 1, 1);
|
||||
|
||||
xev_register(xev);
|
||||
client_delete(cc);
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_configurerequest(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_configurerequest(XEvent *ee)
|
||||
{
|
||||
XConfigureRequestEvent *e = &ee->xconfigurerequest;
|
||||
struct client_ctx *cc;
|
||||
@@ -99,7 +127,6 @@ xev_handle_configurerequest(struct xevent *xev, XEvent *ee)
|
||||
if ((cc = client_find(e->window)) != NULL) {
|
||||
sc = CCTOSC(cc);
|
||||
|
||||
client_gravitate(cc, 0);
|
||||
if (e->value_mask & CWWidth)
|
||||
cc->geom.width = e->width;
|
||||
if (e->value_mask & CWHeight)
|
||||
@@ -108,44 +135,39 @@ xev_handle_configurerequest(struct xevent *xev, XEvent *ee)
|
||||
cc->geom.x = e->x;
|
||||
if (e->value_mask & CWY)
|
||||
cc->geom.y = e->y;
|
||||
if (e->value_mask & CWBorderWidth)
|
||||
wc.border_width = e->border_width;
|
||||
|
||||
if (cc->geom.x == 0 &&
|
||||
cc->geom.width >= DisplayWidth(X_Dpy, sc->which))
|
||||
if (cc->geom.x == 0 && cc->geom.width >= sc->xmax)
|
||||
cc->geom.x -= cc->bwidth;
|
||||
|
||||
if (cc->geom.y == 0 &&
|
||||
cc->geom.height >= DisplayHeight(X_Dpy, sc->which))
|
||||
if (cc->geom.y == 0 && cc->geom.height >= sc->ymax)
|
||||
cc->geom.y -= cc->bwidth;
|
||||
|
||||
client_gravitate(cc, 1);
|
||||
wc.x = cc->geom.x;
|
||||
wc.y = cc->geom.y;
|
||||
wc.width = cc->geom.width;
|
||||
wc.height = cc->geom.height;
|
||||
wc.border_width = cc->bwidth;
|
||||
|
||||
wc.x = cc->geom.x - cc->bwidth;
|
||||
wc.y = cc->geom.y - cc->bwidth;
|
||||
wc.width = cc->geom.width + cc->bwidth*2;
|
||||
wc.height = cc->geom.height + cc->bwidth*2;
|
||||
wc.border_width = 0;
|
||||
|
||||
/* We need to move the parent window, too. */
|
||||
XConfigureWindow(X_Dpy, cc->pwin, e->value_mask, &wc);
|
||||
XConfigureWindow(X_Dpy, cc->win, e->value_mask, &wc);
|
||||
xev_reconfig(cc);
|
||||
} else {
|
||||
/* let it do what it wants, it'll be ours when we map it. */
|
||||
wc.x = e->x;
|
||||
wc.y = e->y;
|
||||
wc.width = e->width;
|
||||
wc.height = e->height;
|
||||
wc.border_width = e->border_width;
|
||||
wc.stack_mode = Above;
|
||||
e->value_mask &= ~CWStackMode;
|
||||
|
||||
XConfigureWindow(X_Dpy, e->window, e->value_mask, &wc);
|
||||
}
|
||||
|
||||
wc.x = cc != NULL ? cc->bwidth : e->x;
|
||||
wc.y = cc != NULL ? cc->bwidth : e->y;
|
||||
wc.width = e->width;
|
||||
wc.height = e->height;
|
||||
wc.stack_mode = Above;
|
||||
wc.border_width = 0;
|
||||
e->value_mask &= ~CWStackMode;
|
||||
e->value_mask |= CWBorderWidth;
|
||||
|
||||
XConfigureWindow(X_Dpy, e->window, e->value_mask, &wc);
|
||||
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_propertynotify(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_propertynotify(XEvent *ee)
|
||||
{
|
||||
XPropertyEvent *e = &ee->xproperty;
|
||||
struct client_ctx *cc;
|
||||
@@ -164,8 +186,6 @@ xev_handle_propertynotify(struct xevent *xev, XEvent *ee)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -180,52 +200,37 @@ xev_reconfig(struct client_ctx *cc)
|
||||
ce.y = cc->geom.y;
|
||||
ce.width = cc->geom.width;
|
||||
ce.height = cc->geom.height;
|
||||
ce.border_width = 0;
|
||||
ce.border_width = cc->bwidth;
|
||||
ce.above = None;
|
||||
ce.override_redirect = 0;
|
||||
|
||||
XSendEvent(X_Dpy, cc->win, False, StructureNotifyMask, (XEvent *)&ce);
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_enternotify(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_enternotify(XEvent *ee)
|
||||
{
|
||||
XCrossingEvent *e = &ee->xcrossing;
|
||||
struct client_ctx *cc;
|
||||
|
||||
if ((cc = client_find(e->window)) == NULL) {
|
||||
/*
|
||||
* XXX - later. messes up unclutter. but may be
|
||||
* needed when we introduce menu windows and such into
|
||||
* the main event loop.
|
||||
*/
|
||||
#ifdef notyet
|
||||
if (e->window != e->root)
|
||||
client_nocurrent();
|
||||
#endif
|
||||
} else
|
||||
if ((cc = client_find(e->window)) != NULL)
|
||||
client_setactive(cc, 1);
|
||||
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_leavenotify(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_leavenotify(XEvent *ee)
|
||||
{
|
||||
client_leave(NULL);
|
||||
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
/* We can split this into two event handlers. */
|
||||
void
|
||||
xev_handle_buttonpress(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_buttonpress(XEvent *ee)
|
||||
{
|
||||
XButtonEvent *e = &ee->xbutton;
|
||||
struct client_ctx *cc;
|
||||
struct screen_ctx *sc;
|
||||
struct mousebinding *mb;
|
||||
char *wname;
|
||||
|
||||
sc = screen_fromroot(e->root);
|
||||
cc = client_find(e->window);
|
||||
@@ -239,35 +244,31 @@ xev_handle_buttonpress(struct xevent *xev, XEvent *ee)
|
||||
}
|
||||
|
||||
if (mb == NULL)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
if (mb->context == MOUSEBIND_CTX_ROOT) {
|
||||
if (e->window != sc->rootwin)
|
||||
goto out;
|
||||
return;
|
||||
} else if (mb->context == MOUSEBIND_CTX_WIN) {
|
||||
cc = client_find(e->window);
|
||||
if (cc == NULL)
|
||||
goto out;
|
||||
return;
|
||||
}
|
||||
|
||||
(*mb->callback)(cc, e);
|
||||
out:
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_buttonrelease(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_buttonrelease(XEvent *ee)
|
||||
{
|
||||
struct client_ctx *cc;
|
||||
|
||||
if ((cc = client_current()) != NULL)
|
||||
group_sticky_toggle_exit(cc);
|
||||
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_keypress(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_keypress(XEvent *ee)
|
||||
{
|
||||
XKeyEvent *e = &ee->xkey;
|
||||
struct client_ctx *cc = NULL;
|
||||
@@ -297,25 +298,22 @@ xev_handle_keypress(struct xevent *xev, XEvent *ee)
|
||||
}
|
||||
|
||||
if (kb == NULL)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
if ((kb->flags & (KBFLAG_NEEDCLIENT)) &&
|
||||
(cc = client_find(e->window)) == NULL &&
|
||||
(cc = client_current()) == NULL)
|
||||
if (kb->flags & KBFLAG_NEEDCLIENT)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
(*kb->callback)(cc, kb->argument);
|
||||
|
||||
out:
|
||||
xev_register(xev);
|
||||
(*kb->callback)(cc, &kb->argument);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is only used for the alt suppression detection.
|
||||
*/
|
||||
void
|
||||
xev_handle_keyrelease(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_keyrelease(XEvent *ee)
|
||||
{
|
||||
XKeyEvent *e = &ee->xkey;
|
||||
struct screen_ctx *sc;
|
||||
@@ -327,7 +325,7 @@ xev_handle_keyrelease(struct xevent *xev, XEvent *ee)
|
||||
|
||||
keysym = XKeycodeToKeysym(X_Dpy, e->keycode, 0);
|
||||
if (keysym != XK_Alt_L && keysym != XK_Alt_R)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
sc->altpersist = 0;
|
||||
|
||||
@@ -341,13 +339,10 @@ xev_handle_keyrelease(struct xevent *xev, XEvent *ee)
|
||||
group_sticky_toggle_exit(cc);
|
||||
XUngrabKeyboard(X_Dpy, CurrentTime);
|
||||
}
|
||||
|
||||
out:
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_clientmessage(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_clientmessage(XEvent *ee)
|
||||
{
|
||||
XClientMessageEvent *e = &ee->xclient;
|
||||
Atom xa_wm_change_state;
|
||||
@@ -356,31 +351,37 @@ xev_handle_clientmessage(struct xevent *xev, XEvent *ee)
|
||||
xa_wm_change_state = XInternAtom(X_Dpy, "WM_CHANGE_STATE", False);
|
||||
|
||||
if ((cc = client_find(e->window)) == NULL)
|
||||
goto out;
|
||||
return;
|
||||
|
||||
if (e->message_type == xa_wm_change_state && e->format == 32 &&
|
||||
e->data.l[0] == IconicState)
|
||||
client_hide(cc);
|
||||
out:
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_shape(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_randr(XEvent *ee)
|
||||
{
|
||||
XShapeEvent *sev = (XShapeEvent *) ee;
|
||||
struct client_ctx *cc;
|
||||
XRRScreenChangeNotifyEvent *rev = (XRRScreenChangeNotifyEvent *)ee;
|
||||
struct screen_ctx *sc;
|
||||
int i;
|
||||
|
||||
if ((cc = client_find(sev->window)) != NULL)
|
||||
client_do_shape(cc);
|
||||
i = XRRRootToScreen(X_Dpy, rev->root);
|
||||
TAILQ_FOREACH(sc, &Screenq, entry) {
|
||||
if (sc->which == (u_int)i) {
|
||||
XRRUpdateConfiguration(ee);
|
||||
sc->xmax = rev->width;
|
||||
sc->ymax = rev->height;
|
||||
screen_init_xinerama(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called when the keymap has changed.
|
||||
* Ungrab all keys, reload keymap and then regrab
|
||||
*/
|
||||
void
|
||||
xev_handle_mapping(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_mappingnotify(XEvent *ee)
|
||||
{
|
||||
XMappingEvent *e = &ee->xmapping;
|
||||
struct keybinding *kb;
|
||||
@@ -392,162 +393,31 @@ xev_handle_mapping(struct xevent *xev, XEvent *ee)
|
||||
|
||||
TAILQ_FOREACH(kb, &Conf.keybindingq, entry)
|
||||
conf_grab(&Conf, kb);
|
||||
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
/*
|
||||
* X Event handling
|
||||
*/
|
||||
|
||||
static struct xevent_q _xevq, _xevq_putaway;
|
||||
static short _xev_q_lock = 0;
|
||||
volatile sig_atomic_t _xev_quit = 0;
|
||||
|
||||
void
|
||||
xev_init(void)
|
||||
{
|
||||
TAILQ_INIT(&_xevq);
|
||||
TAILQ_INIT(&_xevq_putaway);
|
||||
}
|
||||
|
||||
struct xevent *
|
||||
xev_new(Window *win, Window *root,
|
||||
int type, void (*cb)(struct xevent *, XEvent *), void *arg)
|
||||
{
|
||||
struct xevent *xev;
|
||||
|
||||
XMALLOC(xev, struct xevent);
|
||||
xev->xev_win = win;
|
||||
xev->xev_root = root;
|
||||
xev->xev_type = type;
|
||||
xev->xev_cb = cb;
|
||||
xev->xev_arg = arg;
|
||||
|
||||
return (xev);
|
||||
}
|
||||
|
||||
void
|
||||
xev_register(struct xevent *xev)
|
||||
{
|
||||
struct xevent_q *xq;
|
||||
|
||||
xq = _xev_q_lock ? &_xevq_putaway : &_xevq;
|
||||
TAILQ_INSERT_TAIL(xq, xev, entry);
|
||||
}
|
||||
|
||||
void
|
||||
_xev_reincorporate(void)
|
||||
{
|
||||
struct xevent *xev;
|
||||
|
||||
while ((xev = TAILQ_FIRST(&_xevq_putaway)) != NULL) {
|
||||
TAILQ_REMOVE(&_xevq_putaway, xev, entry);
|
||||
TAILQ_INSERT_TAIL(&_xevq, xev, entry);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xev_handle_expose(struct xevent *xev, XEvent *ee)
|
||||
static void
|
||||
xev_handle_expose(XEvent *ee)
|
||||
{
|
||||
XExposeEvent *e = &ee->xexpose;
|
||||
struct client_ctx *cc;
|
||||
|
||||
if ((cc = client_find(e->window)) != NULL && e->count == 0) {
|
||||
if ((cc = client_find(e->window)) != NULL && e->count == 0)
|
||||
client_draw_border(cc);
|
||||
client_do_shape(cc);
|
||||
}
|
||||
|
||||
xev_register(xev);
|
||||
}
|
||||
|
||||
#define ASSIGN(xtype) do { \
|
||||
root = e. xtype .root; \
|
||||
win = e. xtype .window; \
|
||||
} while (0)
|
||||
|
||||
#define ASSIGN1(xtype) do { \
|
||||
win = e. xtype .window; \
|
||||
} while (0)
|
||||
volatile sig_atomic_t _xev_quit = 0;
|
||||
|
||||
void
|
||||
xev_loop(void)
|
||||
{
|
||||
Window win, root;
|
||||
XEvent e;
|
||||
struct xevent *xev = NULL, *nextxev;
|
||||
int type;
|
||||
|
||||
while (_xev_quit == 0) {
|
||||
#ifdef DIAGNOSTIC
|
||||
if (TAILQ_EMPTY(&_xevq))
|
||||
errx(1, "X event queue empty");
|
||||
#endif
|
||||
|
||||
XNextEvent(X_Dpy, &e);
|
||||
type = e.type;
|
||||
|
||||
win = root = 0;
|
||||
|
||||
switch (type) {
|
||||
case MapRequest:
|
||||
ASSIGN1(xmaprequest);
|
||||
break;
|
||||
case UnmapNotify:
|
||||
ASSIGN1(xunmap);
|
||||
break;
|
||||
case ConfigureRequest:
|
||||
ASSIGN1(xconfigurerequest);
|
||||
break;
|
||||
case PropertyNotify:
|
||||
ASSIGN1(xproperty);
|
||||
break;
|
||||
case EnterNotify:
|
||||
case LeaveNotify:
|
||||
ASSIGN(xcrossing);
|
||||
break;
|
||||
case ButtonPress:
|
||||
ASSIGN(xbutton);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
ASSIGN(xbutton);
|
||||
break;
|
||||
case KeyPress:
|
||||
case KeyRelease:
|
||||
ASSIGN(xkey);
|
||||
break;
|
||||
case DestroyNotify:
|
||||
ASSIGN1(xdestroywindow);
|
||||
break;
|
||||
case ClientMessage:
|
||||
ASSIGN1(xclient);
|
||||
break;
|
||||
default:
|
||||
if (e.type == Shape_ev)
|
||||
xev_handle_shape(xev, &e);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, search for matches, and call each of them.
|
||||
*/
|
||||
_xev_q_lock = 1;
|
||||
for (xev = TAILQ_FIRST(&_xevq); xev != NULL; xev = nextxev) {
|
||||
nextxev = TAILQ_NEXT(xev, entry);
|
||||
|
||||
if ((type != xev->xev_type && xev->xev_type != 0) ||
|
||||
(xev->xev_win != NULL && win != *xev->xev_win) ||
|
||||
(xev->xev_root != NULL && root != *xev->xev_root))
|
||||
continue;
|
||||
|
||||
TAILQ_REMOVE(&_xevq, xev, entry);
|
||||
|
||||
(*xev->xev_cb)(xev, &e);
|
||||
}
|
||||
_xev_q_lock = 0;
|
||||
_xev_reincorporate();
|
||||
if (e.type - Randr_ev == RRScreenChangeNotify)
|
||||
xev_handle_randr(&e);
|
||||
else if (e.type < LASTEvent && xev_handlers[e.type] != NULL)
|
||||
(*xev_handlers[e.type])(&e);
|
||||
}
|
||||
}
|
||||
|
||||
#undef ASSIGN
|
||||
#undef ASSIGN1
|
||||
|
53
xutil.c
53
xutil.c
@@ -21,7 +21,7 @@
|
||||
#include "headers.h"
|
||||
#include "calmwm.h"
|
||||
|
||||
unsigned int ign_mods[] = { 0, LockMask, Mod2Mask, Mod2Mask | LockMask };
|
||||
static unsigned int ign_mods[] = { 0, LockMask, Mod2Mask, Mod2Mask | LockMask };
|
||||
|
||||
int
|
||||
xu_ptr_grab(Window win, int mask, Cursor curs)
|
||||
@@ -145,12 +145,9 @@ xu_getprop(struct client_ctx *cc, Atom atm, Atom type, long len, u_char **p)
|
||||
int
|
||||
xu_getstate(struct client_ctx *cc, int *state)
|
||||
{
|
||||
Atom wm_state;
|
||||
long *p = NULL;
|
||||
|
||||
wm_state = XInternAtom(X_Dpy, "WM_STATE", False);
|
||||
|
||||
if (xu_getprop(cc, wm_state, wm_state, 2L, (u_char **)&p) <= 0)
|
||||
if (xu_getprop(cc, WM_STATE, WM_STATE, 2L, (u_char **)&p) <= 0)
|
||||
return (-1);
|
||||
|
||||
*state = (int)*p;
|
||||
@@ -162,16 +159,48 @@ xu_getstate(struct client_ctx *cc, int *state)
|
||||
void
|
||||
xu_setstate(struct client_ctx *cc, int state)
|
||||
{
|
||||
Atom wm_state;
|
||||
long dat[2];
|
||||
|
||||
/* XXX cache */
|
||||
wm_state = XInternAtom(X_Dpy, "WM_STATE", False);
|
||||
|
||||
dat[0] = (long)state;
|
||||
dat[1] = (long)None;
|
||||
dat[0] = state;
|
||||
dat[1] = None;
|
||||
|
||||
cc->state = state;
|
||||
XChangeProperty(X_Dpy, cc->win, wm_state, wm_state, 32,
|
||||
XChangeProperty(X_Dpy, cc->win, WM_STATE, WM_STATE, 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",
|
||||
"_CWM_GRP",
|
||||
};
|
||||
|
||||
void
|
||||
xu_getatoms(void)
|
||||
{
|
||||
XInternAtoms(X_Dpy, atoms, CWM_NO_ATOMS, False, cwm_atoms);
|
||||
}
|
||||
|
||||
unsigned long
|
||||
xu_getcolor(struct screen_ctx *sc, char *name)
|
||||
{
|
||||
XColor color, tmp;
|
||||
|
||||
if (!XAllocNamedColor(X_Dpy, DefaultColormap(X_Dpy, sc->which),
|
||||
name, &color, &tmp)) {
|
||||
warnx("XAllocNamedColor error: '%s'", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return color.pixel;
|
||||
}
|
||||
|
||||
void
|
||||
xu_freecolor(struct screen_ctx *sc, unsigned long pixel)
|
||||
{
|
||||
XFreeColors(X_Dpy, DefaultColormap(X_Dpy, sc->which), &pixel, 1, 0L);
|
||||
}
|
||||
|
Reference in New Issue
Block a user