mirror of
https://github.com/leahneukirchen/cwm.git
synced 2023-08-10 21:13:12 +03:00
Compare commits
48 Commits
Author | SHA1 | Date | |
---|---|---|---|
669e3406ec | |||
f2a2839cec | |||
4154b9b194 | |||
781af9c998 | |||
6131e36f8a | |||
fdb841c3b0 | |||
40000724cc | |||
25b699b582 | |||
3f1caab46a | |||
85d88f3304 | |||
9a7528f5b9 | |||
e55c0d48fa | |||
5bc2098c6f | |||
5071baa2aa | |||
4470a247c8 | |||
eab4b7e4b5 | |||
bf43b62414 | |||
2a3c2b5231 | |||
7c45b87622 | |||
01be5b4e4a | |||
823566a653 | |||
aa79351d2e | |||
b26202724a | |||
9efa6c8c85 | |||
0bda8f7606 | |||
9d5b0e5d22 | |||
fda68a40de | |||
0c0551b8bf | |||
9d25218458 | |||
412b0c9ef4 | |||
ae231f67d0 | |||
880b5cda3f | |||
8cd6d1154c | |||
f4286ad453 | |||
cd4be1c17a | |||
a5ba9aa9da | |||
43cd19378e | |||
953cf1ce89 | |||
535cf541c8 | |||
044ef5a8cd | |||
c307e37dcb | |||
544b4da339 | |||
695eb1d8e5 | |||
194589eb6b | |||
268deed916 | |||
a63b87e315 | |||
b4d4eba6af | |||
9999c3e6e0 |
2
Makefile
2
Makefile
@ -48,6 +48,6 @@ release:
|
||||
|
||||
sign:
|
||||
VERSION=$$(git describe --tags | sed 's/^v//;s/-[^.]*$$//') && \
|
||||
gpg --armor --detach-sign cwm-$$VERSION.tar.gz && \
|
||||
gpg2 --armor --detach-sign cwm-$$VERSION.tar.gz && \
|
||||
signify -S -s ~/.signify/cwm.sec -m cwm-$$VERSION.tar.gz && \
|
||||
sed -i '1cuntrusted comment: verify with cwm.pub' cwm-$$VERSION.tar.gz.sig
|
||||
|
15
README
15
README
@ -1,5 +1,4 @@
|
||||
This is a port of OpenBSD's excellent cwm[0] to Linux and other
|
||||
Unices.
|
||||
This is a port of OpenBSD's excellent cwm[0] to Linux and other Unices.
|
||||
|
||||
cwm is a window manager for X11 which contains many features that
|
||||
concentrate on the efficiency and transparency of window
|
||||
@ -13,8 +12,8 @@ OpenBSD, FreeBSD, NetBSD, OS X 10.9 and Linux.
|
||||
This version actively tracks changes in the OpenBSD CVS repository.
|
||||
Releases are roughly coordinated.
|
||||
|
||||
The revision controlled version is at https://github.com/chneukirchen/cwm
|
||||
Releases can be found at http://chneukirchen.org/releases
|
||||
The revision controlled version is at https://github.com/leahneukirchen/cwm
|
||||
Releases can be found at http://leahneukirchen.org/releases
|
||||
|
||||
You are welcome to join the IRC channel ##cwm on Freenode to talk about cwm.
|
||||
|
||||
@ -115,6 +114,14 @@ Changes made between OpenBSD 6.2 and 6.3
|
||||
|
||||
2018-05-14: Fifth public release 6.3 of portable cwm.
|
||||
|
||||
2020-01-04: Sixth public release 6.6 of portable cwm.
|
||||
|
||||
Changes made between OpenBSD 6.4 and 6.5
|
||||
* Added a configtest flag (-n) to cwm(1).
|
||||
* Introduced 'group-close-[n]' action to cwm(1) to close all windows
|
||||
within a specified group.
|
||||
|
||||
|
||||
--Leah Neukirchen <leah@vuxu.org>
|
||||
|
||||
[0]: http://cvsweb.openbsd.org/cgi-bin/cvsweb/xenocara/app/cwm/
|
||||
|
18
calmwm.c
18
calmwm.c
@ -55,7 +55,7 @@ main(int argc, char **argv)
|
||||
{
|
||||
char *display_name = NULL;
|
||||
char *fallback;
|
||||
int ch, xfd;
|
||||
int ch, xfd, nflag = 0;
|
||||
struct pollfd pfd[1];
|
||||
|
||||
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
|
||||
@ -66,7 +66,7 @@ main(int argc, char **argv)
|
||||
|
||||
fallback = u_argv(argv);
|
||||
Conf.wm_argv = u_argv(argv);
|
||||
while ((ch = getopt(argc, argv, "c:d:v")) != -1) {
|
||||
while ((ch = getopt(argc, argv, "c:d:nv")) != -1) {
|
||||
switch (ch) {
|
||||
case 'c':
|
||||
free(Conf.conf_file);
|
||||
@ -75,6 +75,9 @@ main(int argc, char **argv)
|
||||
case 'd':
|
||||
display_name = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
nflag = 1;
|
||||
break;
|
||||
case 'v':
|
||||
Conf.debug++;
|
||||
break;
|
||||
@ -90,8 +93,13 @@ main(int argc, char **argv)
|
||||
if (signal(SIGHUP, sighdlr) == SIG_ERR)
|
||||
err(1, "signal");
|
||||
|
||||
if (parse_config(Conf.conf_file, &Conf) == -1)
|
||||
if (parse_config(Conf.conf_file, &Conf) == -1) {
|
||||
warnx("error parsing config file");
|
||||
if (nflag)
|
||||
return 1;
|
||||
}
|
||||
if (nflag)
|
||||
return 0;
|
||||
|
||||
xfd = x_init(display_name);
|
||||
cwm_status = CWM_RUNNING;
|
||||
@ -159,8 +167,6 @@ x_teardown(void)
|
||||
DefaultColormap(X_Dpy, sc->which),
|
||||
&sc->xftcolor[i]);
|
||||
XftFontClose(X_Dpy, sc->xftfont);
|
||||
XftDrawDestroy(sc->menu.xftdraw);
|
||||
XDestroyWindow(X_Dpy, sc->menu.win);
|
||||
XUngrabKey(X_Dpy, AnyKey, AnyModifier, sc->rootwin);
|
||||
}
|
||||
XUngrabPointer(X_Dpy, CurrentTime);
|
||||
@ -221,7 +227,7 @@ usage(void)
|
||||
{
|
||||
extern char *__progname;
|
||||
|
||||
(void)fprintf(stderr, "usage: %s [-v] [-c file] [-d display]\n",
|
||||
(void)fprintf(stderr, "usage: %s [-nv] [-c file] [-d display]\n",
|
||||
__progname);
|
||||
exit(1);
|
||||
}
|
||||
|
43
calmwm.h
43
calmwm.h
@ -68,9 +68,6 @@ size_t strlcpy(char *, const char *, size_t);
|
||||
|
||||
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
|
||||
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
|
||||
#define MENUMASK (MOUSEMASK | ButtonMotionMask | KeyPressMask | \
|
||||
ExposureMask)
|
||||
#define MENUGRABMASK (MOUSEMASK | ButtonMotionMask | StructureNotifyMask)
|
||||
#define IGNOREMODMASK (LockMask | Mod2Mask | 0x2000)
|
||||
|
||||
/* direction/amount */
|
||||
@ -145,12 +142,12 @@ TAILQ_HEAD(ignore_q, winname);
|
||||
|
||||
struct client_ctx {
|
||||
TAILQ_ENTRY(client_ctx) entry;
|
||||
TAILQ_ENTRY(client_ctx) group_entry;
|
||||
struct screen_ctx *sc;
|
||||
struct group_ctx *gc;
|
||||
Window win;
|
||||
Colormap colormap;
|
||||
int bwidth; /* border width */
|
||||
int obwidth; /* original border width */
|
||||
struct geom geom, savegeom, fullgeom;
|
||||
struct {
|
||||
long flags; /* defined hints */
|
||||
@ -210,7 +207,6 @@ struct group_ctx {
|
||||
struct screen_ctx *sc;
|
||||
char *name;
|
||||
int num;
|
||||
struct client_q clientq;
|
||||
};
|
||||
TAILQ_HEAD(group_q, group_ctx);
|
||||
|
||||
@ -249,7 +245,7 @@ struct screen_ctx {
|
||||
struct {
|
||||
Window win;
|
||||
XftDraw *xftdraw;
|
||||
} menu;
|
||||
} prop;
|
||||
XftColor xftcolor[CWM_COLOR_NITEMS];
|
||||
XftFont *xftfont;
|
||||
};
|
||||
@ -419,9 +415,9 @@ void usage(void);
|
||||
|
||||
void client_applysizehints(struct client_ctx *);
|
||||
void client_config(struct client_ctx *);
|
||||
struct client_ctx *client_current(void);
|
||||
struct client_ctx *client_current(struct screen_ctx *);
|
||||
void client_cycle(struct screen_ctx *, int);
|
||||
void client_delete(struct client_ctx *);
|
||||
void client_remove(struct client_ctx *);
|
||||
void client_draw_border(struct client_ctx *);
|
||||
struct client_ctx *client_find(Window);
|
||||
long client_get_wm_state(struct client_ctx *);
|
||||
@ -429,7 +425,6 @@ void client_getsizehints(struct client_ctx *);
|
||||
void client_hide(struct client_ctx *);
|
||||
void client_htile(struct client_ctx *);
|
||||
void client_lower(struct client_ctx *);
|
||||
void client_map(struct client_ctx *);
|
||||
void client_msg(struct client_ctx *, Atom, Time);
|
||||
void client_move(struct client_ctx *);
|
||||
void client_mtf(struct client_ctx *);
|
||||
@ -440,7 +435,7 @@ void client_ptrsave(struct client_ctx *);
|
||||
void client_ptrwarp(struct client_ctx *);
|
||||
void client_raise(struct client_ctx *);
|
||||
void client_resize(struct client_ctx *, int);
|
||||
void client_send_delete(struct client_ctx *);
|
||||
void client_close(struct client_ctx *);
|
||||
void client_set_wm_state(struct client_ctx *, long);
|
||||
void client_setactive(struct client_ctx *);
|
||||
void client_setname(struct client_ctx *);
|
||||
@ -456,24 +451,24 @@ void client_toggle_skip_taskbar(struct client_ctx *);
|
||||
void client_toggle_sticky(struct client_ctx *);
|
||||
void client_toggle_vmaximize(struct client_ctx *);
|
||||
void client_transient(struct client_ctx *);
|
||||
void client_unhide(struct client_ctx *);
|
||||
void client_urgency(struct client_ctx *);
|
||||
void client_vtile(struct client_ctx *);
|
||||
void client_wm_hints(struct client_ctx *);
|
||||
|
||||
void group_alltoggle(struct screen_ctx *);
|
||||
void group_assign(struct group_ctx *, struct client_ctx *);
|
||||
int group_autogroup(struct client_ctx *);
|
||||
void group_cycle(struct screen_ctx *, int);
|
||||
void group_hide(struct group_ctx *);
|
||||
void group_hidetoggle(struct screen_ctx *, int);
|
||||
int group_holds_only_hidden(struct group_ctx *);
|
||||
int group_holds_only_sticky(struct group_ctx *);
|
||||
void group_init(struct screen_ctx *, int);
|
||||
void group_init(struct screen_ctx *, int, const char *);
|
||||
void group_movetogroup(struct client_ctx *, int);
|
||||
void group_only(struct screen_ctx *, int);
|
||||
void group_close(struct screen_ctx *, int);
|
||||
int group_restore(struct client_ctx *);
|
||||
void group_show(struct group_ctx *);
|
||||
void group_toggle(struct screen_ctx *, int);
|
||||
void group_toggle_all(struct screen_ctx *);
|
||||
void group_toggle_membership(struct client_ctx *);
|
||||
void group_update_names(struct screen_ctx *);
|
||||
|
||||
@ -505,13 +500,19 @@ void screen_init(int);
|
||||
void screen_update_geometry(struct screen_ctx *);
|
||||
void screen_updatestackingorder(struct screen_ctx *);
|
||||
void screen_assert_clients_within(struct screen_ctx *);
|
||||
void screen_prop_win_create(struct screen_ctx *, Window);
|
||||
void screen_prop_win_destroy(struct screen_ctx *);
|
||||
void screen_prop_win_draw(struct screen_ctx *,
|
||||
const char *, ...)
|
||||
__attribute__((__format__ (printf, 2, 3)))
|
||||
__attribute__((__nonnull__ (2)));
|
||||
|
||||
void kbfunc_cwm_status(void *, struct cargs *);
|
||||
void kbfunc_ptrmove(void *, struct cargs *);
|
||||
void kbfunc_client_snap(void *, struct cargs *);
|
||||
void kbfunc_client_move(void *, struct cargs *);
|
||||
void kbfunc_client_resize(void *, struct cargs *);
|
||||
void kbfunc_client_delete(void *, struct cargs *);
|
||||
void kbfunc_client_close(void *, struct cargs *);
|
||||
void kbfunc_client_lower(void *, struct cargs *);
|
||||
void kbfunc_client_raise(void *, struct cargs *);
|
||||
void kbfunc_client_hide(void *, struct cargs *);
|
||||
@ -529,8 +530,9 @@ void kbfunc_client_toggle_group(void *, struct cargs *);
|
||||
void kbfunc_client_movetogroup(void *, struct cargs *);
|
||||
void kbfunc_group_toggle(void *, struct cargs *);
|
||||
void kbfunc_group_only(void *, struct cargs *);
|
||||
void kbfunc_group_close(void *, struct cargs *);
|
||||
void kbfunc_group_cycle(void *, struct cargs *);
|
||||
void kbfunc_group_alltoggle(void *, struct cargs *);
|
||||
void kbfunc_group_toggle_all(void *, struct cargs *);
|
||||
void kbfunc_menu_client(void *, struct cargs *);
|
||||
void kbfunc_menu_cmd(void *, struct cargs *);
|
||||
void kbfunc_menu_group(void *, struct cargs *);
|
||||
@ -542,10 +544,6 @@ void kbfunc_exec_cmd(void *, struct cargs *);
|
||||
void kbfunc_exec_lock(void *, struct cargs *);
|
||||
void kbfunc_exec_term(void *, struct cargs *);
|
||||
|
||||
void menu_windraw(struct screen_ctx *, Window,
|
||||
const char *, ...)
|
||||
__attribute__((__format__ (printf, 3, 4)))
|
||||
__attribute__((__nonnull__ (3)));
|
||||
struct menu *menu_filter(struct screen_ctx *, struct menu_q *,
|
||||
const char *, const char *, int,
|
||||
void (*)(struct menu_q *, struct menu_q *, char *),
|
||||
@ -575,6 +573,7 @@ void conf_grab_mouse(Window);
|
||||
void conf_init(struct conf *);
|
||||
void conf_ignore(struct conf *, const char *);
|
||||
void conf_screen(struct screen_ctx *);
|
||||
void conf_group(struct screen_ctx *);
|
||||
|
||||
void xev_process(void);
|
||||
|
||||
@ -587,13 +586,13 @@ void xu_xorcolor(XftColor, XftColor, XftColor *);
|
||||
void xu_ewmh_net_supported(struct screen_ctx *);
|
||||
void xu_ewmh_net_supported_wm_check(struct screen_ctx *);
|
||||
void xu_ewmh_net_desktop_geometry(struct screen_ctx *);
|
||||
void xu_ewmh_net_desktop_viewport(struct screen_ctx *);
|
||||
void xu_ewmh_net_workarea(struct screen_ctx *);
|
||||
void xu_ewmh_net_client_list(struct screen_ctx *);
|
||||
void xu_ewmh_net_client_list_stacking(struct screen_ctx *);
|
||||
void xu_ewmh_net_active_window(struct screen_ctx *, Window);
|
||||
Window xu_ewmh_get_net_active_window(struct screen_ctx *);
|
||||
void xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *);
|
||||
void xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *);
|
||||
void xu_ewmh_net_number_of_desktops(struct screen_ctx *);
|
||||
void xu_ewmh_net_showing_desktop(struct screen_ctx *);
|
||||
void xu_ewmh_net_virtual_roots(struct screen_ctx *);
|
||||
void xu_ewmh_net_current_desktop(struct screen_ctx *);
|
||||
|
166
client.c
166
client.c
@ -62,10 +62,9 @@ client_init(Window win, struct screen_ctx *sc, int active)
|
||||
mapped = wattr.map_state != IsUnmapped;
|
||||
}
|
||||
|
||||
cc = xmalloc(sizeof(*cc));
|
||||
|
||||
XGrabServer(X_Dpy);
|
||||
|
||||
cc = xmalloc(sizeof(*cc));
|
||||
cc->sc = sc;
|
||||
cc->win = win;
|
||||
cc->label = NULL;
|
||||
@ -74,29 +73,33 @@ client_init(Window win, struct screen_ctx *sc, int active)
|
||||
cc->stackingorder = 0;
|
||||
memset(&cc->hint, 0, sizeof(cc->hint));
|
||||
memset(&cc->ch, 0, sizeof(cc->ch));
|
||||
|
||||
TAILQ_INIT(&cc->nameq);
|
||||
client_setname(cc);
|
||||
|
||||
cc->geom.x = wattr.x;
|
||||
cc->geom.y = wattr.y;
|
||||
cc->geom.w = wattr.width;
|
||||
cc->geom.h = wattr.height;
|
||||
cc->colormap = wattr.colormap;
|
||||
cc->obwidth = wattr.border_width;
|
||||
cc->bwidth = Conf.bwidth;
|
||||
|
||||
client_setname(cc);
|
||||
conf_client(cc);
|
||||
|
||||
XGetClassHint(X_Dpy, cc->win, &cc->ch);
|
||||
client_wm_hints(cc);
|
||||
client_wm_protocols(cc);
|
||||
client_getsizehints(cc);
|
||||
client_transient(cc);
|
||||
client_mwm_hints(cc);
|
||||
|
||||
cc->geom.x = wattr.x;
|
||||
cc->geom.y = wattr.y;
|
||||
cc->geom.w = wattr.width;
|
||||
cc->geom.h = wattr.height;
|
||||
if ((cc->flags & CLIENT_IGNORE))
|
||||
cc->bwidth = 0;
|
||||
cc->dim.w = (cc->geom.w - cc->hint.basew) / cc->hint.incw;
|
||||
cc->dim.h = (cc->geom.h - cc->hint.baseh) / cc->hint.inch;
|
||||
cc->ptr.x = cc->geom.w / 2;
|
||||
cc->ptr.y = cc->geom.h / 2;
|
||||
|
||||
cc->colormap = wattr.colormap;
|
||||
|
||||
if (wattr.map_state != IsViewable) {
|
||||
client_placecalc(cc);
|
||||
client_resize(cc, 0);
|
||||
@ -113,8 +116,6 @@ client_init(Window win, struct screen_ctx *sc, int active)
|
||||
|
||||
XAddToSaveSet(X_Dpy, cc->win);
|
||||
|
||||
client_transient(cc);
|
||||
|
||||
/* Notify client of its configuration. */
|
||||
client_config(cc);
|
||||
|
||||
@ -127,9 +128,13 @@ client_init(Window win, struct screen_ctx *sc, int active)
|
||||
if (client_get_wm_state(cc) == IconicState)
|
||||
client_hide(cc);
|
||||
else
|
||||
client_unhide(cc);
|
||||
client_show(cc);
|
||||
|
||||
if (mapped) {
|
||||
if (cc->gc) {
|
||||
group_movetogroup(cc, cc->gc->num);
|
||||
goto out;
|
||||
}
|
||||
if (group_restore(cc))
|
||||
goto out;
|
||||
if (group_autogroup(cc))
|
||||
@ -165,7 +170,7 @@ client_find(Window win)
|
||||
}
|
||||
|
||||
void
|
||||
client_delete(struct client_ctx *cc)
|
||||
client_remove(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = cc->sc;
|
||||
struct winname *wn;
|
||||
@ -178,9 +183,6 @@ client_delete(struct client_ctx *cc)
|
||||
if (cc->flags & CLIENT_ACTIVE)
|
||||
xu_ewmh_net_active_window(sc, None);
|
||||
|
||||
if (cc->gc != NULL)
|
||||
TAILQ_REMOVE(&cc->gc->clientq, cc, group_entry);
|
||||
|
||||
while ((wn = TAILQ_FIRST(&cc->nameq)) != NULL) {
|
||||
TAILQ_REMOVE(&cc->nameq, wn, entry);
|
||||
free(wn->name);
|
||||
@ -216,7 +218,7 @@ client_setactive(struct client_ctx *cc)
|
||||
if (cc->flags & CLIENT_WM_TAKE_FOCUS)
|
||||
client_msg(cc, cwmh[WM_TAKE_FOCUS], Last_Event_Time);
|
||||
|
||||
if ((oldcc = client_current()) != NULL) {
|
||||
if ((oldcc = client_current(sc)) != NULL) {
|
||||
oldcc->flags &= ~CLIENT_ACTIVE;
|
||||
client_draw_border(oldcc);
|
||||
}
|
||||
@ -233,16 +235,23 @@ client_setactive(struct client_ctx *cc)
|
||||
}
|
||||
|
||||
struct client_ctx *
|
||||
client_current(void)
|
||||
client_current(struct screen_ctx *sc)
|
||||
{
|
||||
struct screen_ctx *sc;
|
||||
struct screen_ctx *_sc;
|
||||
struct client_ctx *cc;
|
||||
|
||||
TAILQ_FOREACH(sc, &Screenq, entry) {
|
||||
if (sc) {
|
||||
TAILQ_FOREACH(cc, &sc->clientq, entry) {
|
||||
if (cc->flags & CLIENT_ACTIVE)
|
||||
return(cc);
|
||||
}
|
||||
} else {
|
||||
TAILQ_FOREACH(_sc, &Screenq, entry) {
|
||||
TAILQ_FOREACH(cc, &_sc->clientq, entry) {
|
||||
if (cc->flags & CLIENT_ACTIVE)
|
||||
return(cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
@ -522,25 +531,16 @@ client_hide(struct client_ctx *cc)
|
||||
{
|
||||
XUnmapWindow(X_Dpy, cc->win);
|
||||
|
||||
if (cc->flags & CLIENT_ACTIVE)
|
||||
if (cc->flags & CLIENT_ACTIVE) {
|
||||
cc->flags &= ~CLIENT_ACTIVE;
|
||||
xu_ewmh_net_active_window(cc->sc, None);
|
||||
|
||||
cc->flags &= ~CLIENT_ACTIVE;
|
||||
}
|
||||
cc->flags |= CLIENT_HIDDEN;
|
||||
client_set_wm_state(cc, IconicState);
|
||||
}
|
||||
|
||||
void
|
||||
client_show(struct client_ctx *cc)
|
||||
{
|
||||
if (cc->flags & CLIENT_HIDDEN)
|
||||
client_unhide(cc);
|
||||
else
|
||||
client_raise(cc);
|
||||
}
|
||||
|
||||
void
|
||||
client_unhide(struct client_ctx *cc)
|
||||
{
|
||||
XMapRaised(X_Dpy, cc->win);
|
||||
|
||||
@ -631,7 +631,7 @@ client_msg(struct client_ctx *cc, Atom proto, Time ts)
|
||||
}
|
||||
|
||||
void
|
||||
client_send_delete(struct client_ctx *cc)
|
||||
client_close(struct client_ctx *cc)
|
||||
{
|
||||
if (cc->flags & CLIENT_WM_DELETE_WINDOW)
|
||||
client_msg(cc, cwmh[WM_DELETE_WINDOW], CurrentTime);
|
||||
@ -686,7 +686,7 @@ client_cycle(struct screen_ctx *sc, int flags)
|
||||
return;
|
||||
|
||||
prevcc = TAILQ_FIRST(&sc->clientq);
|
||||
oldcc = client_current();
|
||||
oldcc = client_current(sc);
|
||||
if (oldcc == NULL)
|
||||
oldcc = (flags & CWM_CYCLE_REVERSE) ?
|
||||
TAILQ_LAST(&sc->clientq, client_q) :
|
||||
@ -749,7 +749,6 @@ static void
|
||||
client_placecalc(struct client_ctx *cc)
|
||||
{
|
||||
struct screen_ctx *sc = cc->sc;
|
||||
int xslack, yslack;
|
||||
|
||||
if (cc->hint.flags & (USPosition | PPosition)) {
|
||||
if (cc->geom.x >= sc->view.w)
|
||||
@ -760,34 +759,36 @@ client_placecalc(struct client_ctx *cc)
|
||||
cc->geom.x = sc->view.h - cc->bwidth - 1;
|
||||
if (cc->geom.y + cc->geom.h + cc->bwidth <= 0)
|
||||
cc->geom.y = -(cc->geom.h + cc->bwidth - 1);
|
||||
if (cc->flags & CLIENT_IGNORE) {
|
||||
if (((cc->obwidth * 2) + cc->geom.x + cc->geom.w) == sc->view.w)
|
||||
cc->geom.x += cc->obwidth * 2;
|
||||
if (((cc->obwidth * 2) + cc->geom.y + cc->geom.h) == sc->view.h)
|
||||
cc->geom.y += cc->obwidth * 2;
|
||||
}
|
||||
} else {
|
||||
struct geom area;
|
||||
int xmouse, ymouse;
|
||||
struct geom area;
|
||||
int xmouse, ymouse, xslack, yslack;
|
||||
|
||||
xu_ptr_getpos(sc->rootwin, &xmouse, &ymouse);
|
||||
area = screen_area(sc, xmouse, ymouse, CWM_GAP);
|
||||
area.w += area.x;
|
||||
area.h += area.y;
|
||||
xmouse = MAX(xmouse, area.x) - cc->geom.w / 2;
|
||||
ymouse = MAX(ymouse, area.y) - cc->geom.h / 2;
|
||||
|
||||
xmouse = MAX(xmouse, area.x);
|
||||
ymouse = MAX(ymouse, area.y);
|
||||
xmouse = MAX(MAX(xmouse, area.x) - cc->geom.w / 2, area.x);
|
||||
ymouse = MAX(MAX(ymouse, area.y) - cc->geom.h / 2, area.y);
|
||||
|
||||
xslack = area.w - cc->geom.w - cc->bwidth * 2;
|
||||
yslack = area.h - cc->geom.h - cc->bwidth * 2;
|
||||
xslack = area.x + area.w - cc->geom.w - cc->bwidth * 2;
|
||||
yslack = area.y + area.h - cc->geom.h - cc->bwidth * 2;
|
||||
|
||||
if (xslack >= area.x) {
|
||||
cc->geom.x = MAX(MIN(xmouse, xslack), area.x);
|
||||
} else {
|
||||
cc->geom.x = area.x;
|
||||
cc->geom.w = area.w;
|
||||
cc->geom.w = area.x + area.w;
|
||||
}
|
||||
if (yslack >= area.y) {
|
||||
cc->geom.y = MAX(MIN(ymouse, yslack), area.y);
|
||||
} else {
|
||||
cc->geom.y = area.y;
|
||||
cc->geom.h = area.h;
|
||||
cc->geom.h = area.y + area.h;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -919,10 +920,11 @@ client_transient(struct client_ctx *cc)
|
||||
Window trans;
|
||||
|
||||
if (XGetTransientForHint(X_Dpy, cc->win, &trans)) {
|
||||
if ((tc = client_find(trans)) != NULL && tc->gc) {
|
||||
group_movetogroup(cc, tc->gc->num);
|
||||
if (tc->flags & CLIENT_IGNORE)
|
||||
if ((tc = client_find(trans)) != NULL) {
|
||||
if (tc->flags & CLIENT_IGNORE) {
|
||||
cc->flags |= CLIENT_IGNORE;
|
||||
cc->bwidth = tc->bwidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -965,28 +967,33 @@ void
|
||||
client_htile(struct client_ctx *cc)
|
||||
{
|
||||
struct client_ctx *ci;
|
||||
struct group_ctx *gc = cc->gc;
|
||||
struct screen_ctx *sc = cc->sc;
|
||||
struct geom area;
|
||||
int i, n, mh, x, w, h;
|
||||
|
||||
if (!gc)
|
||||
if (!cc->gc)
|
||||
return;
|
||||
i = n = 0;
|
||||
|
||||
TAILQ_FOREACH(ci, &gc->clientq, group_entry) {
|
||||
area = screen_area(sc,
|
||||
cc->geom.x + cc->geom.w / 2,
|
||||
cc->geom.y + cc->geom.h / 2, CWM_GAP);
|
||||
|
||||
TAILQ_FOREACH(ci, &sc->clientq, entry) {
|
||||
if (ci->gc != cc->gc)
|
||||
continue;
|
||||
if (ci->flags & CLIENT_HIDDEN ||
|
||||
ci->flags & CLIENT_IGNORE || (ci == cc))
|
||||
ci->flags & CLIENT_IGNORE || (ci == cc) ||
|
||||
ci->geom.x < area.x ||
|
||||
ci->geom.x > (area.x + area.w) ||
|
||||
ci->geom.y < area.y ||
|
||||
ci->geom.y > (area.y + area.h))
|
||||
continue;
|
||||
n++;
|
||||
}
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
area = screen_area(sc,
|
||||
cc->geom.x + cc->geom.w / 2,
|
||||
cc->geom.y + cc->geom.h / 2, CWM_GAP);
|
||||
|
||||
if (cc->flags & CLIENT_VMAXIMIZED ||
|
||||
cc->geom.h + (cc->bwidth * 2) >= area.h)
|
||||
return;
|
||||
@ -1003,9 +1010,15 @@ client_htile(struct client_ctx *cc)
|
||||
x = area.x;
|
||||
w = area.w / n;
|
||||
h = area.h - mh;
|
||||
TAILQ_FOREACH(ci, &gc->clientq, group_entry) {
|
||||
TAILQ_FOREACH(ci, &sc->clientq, entry) {
|
||||
if (ci->gc != cc->gc)
|
||||
continue;
|
||||
if (ci->flags & CLIENT_HIDDEN ||
|
||||
ci->flags & CLIENT_IGNORE || (ci == cc))
|
||||
ci->flags & CLIENT_IGNORE || (ci == cc) ||
|
||||
ci->geom.x < area.x ||
|
||||
ci->geom.x > (area.x + area.w) ||
|
||||
ci->geom.y < area.y ||
|
||||
ci->geom.y > (area.y + area.h))
|
||||
continue;
|
||||
ci->bwidth = Conf.bwidth;
|
||||
ci->geom.x = x;
|
||||
@ -1025,28 +1038,33 @@ void
|
||||
client_vtile(struct client_ctx *cc)
|
||||
{
|
||||
struct client_ctx *ci;
|
||||
struct group_ctx *gc = cc->gc;
|
||||
struct screen_ctx *sc = cc->sc;
|
||||
struct geom area;
|
||||
int i, n, mw, y, w, h;
|
||||
|
||||
if (!gc)
|
||||
if (!cc->gc)
|
||||
return;
|
||||
i = n = 0;
|
||||
|
||||
TAILQ_FOREACH(ci, &gc->clientq, group_entry) {
|
||||
area = screen_area(sc,
|
||||
cc->geom.x + cc->geom.w / 2,
|
||||
cc->geom.y + cc->geom.h / 2, CWM_GAP);
|
||||
|
||||
TAILQ_FOREACH(ci, &sc->clientq, entry) {
|
||||
if (ci->gc != cc->gc)
|
||||
continue;
|
||||
if (ci->flags & CLIENT_HIDDEN ||
|
||||
ci->flags & CLIENT_IGNORE || (ci == cc))
|
||||
ci->flags & CLIENT_IGNORE || (ci == cc) ||
|
||||
ci->geom.x < area.x ||
|
||||
ci->geom.x > (area.x + area.w) ||
|
||||
ci->geom.y < area.y ||
|
||||
ci->geom.y > (area.y + area.h))
|
||||
continue;
|
||||
n++;
|
||||
}
|
||||
if (n == 0)
|
||||
return;
|
||||
|
||||
area = screen_area(sc,
|
||||
cc->geom.x + cc->geom.w / 2,
|
||||
cc->geom.y + cc->geom.h / 2, CWM_GAP);
|
||||
|
||||
if (cc->flags & CLIENT_HMAXIMIZED ||
|
||||
cc->geom.w + (cc->bwidth * 2) >= area.w)
|
||||
return;
|
||||
@ -1063,9 +1081,15 @@ client_vtile(struct client_ctx *cc)
|
||||
y = area.y;
|
||||
h = area.h / n;
|
||||
w = area.w - mw;
|
||||
TAILQ_FOREACH(ci, &gc->clientq, group_entry) {
|
||||
TAILQ_FOREACH(ci, &sc->clientq, entry) {
|
||||
if (ci->gc != cc->gc)
|
||||
continue;
|
||||
if (ci->flags & CLIENT_HIDDEN ||
|
||||
ci->flags & CLIENT_IGNORE || (ci == cc))
|
||||
ci->flags & CLIENT_IGNORE || (ci == cc) ||
|
||||
ci->geom.x < area.x ||
|
||||
ci->geom.x > (area.x + area.w) ||
|
||||
ci->geom.y < area.y ||
|
||||
ci->geom.y > (area.y + area.h))
|
||||
continue;
|
||||
ci->bwidth = Conf.bwidth;
|
||||
ci->geom.x = area.x + mw;
|
||||
|
67
conf.c
67
conf.c
@ -20,7 +20,6 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "queue.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
@ -37,6 +36,21 @@ static const char *conf_bind_getmask(const char *, unsigned int *);
|
||||
static void conf_unbind_key(struct conf *, struct bind_ctx *);
|
||||
static void conf_unbind_mouse(struct conf *, struct bind_ctx *);
|
||||
|
||||
static const struct {
|
||||
int num;
|
||||
const char *name;
|
||||
} group_binds[] = {
|
||||
{ 0, "nogroup" },
|
||||
{ 1, "one" },
|
||||
{ 2, "two" },
|
||||
{ 3, "three" },
|
||||
{ 4, "four" },
|
||||
{ 5, "five" },
|
||||
{ 6, "six" },
|
||||
{ 7, "seven" },
|
||||
{ 8, "eight" },
|
||||
{ 9, "nine" },
|
||||
};
|
||||
static int cursor_binds[] = {
|
||||
XC_left_ptr, /* CF_NORMAL */
|
||||
XC_fleur, /* CF_MOVE */
|
||||
@ -68,7 +82,8 @@ static const struct {
|
||||
{ FUNC_CC(window-lower, client_lower, 0) },
|
||||
{ FUNC_CC(window-raise, client_raise, 0) },
|
||||
{ FUNC_CC(window-hide, client_hide, 0) },
|
||||
{ FUNC_CC(window-delete, client_delete, 0) },
|
||||
{ FUNC_CC(window-close, client_close, 0) },
|
||||
{ FUNC_CC(window-delete, client_close, 0) },
|
||||
{ FUNC_CC(window-htile, client_htile, 0) },
|
||||
{ FUNC_CC(window-vtile, client_vtile, 0) },
|
||||
{ FUNC_CC(window-stick, client_toggle_sticky, 0) },
|
||||
@ -124,7 +139,7 @@ static const struct {
|
||||
|
||||
{ FUNC_SC(group-cycle, group_cycle, (CWM_CYCLE_FORWARD)) },
|
||||
{ FUNC_SC(group-rcycle, group_cycle, (CWM_CYCLE_REVERSE)) },
|
||||
{ FUNC_SC(group-toggle-all, group_alltoggle, 0) },
|
||||
{ FUNC_SC(group-toggle-all, group_toggle_all, 0) },
|
||||
{ FUNC_SC(group-toggle-1, group_toggle, 1) },
|
||||
{ FUNC_SC(group-toggle-2, group_toggle, 2) },
|
||||
{ FUNC_SC(group-toggle-3, group_toggle, 3) },
|
||||
@ -143,6 +158,15 @@ static const struct {
|
||||
{ FUNC_SC(group-only-7, group_only, 7) },
|
||||
{ FUNC_SC(group-only-8, group_only, 8) },
|
||||
{ FUNC_SC(group-only-9, group_only, 9) },
|
||||
{ FUNC_SC(group-close-1, group_close, 1) },
|
||||
{ FUNC_SC(group-close-2, group_close, 2) },
|
||||
{ FUNC_SC(group-close-3, group_close, 3) },
|
||||
{ FUNC_SC(group-close-4, group_close, 4) },
|
||||
{ FUNC_SC(group-close-5, group_close, 5) },
|
||||
{ FUNC_SC(group-close-6, group_close, 6) },
|
||||
{ FUNC_SC(group-close-7, group_close, 7) },
|
||||
{ FUNC_SC(group-close-8, group_close, 8) },
|
||||
{ FUNC_SC(group-close-9, group_close, 9) },
|
||||
|
||||
{ FUNC_SC(pointer-move-up, ptrmove, (CWM_UP)) },
|
||||
{ FUNC_SC(pointer-move-down, ptrmove, (CWM_DOWN)) },
|
||||
@ -195,7 +219,7 @@ static const struct {
|
||||
{ "M-Tab", "window-cycle" },
|
||||
{ "MS-Tab", "window-rcycle" },
|
||||
{ "CM-n", "window-menu-label" },
|
||||
{ "CM-x", "window-delete" },
|
||||
{ "CM-x", "window-close" },
|
||||
{ "CM-a", "group-toggle-all" },
|
||||
{ "CM-0", "group-toggle-all" },
|
||||
{ "CM-1", "group-toggle-1" },
|
||||
@ -257,7 +281,7 @@ conf_init(struct conf *c)
|
||||
c->bwidth = 1;
|
||||
c->mamount = 1;
|
||||
c->snapdist = 0;
|
||||
c->ngroups = 10;
|
||||
c->ngroups = 0;
|
||||
c->nameqlen = 5;
|
||||
|
||||
TAILQ_INIT(&c->ignoreq);
|
||||
@ -434,16 +458,13 @@ void
|
||||
conf_client(struct client_ctx *cc)
|
||||
{
|
||||
struct winname *wn;
|
||||
int ignore = 0;
|
||||
|
||||
TAILQ_FOREACH(wn, &Conf.ignoreq, entry) {
|
||||
if (strncasecmp(wn->name, cc->name, strlen(wn->name)) == 0) {
|
||||
ignore = 1;
|
||||
cc->flags |= CLIENT_IGNORE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cc->bwidth = (ignore) ? 0 : Conf.bwidth;
|
||||
cc->flags |= (ignore) ? CLIENT_IGNORE : 0;
|
||||
}
|
||||
|
||||
void
|
||||
@ -472,30 +493,28 @@ conf_screen(struct screen_ctx *sc)
|
||||
warnx("XftColorAllocValue: %s", Conf.color[i]);
|
||||
break;
|
||||
}
|
||||
if (XftColorAllocName(X_Dpy, sc->visual, sc->colormap,
|
||||
Conf.color[i], &xc)) {
|
||||
sc->xftcolor[i] = xc;
|
||||
XftColorFree(X_Dpy, sc->visual, sc->colormap, &xc);
|
||||
} else {
|
||||
if (!XftColorAllocName(X_Dpy, sc->visual, sc->colormap,
|
||||
Conf.color[i], &sc->xftcolor[i])) {
|
||||
warnx("XftColorAllocName: %s", Conf.color[i]);
|
||||
XftColorAllocName(X_Dpy, sc->visual, sc->colormap,
|
||||
color_binds[i], &sc->xftcolor[i]);
|
||||
}
|
||||
}
|
||||
|
||||
sc->menu.win = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1,
|
||||
Conf.bwidth,
|
||||
sc->xftcolor[CWM_COLOR_MENU_FG].pixel,
|
||||
sc->xftcolor[CWM_COLOR_MENU_BG].pixel);
|
||||
|
||||
sc->menu.xftdraw = XftDrawCreate(X_Dpy, sc->menu.win,
|
||||
sc->visual, sc->colormap);
|
||||
if (sc->menu.xftdraw == NULL)
|
||||
errx(1, "%s: XftDrawCreate", __func__);
|
||||
|
||||
conf_grab_kbd(sc->rootwin);
|
||||
}
|
||||
|
||||
void
|
||||
conf_group(struct screen_ctx *sc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < nitems(group_binds); i++) {
|
||||
group_init(sc, group_binds[i].num, group_binds[i].name);
|
||||
Conf.ngroups++;
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
conf_bind_getmask(const char *name, unsigned int *mask)
|
||||
{
|
||||
|
15
cwm.1
15
cwm.1
@ -23,7 +23,7 @@
|
||||
.Sh SYNOPSIS
|
||||
.\" For a program: program [-abc] file ...
|
||||
.Nm cwm
|
||||
.Op Fl v
|
||||
.Op Fl nv
|
||||
.Op Fl c Ar file
|
||||
.Op Fl d Ar display
|
||||
.Sh DESCRIPTION
|
||||
@ -48,6 +48,9 @@ however,
|
||||
will continue to process the rest of the configuration file.
|
||||
.It Fl d Ar display
|
||||
Specify the display to use.
|
||||
.It Fl n
|
||||
Configtest mode.
|
||||
Only check the configuration file for validity.
|
||||
.It Fl v
|
||||
Verbose mode.
|
||||
Multiple
|
||||
@ -100,7 +103,7 @@ Cycle through currently visible windows.
|
||||
.It Ic MS-Tab
|
||||
Reverse cycle through currently visible windows.
|
||||
.It Ic CM-x
|
||||
Delete current window.
|
||||
Close current window.
|
||||
.It Ic CM-[n]
|
||||
Toggle visibility of group n, where n is 1-9.
|
||||
.It Ic CM-a
|
||||
@ -216,6 +219,11 @@ Window is currently focused.
|
||||
.It &
|
||||
Window is hidden.
|
||||
.El
|
||||
.Sh APPLICATIONS
|
||||
.Nm
|
||||
manages a list of applications defined with the
|
||||
.Cm command
|
||||
configuration option.
|
||||
.Sh GROUPS
|
||||
.Nm
|
||||
has the ability to group windows together, and use the groups to
|
||||
@ -239,8 +247,7 @@ Selecting an item will warp to that window, unhiding it if necessary.
|
||||
Show list of currently defined groups.
|
||||
Selecting an item will hide/unhide that group.
|
||||
.It Ic M3
|
||||
Show list of applications as defined in
|
||||
.Pa ~/.cwmrc .
|
||||
Show list of applications as defined in the configuration file.
|
||||
Selecting an item will spawn that application.
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
|
8
cwmrc.5
8
cwmrc.5
@ -173,7 +173,7 @@ entry is shown in the application menu.
|
||||
When selected, the defined
|
||||
.Ar path
|
||||
is executed with
|
||||
.Xr execve 2 .
|
||||
.Xr execvp 3 .
|
||||
.Pp
|
||||
The
|
||||
.Ar name
|
||||
@ -288,6 +288,8 @@ menu.
|
||||
Toggle visibility of group n, where n is 1-9.
|
||||
.It group-only-[n]
|
||||
Show only group n, where n is 1-9, hiding other groups.
|
||||
.It group-close-[n]
|
||||
Close all windows in group n, where n is 1-9.
|
||||
.It group-toggle-all
|
||||
Toggle visibility of all groups.
|
||||
.It window-group
|
||||
@ -306,8 +308,8 @@ Reverse cycle through windows.
|
||||
Forward cycle through windows in current group.
|
||||
.It window-rcycle-ingroup
|
||||
Reverse cycle through windows in current group.
|
||||
.It window-delete
|
||||
Delete current window.
|
||||
.It window-close
|
||||
Close current window.
|
||||
.It window-hide
|
||||
Hide current window.
|
||||
.It window-lower
|
||||
|
163
group.c
163
group.c
@ -37,37 +37,30 @@ static struct group_ctx *group_prev(struct group_ctx *);
|
||||
static void group_restack(struct group_ctx *);
|
||||
static void group_setactive(struct group_ctx *);
|
||||
|
||||
const char *num_to_name[] = {
|
||||
"nogroup", "one", "two", "three", "four", "five", "six",
|
||||
"seven", "eight", "nine"
|
||||
};
|
||||
|
||||
void
|
||||
group_assign(struct group_ctx *gc, struct client_ctx *cc)
|
||||
{
|
||||
if (cc->gc != NULL)
|
||||
TAILQ_REMOVE(&cc->gc->clientq, cc, group_entry);
|
||||
|
||||
if ((gc != NULL) && (gc->num == 0))
|
||||
gc = NULL;
|
||||
|
||||
cc->gc = gc;
|
||||
|
||||
if (cc->gc != NULL)
|
||||
TAILQ_INSERT_TAIL(&gc->clientq, cc, group_entry);
|
||||
|
||||
xu_ewmh_net_wm_desktop(cc);
|
||||
}
|
||||
|
||||
void
|
||||
group_hide(struct group_ctx *gc)
|
||||
{
|
||||
struct screen_ctx *sc = gc->sc;
|
||||
struct client_ctx *cc;
|
||||
|
||||
screen_updatestackingorder(gc->sc);
|
||||
|
||||
TAILQ_FOREACH(cc, &gc->clientq, group_entry) {
|
||||
if (!(cc->flags & CLIENT_STICKY))
|
||||
TAILQ_FOREACH(cc, &sc->clientq, entry) {
|
||||
if (cc->gc != gc)
|
||||
continue;
|
||||
if (!(cc->flags & CLIENT_STICKY) &&
|
||||
!(cc->flags & CLIENT_HIDDEN))
|
||||
client_hide(cc);
|
||||
}
|
||||
}
|
||||
@ -75,13 +68,16 @@ group_hide(struct group_ctx *gc)
|
||||
void
|
||||
group_show(struct group_ctx *gc)
|
||||
{
|
||||
struct screen_ctx *sc = gc->sc;
|
||||
struct client_ctx *cc;
|
||||
|
||||
TAILQ_FOREACH(cc, &gc->clientq, group_entry) {
|
||||
if (!(cc->flags & CLIENT_STICKY))
|
||||
client_unhide(cc);
|
||||
TAILQ_FOREACH(cc, &sc->clientq, entry) {
|
||||
if (cc->gc != gc)
|
||||
continue;
|
||||
if (!(cc->flags & CLIENT_STICKY) &&
|
||||
(cc->flags & CLIENT_HIDDEN))
|
||||
client_show(cc);
|
||||
}
|
||||
|
||||
group_restack(gc);
|
||||
group_setactive(gc);
|
||||
}
|
||||
@ -89,19 +85,24 @@ group_show(struct group_ctx *gc)
|
||||
static void
|
||||
group_restack(struct group_ctx *gc)
|
||||
{
|
||||
struct screen_ctx *sc = gc->sc;
|
||||
struct client_ctx *cc;
|
||||
Window *winlist;
|
||||
int i, lastempty = -1;
|
||||
int nwins = 0, highstack = 0;
|
||||
|
||||
TAILQ_FOREACH(cc, &gc->clientq, group_entry) {
|
||||
TAILQ_FOREACH(cc, &sc->clientq, entry) {
|
||||
if (cc->gc != gc)
|
||||
continue;
|
||||
if (cc->stackingorder > highstack)
|
||||
highstack = cc->stackingorder;
|
||||
}
|
||||
winlist = xreallocarray(NULL, (highstack + 1), sizeof(*winlist));
|
||||
|
||||
/* Invert the stacking order for XRestackWindows(). */
|
||||
TAILQ_FOREACH(cc, &gc->clientq, group_entry) {
|
||||
TAILQ_FOREACH(cc, &sc->clientq, entry) {
|
||||
if (cc->gc != gc)
|
||||
continue;
|
||||
winlist[highstack - cc->stackingorder] = cc->win;
|
||||
nwins++;
|
||||
}
|
||||
@ -122,16 +123,14 @@ group_restack(struct group_ctx *gc)
|
||||
}
|
||||
|
||||
void
|
||||
group_init(struct screen_ctx *sc, int num)
|
||||
group_init(struct screen_ctx *sc, int num, const char *name)
|
||||
{
|
||||
struct group_ctx *gc;
|
||||
|
||||
gc = xmalloc(sizeof(*gc));
|
||||
gc->sc = sc;
|
||||
gc->name = xstrdup(num_to_name[num]);
|
||||
gc->name = xstrdup(name);
|
||||
gc->num = num;
|
||||
TAILQ_INIT(&gc->clientq);
|
||||
|
||||
TAILQ_INSERT_TAIL(&sc->groupq, gc, entry);
|
||||
|
||||
if (num == 1)
|
||||
@ -154,19 +153,15 @@ group_movetogroup(struct client_ctx *cc, int idx)
|
||||
struct screen_ctx *sc = cc->sc;
|
||||
struct group_ctx *gc;
|
||||
|
||||
if (idx < 0 || idx >= Conf.ngroups)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(gc, &sc->groupq, entry) {
|
||||
if (gc->num == idx)
|
||||
break;
|
||||
if (gc->num == idx) {
|
||||
if (cc->gc == gc)
|
||||
return;
|
||||
if (gc->num != 0 && group_holds_only_hidden(gc))
|
||||
client_hide(cc);
|
||||
group_assign(gc, cc);
|
||||
}
|
||||
}
|
||||
|
||||
if (cc->gc == gc)
|
||||
return;
|
||||
if (gc->num != 0 && group_holds_only_hidden(gc))
|
||||
client_hide(cc);
|
||||
group_assign(gc, cc);
|
||||
}
|
||||
|
||||
void
|
||||
@ -175,23 +170,25 @@ group_toggle_membership(struct client_ctx *cc)
|
||||
struct screen_ctx *sc = cc->sc;
|
||||
struct group_ctx *gc = sc->group_active;
|
||||
|
||||
if (gc == cc->gc) {
|
||||
if (cc->gc == gc) {
|
||||
group_assign(NULL, cc);
|
||||
cc->flags |= CLIENT_UNGROUP;
|
||||
} else {
|
||||
group_assign(gc, cc);
|
||||
cc->flags |= CLIENT_GROUP;
|
||||
}
|
||||
|
||||
client_draw_border(cc);
|
||||
}
|
||||
|
||||
int
|
||||
group_holds_only_sticky(struct group_ctx *gc)
|
||||
{
|
||||
struct screen_ctx *sc = gc->sc;
|
||||
struct client_ctx *cc;
|
||||
|
||||
TAILQ_FOREACH(cc, &gc->clientq, group_entry) {
|
||||
TAILQ_FOREACH(cc, &sc->clientq, entry) {
|
||||
if (cc->gc != gc)
|
||||
continue;
|
||||
if (!(cc->flags & CLIENT_STICKY))
|
||||
return(0);
|
||||
}
|
||||
@ -201,46 +198,23 @@ group_holds_only_sticky(struct group_ctx *gc)
|
||||
int
|
||||
group_holds_only_hidden(struct group_ctx *gc)
|
||||
{
|
||||
struct screen_ctx *sc = gc->sc;
|
||||
struct client_ctx *cc;
|
||||
|
||||
TAILQ_FOREACH(cc, &gc->clientq, group_entry) {
|
||||
TAILQ_FOREACH(cc, &sc->clientq, entry) {
|
||||
if (cc->gc != gc)
|
||||
continue;
|
||||
if (!(cc->flags & (CLIENT_HIDDEN | CLIENT_STICKY)))
|
||||
return(0);
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
void
|
||||
group_hidetoggle(struct screen_ctx *sc, int idx)
|
||||
{
|
||||
struct group_ctx *gc;
|
||||
|
||||
if (idx < 0 || idx >= Conf.ngroups)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(gc, &sc->groupq, entry) {
|
||||
if (gc->num == idx)
|
||||
break;
|
||||
}
|
||||
|
||||
if (group_holds_only_hidden(gc))
|
||||
group_show(gc);
|
||||
else {
|
||||
group_hide(gc);
|
||||
/* make clients stick to empty group */
|
||||
if (TAILQ_EMPTY(&gc->clientq))
|
||||
group_setactive(gc);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
group_only(struct screen_ctx *sc, int idx)
|
||||
{
|
||||
struct group_ctx *gc;
|
||||
|
||||
if (idx < 0 || idx >= Conf.ngroups)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(gc, &sc->groupq, entry) {
|
||||
if (gc->num == idx)
|
||||
group_show(gc);
|
||||
@ -249,6 +223,52 @@ group_only(struct screen_ctx *sc, int idx)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
group_toggle(struct screen_ctx *sc, int idx)
|
||||
{
|
||||
struct group_ctx *gc;
|
||||
|
||||
TAILQ_FOREACH(gc, &sc->groupq, entry) {
|
||||
if (gc->num == idx) {
|
||||
if (group_holds_only_hidden(gc))
|
||||
group_show(gc);
|
||||
else
|
||||
group_hide(gc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
group_toggle_all(struct screen_ctx *sc)
|
||||
{
|
||||
struct group_ctx *gc;
|
||||
|
||||
TAILQ_FOREACH(gc, &sc->groupq, entry) {
|
||||
if (sc->hideall)
|
||||
group_show(gc);
|
||||
else
|
||||
group_hide(gc);
|
||||
}
|
||||
sc->hideall = !sc->hideall;
|
||||
}
|
||||
|
||||
void
|
||||
group_close(struct screen_ctx *sc, int idx)
|
||||
{
|
||||
struct group_ctx *gc;
|
||||
struct client_ctx *cc;
|
||||
|
||||
TAILQ_FOREACH(gc, &sc->groupq, entry) {
|
||||
if (gc->num == idx) {
|
||||
TAILQ_FOREACH(cc, &sc->clientq, entry) {
|
||||
if (cc->gc != gc)
|
||||
continue;
|
||||
client_close(cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
group_cycle(struct screen_ctx *sc, int flags)
|
||||
{
|
||||
@ -269,7 +289,6 @@ group_cycle(struct screen_ctx *sc, int flags)
|
||||
else if (!group_holds_only_hidden(newgc))
|
||||
group_hide(newgc);
|
||||
}
|
||||
|
||||
if (showgroup == NULL)
|
||||
return;
|
||||
|
||||
@ -301,20 +320,6 @@ group_prev(struct group_ctx *gc)
|
||||
newgc : TAILQ_LAST(&sc->groupq, group_q));
|
||||
}
|
||||
|
||||
void
|
||||
group_alltoggle(struct screen_ctx *sc)
|
||||
{
|
||||
struct group_ctx *gc;
|
||||
|
||||
TAILQ_FOREACH(gc, &sc->groupq, entry) {
|
||||
if (sc->hideall)
|
||||
group_show(gc);
|
||||
else
|
||||
group_hide(gc);
|
||||
}
|
||||
sc->hideall = !sc->hideall;
|
||||
}
|
||||
|
||||
int
|
||||
group_restore(struct client_ctx *cc)
|
||||
{
|
||||
|
54
kbfunc.c
54
kbfunc.c
@ -23,6 +23,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "queue.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <err.h>
|
||||
@ -144,6 +145,7 @@ kbfunc_client_move_kb(void *ctx, struct cargs *cargs)
|
||||
|
||||
client_move(cc);
|
||||
client_ptr_inbound(cc, 1);
|
||||
XSync(X_Dpy, True);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -168,8 +170,8 @@ kbfunc_client_move_mb(void *ctx, struct cargs *cargs)
|
||||
CurrentTime) != GrabSuccess)
|
||||
return;
|
||||
|
||||
menu_windraw(sc, cc->win, "%4d, %-4d", cc->geom.x, cc->geom.y);
|
||||
|
||||
screen_prop_win_create(sc, cc->win);
|
||||
screen_prop_win_draw(sc, "%+5d%+5d", cc->geom.x, cc->geom.y);
|
||||
while (move) {
|
||||
XMaskEvent(X_Dpy, MOUSEMASK, &ev);
|
||||
switch (ev.type) {
|
||||
@ -192,8 +194,8 @@ kbfunc_client_move_mb(void *ctx, struct cargs *cargs)
|
||||
cc->geom.y + cc->geom.h + (cc->bwidth * 2),
|
||||
area.y, area.y + area.h, sc->snapdist);
|
||||
client_move(cc);
|
||||
menu_windraw(sc, cc->win,
|
||||
"%4d, %-4d", cc->geom.x, cc->geom.y);
|
||||
screen_prop_win_draw(sc,
|
||||
"%+5d%+5d", cc->geom.x, cc->geom.y);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
move = 0;
|
||||
@ -202,8 +204,7 @@ kbfunc_client_move_mb(void *ctx, struct cargs *cargs)
|
||||
}
|
||||
if (ltime)
|
||||
client_move(cc);
|
||||
XUnmapWindow(X_Dpy, sc->menu.win);
|
||||
XReparentWindow(X_Dpy, sc->menu.win, sc->rootwin, 0, 0);
|
||||
screen_prop_win_destroy(sc);
|
||||
XUngrabPointer(X_Dpy, CurrentTime);
|
||||
}
|
||||
|
||||
@ -233,6 +234,7 @@ kbfunc_client_resize_kb(void *ctx, struct cargs *cargs)
|
||||
|
||||
client_resize(cc, 1);
|
||||
client_ptr_inbound(cc, 1);
|
||||
XSync(X_Dpy, True);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -257,7 +259,8 @@ kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)
|
||||
CurrentTime) != GrabSuccess)
|
||||
return;
|
||||
|
||||
menu_windraw(sc, cc->win, "%4d x %-4d", cc->dim.w, cc->dim.h);
|
||||
screen_prop_win_create(sc, cc->win);
|
||||
screen_prop_win_draw(sc, "%4d x %-4d", cc->dim.w, cc->dim.h);
|
||||
while (resize) {
|
||||
XMaskEvent(X_Dpy, MOUSEMASK, &ev);
|
||||
switch (ev.type) {
|
||||
@ -271,7 +274,7 @@ kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)
|
||||
cc->geom.h = ev.xmotion.y;
|
||||
client_applysizehints(cc);
|
||||
client_resize(cc, 1);
|
||||
menu_windraw(sc, cc->win,
|
||||
screen_prop_win_draw(sc,
|
||||
"%4d x %-4d", cc->dim.w, cc->dim.h);
|
||||
break;
|
||||
case ButtonRelease:
|
||||
@ -281,8 +284,7 @@ kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)
|
||||
}
|
||||
if (ltime)
|
||||
client_resize(cc, 1);
|
||||
XUnmapWindow(X_Dpy, sc->menu.win);
|
||||
XReparentWindow(X_Dpy, sc->menu.win, sc->rootwin, 0, 0);
|
||||
screen_prop_win_destroy(sc);
|
||||
XUngrabPointer(X_Dpy, CurrentTime);
|
||||
|
||||
/* Make sure the pointer stays within the window. */
|
||||
@ -326,9 +328,9 @@ kbfunc_client_snap(void *ctx, struct cargs *cargs)
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_client_delete(void *ctx, struct cargs *cargs)
|
||||
kbfunc_client_close(void *ctx, struct cargs *cargs)
|
||||
{
|
||||
client_send_delete(ctx);
|
||||
client_close(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
@ -430,12 +432,6 @@ kbfunc_client_movetogroup(void *ctx, struct cargs *cargs)
|
||||
group_movetogroup(ctx, cargs->flag);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_group_toggle(void *ctx, struct cargs *cargs)
|
||||
{
|
||||
group_hidetoggle(ctx, cargs->flag);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_group_only(void *ctx, struct cargs *cargs)
|
||||
{
|
||||
@ -443,15 +439,27 @@ kbfunc_group_only(void *ctx, struct cargs *cargs)
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_group_cycle(void *ctx, struct cargs *cargs)
|
||||
kbfunc_group_toggle(void *ctx, struct cargs *cargs)
|
||||
{
|
||||
group_cycle(ctx, cargs->flag);
|
||||
group_toggle(ctx, cargs->flag);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_group_alltoggle(void *ctx, struct cargs *cargs)
|
||||
kbfunc_group_toggle_all(void *ctx, struct cargs *cargs)
|
||||
{
|
||||
group_alltoggle(ctx);
|
||||
group_toggle_all(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_group_close(void *ctx, struct cargs *cargs)
|
||||
{
|
||||
group_close(ctx, cargs->flag);
|
||||
}
|
||||
|
||||
void
|
||||
kbfunc_group_cycle(void *ctx, struct cargs *cargs)
|
||||
{
|
||||
group_cycle(ctx, cargs->flag);
|
||||
}
|
||||
|
||||
void
|
||||
@ -467,7 +475,7 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs)
|
||||
if (cargs->xev == CWM_XEV_BTN)
|
||||
mflags |= CWM_MENU_LIST;
|
||||
|
||||
old_cc = client_current();
|
||||
old_cc = client_current(sc);
|
||||
|
||||
TAILQ_INIT(&menuq);
|
||||
TAILQ_FOREACH(cc, &sc->clientq, entry) {
|
||||
|
80
menu.c
80
menu.c
@ -37,6 +37,10 @@
|
||||
#define PROMPT_SCHAR "\xc2\xbb"
|
||||
#define PROMPT_ECHAR "\xc2\xab"
|
||||
|
||||
#define MENUMASK (MOUSEMASK | ButtonMotionMask | KeyPressMask | \
|
||||
ExposureMask)
|
||||
#define MENUGRABMASK (MOUSEMASK | ButtonMotionMask | StructureNotifyMask)
|
||||
|
||||
enum ctltype {
|
||||
CTL_NONE = -1,
|
||||
CTL_ERASEONE = 0, CTL_WIPE, CTL_UP, CTL_DOWN, CTL_RETURN,
|
||||
@ -45,6 +49,9 @@ enum ctltype {
|
||||
|
||||
struct menu_ctx {
|
||||
struct screen_ctx *sc;
|
||||
Window win;
|
||||
XftDraw *xftdraw;
|
||||
struct geom geom;
|
||||
char searchstr[MENU_MAXENTRY + 1];
|
||||
char dispstr[MENU_MAXENTRY*2 + 1];
|
||||
char promptstr[MENU_MAXENTRY + 1];
|
||||
@ -55,7 +62,6 @@ struct menu_ctx {
|
||||
int entry;
|
||||
int num;
|
||||
int flags;
|
||||
struct geom geom;
|
||||
void (*match)(struct menu_q *, struct menu_q *, char *);
|
||||
void (*print)(struct menu *, int);
|
||||
};
|
||||
@ -108,27 +114,35 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt,
|
||||
else
|
||||
mc.searchstr[0] = '\0';
|
||||
|
||||
XSelectInput(X_Dpy, sc->menu.win, MENUMASK);
|
||||
XMapRaised(X_Dpy, sc->menu.win);
|
||||
mc.win = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1,
|
||||
Conf.bwidth,
|
||||
sc->xftcolor[CWM_COLOR_MENU_FG].pixel,
|
||||
sc->xftcolor[CWM_COLOR_MENU_BG].pixel);
|
||||
mc.xftdraw = XftDrawCreate(X_Dpy, mc.win,
|
||||
sc->visual, sc->colormap);
|
||||
|
||||
if (XGrabPointer(X_Dpy, sc->menu.win, False, MENUGRABMASK,
|
||||
XSelectInput(X_Dpy, mc.win, MENUMASK);
|
||||
XMapRaised(X_Dpy, mc.win);
|
||||
|
||||
if (XGrabPointer(X_Dpy, mc.win, False, MENUGRABMASK,
|
||||
GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_QUESTION],
|
||||
CurrentTime) != GrabSuccess) {
|
||||
XUnmapWindow(X_Dpy, sc->menu.win);
|
||||
XftDrawDestroy(mc.xftdraw);
|
||||
XDestroyWindow(X_Dpy, mc.win);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
XGetInputFocus(X_Dpy, &focuswin, &focusrevert);
|
||||
XSetInputFocus(X_Dpy, sc->menu.win, RevertToPointerRoot, CurrentTime);
|
||||
XSetInputFocus(X_Dpy, mc.win, RevertToPointerRoot, CurrentTime);
|
||||
|
||||
/* make sure keybindings don't remove keys from the menu stream */
|
||||
XGrabKeyboard(X_Dpy, sc->menu.win, True,
|
||||
XGrabKeyboard(X_Dpy, mc.win, True,
|
||||
GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
|
||||
for (;;) {
|
||||
mc.changed = 0;
|
||||
|
||||
XWindowEvent(X_Dpy, sc->menu.win, MENUMASK, &e);
|
||||
XWindowEvent(X_Dpy, mc.win, MENUMASK, &e);
|
||||
|
||||
switch (e.type) {
|
||||
case KeyPress:
|
||||
@ -159,15 +173,16 @@ out:
|
||||
mi = NULL;
|
||||
}
|
||||
|
||||
XftDrawDestroy(mc.xftdraw);
|
||||
XDestroyWindow(X_Dpy, mc.win);
|
||||
|
||||
XSetInputFocus(X_Dpy, focuswin, focusrevert, CurrentTime);
|
||||
/* restore if user didn't move */
|
||||
xu_ptr_getpos(sc->rootwin, &xcur, &ycur);
|
||||
if (xcur == mc.geom.x && ycur == mc.geom.y)
|
||||
xu_ptr_setpos(sc->rootwin, xsave, ysave);
|
||||
XUngrabPointer(X_Dpy, CurrentTime);
|
||||
|
||||
XMoveResizeWindow(X_Dpy, sc->menu.win, 0, 0, 1, 1);
|
||||
XUnmapWindow(X_Dpy, sc->menu.win);
|
||||
XUngrabPointer(X_Dpy, CurrentTime);
|
||||
XUngrabKeyboard(X_Dpy, CurrentTime);
|
||||
|
||||
return(mi);
|
||||
@ -377,12 +392,12 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
|
||||
if (mc->geom.x != xsave || mc->geom.y != ysave)
|
||||
xu_ptr_setpos(sc->rootwin, mc->geom.x, mc->geom.y);
|
||||
|
||||
XClearWindow(X_Dpy, sc->menu.win);
|
||||
XMoveResizeWindow(X_Dpy, sc->menu.win, mc->geom.x, mc->geom.y,
|
||||
XClearWindow(X_Dpy, mc->win);
|
||||
XMoveResizeWindow(X_Dpy, mc->win, mc->geom.x, mc->geom.y,
|
||||
mc->geom.w, mc->geom.h);
|
||||
|
||||
n = 1;
|
||||
XftDrawStringUtf8(sc->menu.xftdraw,
|
||||
XftDrawStringUtf8(mc->xftdraw,
|
||||
&sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont,
|
||||
0, sc->xftfont->ascent,
|
||||
(const FcChar8*)mc->dispstr, strlen(mc->dispstr));
|
||||
@ -394,7 +409,7 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
|
||||
if (mc->geom.y + y > area.h)
|
||||
break;
|
||||
|
||||
XftDrawStringUtf8(sc->menu.xftdraw,
|
||||
XftDrawStringUtf8(mc->xftdraw,
|
||||
&sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont,
|
||||
0, y,
|
||||
(const FcChar8*)mi->print, strlen(mi->print));
|
||||
@ -419,11 +434,11 @@ menu_draw_entry(struct menu_ctx *mc, struct menu_q *resultq,
|
||||
return;
|
||||
|
||||
color = (active) ? CWM_COLOR_MENU_FG : CWM_COLOR_MENU_BG;
|
||||
XftDrawRect(sc->menu.xftdraw, &sc->xftcolor[color], 0,
|
||||
XftDrawRect(mc->xftdraw, &sc->xftcolor[color], 0,
|
||||
(sc->xftfont->height + 1) * entry, mc->geom.w,
|
||||
(sc->xftfont->height + 1) + sc->xftfont->descent);
|
||||
color = (active) ? CWM_COLOR_MENU_FONT_SEL : CWM_COLOR_MENU_FONT;
|
||||
XftDrawStringUtf8(sc->menu.xftdraw,
|
||||
XftDrawStringUtf8(mc->xftdraw,
|
||||
&sc->xftcolor[color], sc->xftfont,
|
||||
0, (sc->xftfont->height + 1) * entry + sc->xftfont->ascent + 1,
|
||||
(const FcChar8*)mi->print, strlen(mi->print));
|
||||
@ -603,34 +618,3 @@ menuq_clear(struct menu_q *mq)
|
||||
free(mi);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
menu_windraw(struct screen_ctx *sc, Window win, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
char *text;
|
||||
XGlyphInfo extents;
|
||||
|
||||
va_start(ap, fmt);
|
||||
i = vasprintf(&text, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (i < 0 || text == NULL)
|
||||
err(1, "vasprintf");
|
||||
|
||||
XftTextExtentsUtf8(X_Dpy, sc->xftfont, (const FcChar8*)text,
|
||||
strlen(text), &extents);
|
||||
|
||||
XReparentWindow(X_Dpy, sc->menu.win, win, 0, 0);
|
||||
XMoveResizeWindow(X_Dpy, sc->menu.win, 0, 0,
|
||||
extents.xOff, sc->xftfont->height);
|
||||
XMapWindow(X_Dpy, sc->menu.win);
|
||||
XClearWindow(X_Dpy, sc->menu.win);
|
||||
|
||||
XftDrawStringUtf8(sc->menu.xftdraw, &sc->xftcolor[CWM_COLOR_MENU_FONT],
|
||||
sc->xftfont, 0, sc->xftfont->ascent + 1,
|
||||
(const FcChar8*)text, strlen(text));
|
||||
|
||||
free(text);
|
||||
}
|
||||
|
3
parse.y
3
parse.y
@ -469,7 +469,8 @@ yylex(void)
|
||||
} else if (c == '\\') {
|
||||
if ((next = lgetc(quotec)) == EOF)
|
||||
return (0);
|
||||
if (next == quotec || c == ' ' || c == '\t')
|
||||
if (next == quotec || next == ' ' ||
|
||||
next == '\t')
|
||||
c = next;
|
||||
else if (next == '\n') {
|
||||
file->lineno++;
|
||||
|
56
screen.c
56
screen.c
@ -24,6 +24,7 @@
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -40,7 +41,6 @@ screen_init(int which)
|
||||
Window *wins, w0, w1, active = None;
|
||||
XSetWindowAttributes rootattr;
|
||||
unsigned int nwins, w;
|
||||
int i;
|
||||
|
||||
sc = xmalloc(sizeof(*sc));
|
||||
|
||||
@ -60,14 +60,11 @@ screen_init(int which)
|
||||
xu_ewmh_net_supported(sc);
|
||||
xu_ewmh_net_supported_wm_check(sc);
|
||||
|
||||
conf_group(sc);
|
||||
screen_update_geometry(sc);
|
||||
|
||||
for (i = 0; i < Conf.ngroups; i++)
|
||||
group_init(sc, i);
|
||||
|
||||
xu_ewmh_net_desktop_names(sc);
|
||||
xu_ewmh_net_wm_desktop_viewport(sc);
|
||||
xu_ewmh_net_wm_number_of_desktops(sc);
|
||||
xu_ewmh_net_number_of_desktops(sc);
|
||||
xu_ewmh_net_showing_desktop(sc);
|
||||
xu_ewmh_net_virtual_roots(sc);
|
||||
active = xu_ewmh_get_net_active_window(sc);
|
||||
@ -106,7 +103,7 @@ screen_find(Window win)
|
||||
if (sc->rootwin == win)
|
||||
return(sc);
|
||||
}
|
||||
warnx("%s: failure win 0x%lu\n", __func__, win);
|
||||
warnx("%s: failure win 0x%lx", __func__, win);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
@ -217,6 +214,7 @@ screen_update_geometry(struct screen_ctx *sc)
|
||||
}
|
||||
|
||||
xu_ewmh_net_desktop_geometry(sc);
|
||||
xu_ewmh_net_desktop_viewport(sc);
|
||||
xu_ewmh_net_workarea(sc);
|
||||
}
|
||||
|
||||
@ -253,3 +251,47 @@ screen_assert_clients_within(struct screen_ctx *sc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
screen_prop_win_create(struct screen_ctx *sc, Window win)
|
||||
{
|
||||
sc->prop.win = XCreateSimpleWindow(X_Dpy, win, 0, 0, 1, 1, 0,
|
||||
sc->xftcolor[CWM_COLOR_MENU_BG].pixel,
|
||||
sc->xftcolor[CWM_COLOR_MENU_BG].pixel);
|
||||
sc->prop.xftdraw = XftDrawCreate(X_Dpy, sc->prop.win,
|
||||
sc->visual, sc->colormap);
|
||||
|
||||
XMapWindow(X_Dpy, sc->prop.win);
|
||||
}
|
||||
|
||||
void
|
||||
screen_prop_win_destroy(struct screen_ctx *sc)
|
||||
{
|
||||
XftDrawDestroy(sc->prop.xftdraw);
|
||||
XDestroyWindow(X_Dpy, sc->prop.win);
|
||||
}
|
||||
|
||||
void
|
||||
screen_prop_win_draw(struct screen_ctx *sc, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
char *text;
|
||||
XGlyphInfo extents;
|
||||
|
||||
va_start(ap, fmt);
|
||||
i = vasprintf(&text, fmt, ap);
|
||||
va_end(ap);
|
||||
if (i < 0 || text == NULL)
|
||||
err(1, "vasprintf");
|
||||
|
||||
XftTextExtentsUtf8(X_Dpy, sc->xftfont, (const FcChar8*)text,
|
||||
strlen(text), &extents);
|
||||
XResizeWindow(X_Dpy, sc->prop.win, extents.xOff, sc->xftfont->height);
|
||||
XClearWindow(X_Dpy, sc->prop.win);
|
||||
XftDrawStringUtf8(sc->prop.xftdraw, &sc->xftcolor[CWM_COLOR_MENU_FONT],
|
||||
sc->xftfont, 0, sc->xftfont->ascent + 1,
|
||||
(const FcChar8*)text, strlen(text));
|
||||
|
||||
free(text);
|
||||
}
|
||||
|
2
util.c
2
util.c
@ -24,6 +24,7 @@
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -134,5 +135,6 @@ log_debug(int level, const char *func, const char *msg, ...)
|
||||
va_start(ap, msg);
|
||||
xasprintf(&fmt, "debug%d: %s: %s", level, func, msg);
|
||||
log_msg(fmt, ap);
|
||||
free(fmt);
|
||||
va_end(ap);
|
||||
}
|
||||
|
97
xevents.c
97
xevents.c
@ -75,11 +75,15 @@ static void
|
||||
xev_handle_maprequest(XEvent *ee)
|
||||
{
|
||||
XMapRequestEvent *e = &ee->xmaprequest;
|
||||
struct client_ctx *cc = NULL, *old_cc;
|
||||
struct screen_ctx *sc;
|
||||
struct client_ctx *cc, *old_cc;
|
||||
|
||||
LOG_DEBUG3("window: 0x%lx", e->window);
|
||||
LOG_DEBUG3("parent: 0x%lx window: 0x%lx", e->parent, e->window);
|
||||
|
||||
if ((old_cc = client_current()) != NULL)
|
||||
if ((sc = screen_find(e->parent)) == NULL)
|
||||
return;
|
||||
|
||||
if ((old_cc = client_current(sc)) != NULL)
|
||||
client_ptrsave(old_cc);
|
||||
|
||||
if ((cc = client_find(e->window)) == NULL)
|
||||
@ -102,7 +106,7 @@ xev_handle_unmapnotify(XEvent *ee)
|
||||
client_set_wm_state(cc, WithdrawnState);
|
||||
} else {
|
||||
if (!(cc->flags & CLIENT_HIDDEN))
|
||||
client_delete(cc);
|
||||
client_remove(cc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -116,7 +120,7 @@ xev_handle_destroynotify(XEvent *ee)
|
||||
LOG_DEBUG3("window: 0x%lx", e->window);
|
||||
|
||||
if ((cc = client_find(e->window)) != NULL)
|
||||
client_delete(cc);
|
||||
client_remove(cc);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -198,17 +202,19 @@ xev_handle_propertynotify(XEvent *ee)
|
||||
break;
|
||||
case XA_WM_TRANSIENT_FOR:
|
||||
client_transient(cc);
|
||||
client_draw_border(cc);
|
||||
if (cc->gc)
|
||||
group_movetogroup(cc, cc->gc->num);
|
||||
break;
|
||||
default:
|
||||
/* do nothing */
|
||||
if (e->atom == ewmh[_NET_WM_NAME])
|
||||
client_setname(cc);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
TAILQ_FOREACH(sc, &Screenq, entry) {
|
||||
if (sc->rootwin == e->window) {
|
||||
if (e->atom == ewmh[_NET_DESKTOP_NAMES])
|
||||
xu_ewmh_net_desktop_names(sc);
|
||||
}
|
||||
if (e->atom == ewmh[_NET_DESKTOP_NAMES]) {
|
||||
if ((sc = screen_find(e->window)) != NULL)
|
||||
xu_ewmh_net_desktop_names(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -235,7 +241,11 @@ xev_handle_buttonpress(XEvent *ee)
|
||||
struct screen_ctx *sc;
|
||||
struct bind_ctx *mb;
|
||||
|
||||
LOG_DEBUG3("window: 0x%lx", e->window);
|
||||
LOG_DEBUG3("root: 0x%lx window: 0x%lx subwindow: 0x%lx",
|
||||
e->root, e->window, e->subwindow);
|
||||
|
||||
if ((sc = screen_find(e->root)) == NULL)
|
||||
return;
|
||||
|
||||
e->state &= ~IGNOREMODMASK;
|
||||
|
||||
@ -243,22 +253,17 @@ xev_handle_buttonpress(XEvent *ee)
|
||||
if (e->button == mb->press.button && e->state == mb->modmask)
|
||||
break;
|
||||
}
|
||||
|
||||
if (mb == NULL)
|
||||
return;
|
||||
mb->cargs->xev = CWM_XEV_BTN;
|
||||
switch (mb->context) {
|
||||
case CWM_CONTEXT_CC:
|
||||
if (((cc = client_find(e->window)) == NULL) &&
|
||||
(cc = client_current()) == NULL)
|
||||
((cc = client_current(sc)) == NULL))
|
||||
return;
|
||||
(*mb->callback)(cc, mb->cargs);
|
||||
break;
|
||||
case CWM_CONTEXT_SC:
|
||||
if (e->window != e->root)
|
||||
return;
|
||||
if ((sc = screen_find(e->window)) == NULL)
|
||||
return;
|
||||
(*mb->callback)(sc, mb->cargs);
|
||||
break;
|
||||
case CWM_CONTEXT_NONE:
|
||||
@ -273,7 +278,8 @@ xev_handle_buttonrelease(XEvent *ee)
|
||||
XButtonEvent *e = &ee->xbutton;
|
||||
struct client_ctx *cc;
|
||||
|
||||
LOG_DEBUG3("window: 0x%lx", ee->xbutton.window);
|
||||
LOG_DEBUG3("root: 0x%lx window: 0x%lx subwindow: 0x%lx",
|
||||
e->root, e->window, e->subwindow);
|
||||
|
||||
if ((cc = client_find(e->window)) != NULL) {
|
||||
if (cc->flags & (CLIENT_ACTIVE | CLIENT_HIGHLIGHT)) {
|
||||
@ -293,7 +299,11 @@ xev_handle_keypress(XEvent *ee)
|
||||
KeySym keysym, skeysym;
|
||||
unsigned int modshift;
|
||||
|
||||
LOG_DEBUG3("window: 0x%lx", e->window);
|
||||
LOG_DEBUG3("root: 0x%lx window: 0x%lx subwindow: 0x%lx",
|
||||
e->root, e->window, e->subwindow);
|
||||
|
||||
if ((sc = screen_find(e->root)) == NULL)
|
||||
return;
|
||||
|
||||
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
|
||||
skeysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 1);
|
||||
@ -312,20 +322,17 @@ xev_handle_keypress(XEvent *ee)
|
||||
if (kb->press.keysym == ((modshift == 0) ? keysym : skeysym))
|
||||
break;
|
||||
}
|
||||
|
||||
if (kb == NULL)
|
||||
return;
|
||||
kb->cargs->xev = CWM_XEV_KEY;
|
||||
switch (kb->context) {
|
||||
case CWM_CONTEXT_CC:
|
||||
if (((cc = client_find(e->window)) == NULL) &&
|
||||
(cc = client_current()) == NULL)
|
||||
if (((cc = client_find(e->subwindow)) == NULL) &&
|
||||
((cc = client_current(sc)) == NULL))
|
||||
return;
|
||||
(*kb->callback)(cc, kb->cargs);
|
||||
break;
|
||||
case CWM_CONTEXT_SC:
|
||||
if ((sc = screen_find(e->window)) == NULL)
|
||||
return;
|
||||
(*kb->callback)(sc, kb->cargs);
|
||||
break;
|
||||
case CWM_CONTEXT_NONE:
|
||||
@ -346,7 +353,8 @@ xev_handle_keyrelease(XEvent *ee)
|
||||
KeySym keysym;
|
||||
unsigned int i;
|
||||
|
||||
LOG_DEBUG3("window: 0x%lx", e->window);
|
||||
LOG_DEBUG3("root: 0x%lx window: 0x%lx subwindow: 0x%lx",
|
||||
e->root, e->window, e->subwindow);
|
||||
|
||||
if ((sc = screen_find(e->root)) == NULL)
|
||||
return;
|
||||
@ -354,7 +362,7 @@ xev_handle_keyrelease(XEvent *ee)
|
||||
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
|
||||
for (i = 0; i < nitems(modkeys); i++) {
|
||||
if (keysym == modkeys[i]) {
|
||||
if ((cc = client_current()) != NULL) {
|
||||
if ((cc = client_current(sc)) != NULL) {
|
||||
if (sc->cycling) {
|
||||
sc->cycling = 0;
|
||||
client_mtf(cc);
|
||||
@ -386,11 +394,11 @@ xev_handle_clientmessage(XEvent *ee)
|
||||
}
|
||||
} else if (e->message_type == ewmh[_NET_CLOSE_WINDOW]) {
|
||||
if ((cc = client_find(e->window)) != NULL) {
|
||||
client_send_delete(cc);
|
||||
client_close(cc);
|
||||
}
|
||||
} else if (e->message_type == ewmh[_NET_ACTIVE_WINDOW]) {
|
||||
if ((cc = client_find(e->window)) != NULL) {
|
||||
if ((old_cc = client_current()) != NULL)
|
||||
if ((old_cc = client_current(NULL)) != NULL)
|
||||
client_ptrsave(old_cc);
|
||||
client_show(cc);
|
||||
client_ptrwarp(cc);
|
||||
@ -405,7 +413,9 @@ xev_handle_clientmessage(XEvent *ee)
|
||||
if (e->data.l[0] == (unsigned long)-1)
|
||||
group_movetogroup(cc, 0);
|
||||
else
|
||||
group_movetogroup(cc, e->data.l[0]);
|
||||
if (e->data.l[0] >= 0 &&
|
||||
e->data.l[0] < Conf.ngroups)
|
||||
group_movetogroup(cc, e->data.l[0]);
|
||||
}
|
||||
} else if (e->message_type == ewmh[_NET_WM_STATE]) {
|
||||
if ((cc = client_find(e->window)) != NULL) {
|
||||
@ -414,7 +424,9 @@ xev_handle_clientmessage(XEvent *ee)
|
||||
}
|
||||
} else if (e->message_type == ewmh[_NET_CURRENT_DESKTOP]) {
|
||||
if ((sc = screen_find(e->window)) != NULL) {
|
||||
group_only(sc, e->data.l[0]);
|
||||
if (e->data.l[0] >= 0 &&
|
||||
e->data.l[0] < Conf.ngroups)
|
||||
group_only(sc, e->data.l[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -422,20 +434,17 @@ xev_handle_clientmessage(XEvent *ee)
|
||||
static void
|
||||
xev_handle_randr(XEvent *ee)
|
||||
{
|
||||
XRRScreenChangeNotifyEvent *rev = (XRRScreenChangeNotifyEvent *)ee;
|
||||
XRRScreenChangeNotifyEvent *e = (XRRScreenChangeNotifyEvent *)ee;
|
||||
struct screen_ctx *sc;
|
||||
int i;
|
||||
|
||||
LOG_DEBUG3("new size: %d/%d", rev->width, rev->height);
|
||||
LOG_DEBUG3("size: %d/%d", e->width, e->height);
|
||||
|
||||
i = XRRRootToScreen(X_Dpy, rev->root);
|
||||
TAILQ_FOREACH(sc, &Screenq, entry) {
|
||||
if (sc->which == i) {
|
||||
XRRUpdateConfiguration(ee);
|
||||
screen_update_geometry(sc);
|
||||
screen_assert_clients_within(sc);
|
||||
}
|
||||
}
|
||||
if ((sc = screen_find(e->root)) == NULL)
|
||||
return;
|
||||
|
||||
XRRUpdateConfiguration(ee);
|
||||
screen_update_geometry(sc);
|
||||
screen_assert_clients_within(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -476,9 +485,9 @@ xev_process(void)
|
||||
|
||||
while (XPending(X_Dpy)) {
|
||||
XNextEvent(X_Dpy, &e);
|
||||
if (e.type - Conf.xrandr_event_base == RRScreenChangeNotify)
|
||||
if ((e.type - Conf.xrandr_event_base) == RRScreenChangeNotify)
|
||||
xev_handle_randr(&e);
|
||||
else if (e.type < LASTEvent && xev_handlers[e.type] != NULL)
|
||||
else if ((e.type < LASTEvent) && (xev_handlers[e.type] != NULL))
|
||||
(*xev_handlers[e.type])(&e);
|
||||
}
|
||||
}
|
||||
|
22
xutil.c
22
xutil.c
@ -128,6 +128,16 @@ xu_ewmh_net_desktop_geometry(struct screen_ctx *sc)
|
||||
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)geom , 2);
|
||||
}
|
||||
|
||||
void
|
||||
xu_ewmh_net_desktop_viewport(struct screen_ctx *sc)
|
||||
{
|
||||
long viewports[2] = {0, 0};
|
||||
|
||||
/* We don't support large desktops, so this is (0, 0). */
|
||||
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_VIEWPORT],
|
||||
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)viewports, 2);
|
||||
}
|
||||
|
||||
void
|
||||
xu_ewmh_net_workarea(struct screen_ctx *sc)
|
||||
{
|
||||
@ -212,17 +222,7 @@ xu_ewmh_get_net_active_window(struct screen_ctx *sc)
|
||||
}
|
||||
|
||||
void
|
||||
xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *sc)
|
||||
{
|
||||
long viewports[2] = {0, 0};
|
||||
|
||||
/* We don't support large desktops, so this is (0, 0). */
|
||||
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_VIEWPORT],
|
||||
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)viewports, 2);
|
||||
}
|
||||
|
||||
void
|
||||
xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *sc)
|
||||
xu_ewmh_net_number_of_desktops(struct screen_ctx *sc)
|
||||
{
|
||||
long ndesks = Conf.ngroups;
|
||||
|
||||
|
Reference in New Issue
Block a user