cvsimport

* refs/heads/master: (21 commits)
  Lost fix from r1.112; add comment.
  Mechanical change: group->gc
  Add consistent checks against NULL.
  Move client cycle grab/ungrab into a more relevant place; while here, update comments about why we need to grab/ungrab the keyboard.
  Re-add lost chunk in group_cycle from r1.113.
  Further simplify _NET_WM_DESKTOP handling using new group_assign().
  oops; remove left over debug print
  Allowing sending a valid 'nogroup' (0) group_ctx to group_assign() (since we init all groups), though assigning the client's group to NULL for 'sticky'; use this simplification in a few places (others to follow).
  Split out sticky mode checks and the restoring of a client's group and _NET_WM_DESKTOP from the config-based auto-grouping; no (intentional) behavior changes.  Needed for further work in cleaning up this area.
  Implement _NET_CLIENT_LIST_STACKING (from Thomas Admin), but bottom-to-top order, as per spec (notified Thomas as well).
  Don't allow freeze operations on fullscreen (consistent with what fullscreen does).
  Sort _NET_WM_STATE Atoms like the spec.
  Move CLIENT_STICKY logic from client hide/unhide to group hide/unhide; rationale being that clients should be able to hide/unhide independently of group switching.
  Add Xkb modifier to ignore mask; from Alexander Polakov.
  Fix whitespace.
  Add client freeze extension to _NET_WM_STATE Atom, allowing flag to persist. As usual with new Atoms, requires X restart.
  _NET_WM_STATE_STICKY implies only sticky at the group/desktop level, not position and size; based on discussion with a few.
  Instead of special casing the 'term' and 'lock' commands, go back to keeping them hidden; showing them has apparently caused confusion/angst.
  Leave command list order from .cwmrc alone; remove sort.
  Bring group and client cycle closer together.
  ...
This commit is contained in:
okan 2015-08-28 12:07:28 +00:00
commit 3f0b6cf4ea
11 changed files with 254 additions and 184 deletions

View File

@ -64,12 +64,12 @@ size_t strlcpy(char *, const char *, size_t);
#define CONFFILE ".cwmrc"
#define WMNAME "CWM"
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define MENUMASK (MOUSEMASK|ButtonMotionMask|ExposureMask)
#define MENUGRABMASK (MOUSEMASK|ButtonMotionMask|StructureNotifyMask)
#define KEYMASK (KeyPressMask|ExposureMask)
#define IGNOREMODMASK (LockMask|Mod2Mask)
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
#define MENUMASK (MOUSEMASK | ButtonMotionMask | ExposureMask)
#define MENUGRABMASK (MOUSEMASK | ButtonMotionMask | StructureNotifyMask)
#define KEYMASK (KeyPressMask | ExposureMask)
#define IGNOREMODMASK (LockMask | Mod2Mask | 0x2000)
/* kb movement */
#define CWM_MOVE 0x0001
@ -168,6 +168,7 @@ 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;
unsigned int bwidth; /* border width */
@ -219,7 +220,6 @@ struct client_ctx {
char *name;
char *label;
char *matchname;
struct group_ctx *group;
XClassHint ch;
XWMHints *wmh;
};
@ -373,6 +373,7 @@ enum {
_NET_SUPPORTING_WM_CHECK,
_NET_ACTIVE_WINDOW,
_NET_CLIENT_LIST,
_NET_CLIENT_LIST_STACKING,
_NET_NUMBER_OF_DESKTOPS,
_NET_CURRENT_DESKTOP,
_NET_DESKTOP_VIEWPORT,
@ -385,13 +386,14 @@ enum {
_NET_WM_DESKTOP,
_NET_CLOSE_WINDOW,
_NET_WM_STATE,
#define _NET_WM_STATES_NITEMS 6
#define _NET_WM_STATES_NITEMS 7
_NET_WM_STATE_STICKY,
_NET_WM_STATE_MAXIMIZED_VERT,
_NET_WM_STATE_MAXIMIZED_HORZ,
_NET_WM_STATE_HIDDEN,
_NET_WM_STATE_FULLSCREEN,
_NET_WM_STATE_DEMANDS_ATTENTION,
_CWM_WM_STATE_FREEZE,
EWMH_NITEMS
};
enum {
@ -445,7 +447,8 @@ void client_warp(struct client_ctx *);
void client_wm_hints(struct client_ctx *);
void group_alltoggle(struct screen_ctx *);
void group_autogroup(struct client_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);
@ -454,6 +457,7 @@ int group_holds_only_sticky(struct group_ctx *);
void group_init(struct screen_ctx *, int);
void group_movetogroup(struct client_ctx *, int);
void group_only(struct screen_ctx *, int);
int group_restore(struct client_ctx *);
void group_show(struct group_ctx *);
void group_toggle_membership_enter(struct client_ctx *);
void group_toggle_membership_leave(struct client_ctx *);
@ -582,6 +586,7 @@ void xu_ewmh_net_supported_wm_check(struct screen_ctx *);
void xu_ewmh_net_desktop_geometry(struct screen_ctx *);
void xu_ewmh_net_workarea(struct screen_ctx *);
void xu_ewmh_net_client_list(struct screen_ctx *);
void xu_ewmh_net_client_list_stacking(struct screen_ctx *);
void xu_ewmh_net_active_window(struct screen_ctx *, Window);
void xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *);
void xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *);

View File

@ -112,6 +112,7 @@ client_init(Window win, struct screen_ctx *sc)
TAILQ_INSERT_TAIL(&sc->clientq, cc, entry);
xu_ewmh_net_client_list(sc);
xu_ewmh_net_client_list_stacking(sc);
xu_ewmh_restore_net_wm_state(cc);
if (client_get_wm_state(cc) == IconicState)
@ -119,9 +120,17 @@ client_init(Window win, struct screen_ctx *sc)
else
client_unhide(cc);
if (mapped)
group_autogroup(cc);
if (mapped) {
if (group_restore(cc))
goto out;
if (group_autogroup(cc))
goto out;
if (Conf.flags & CONF_STICKY_GROUPS)
group_assign(sc->group_active, cc);
else
group_assign(NULL, cc);
}
out:
XSync(X_Dpy, False);
XUngrabServer(X_Dpy);
@ -152,9 +161,10 @@ client_delete(struct client_ctx *cc)
TAILQ_REMOVE(&sc->clientq, cc, entry);
xu_ewmh_net_client_list(sc);
xu_ewmh_net_client_list_stacking(sc);
if (cc->group != NULL)
TAILQ_REMOVE(&cc->group->clientq, cc, group_entry);
if (cc->gc != NULL)
TAILQ_REMOVE(&cc->gc->clientq, cc, group_entry);
if (cc == client_current())
client_none(sc);
@ -194,7 +204,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())) {
if ((oldcc = client_current()) != NULL) {
oldcc->flags &= ~CLIENT_ACTIVE;
client_draw_border(oldcc);
}
@ -233,10 +243,15 @@ client_current(void)
void
client_toggle_freeze(struct client_ctx *cc)
{
if (cc->flags & CLIENT_FULLSCREEN)
return;
if (cc->flags & CLIENT_FREEZE)
cc->flags &= ~CLIENT_FREEZE;
else
cc->flags |= CLIENT_FREEZE;
xu_ewmh_set_net_wm_state(cc);
}
void
@ -299,7 +314,7 @@ client_toggle_maximize(struct client_ctx *cc)
struct screen_ctx *sc = cc->sc;
struct geom area;
if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY))
if (cc->flags & CLIENT_FREEZE)
return;
if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_MAXIMIZED) {
@ -344,7 +359,7 @@ client_toggle_vmaximize(struct client_ctx *cc)
struct screen_ctx *sc = cc->sc;
struct geom area;
if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY))
if (cc->flags & CLIENT_FREEZE)
return;
if (cc->flags & CLIENT_VMAXIMIZED) {
@ -376,7 +391,7 @@ client_toggle_hmaximize(struct client_ctx *cc)
struct screen_ctx *sc = cc->sc;
struct geom area;
if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY))
if (cc->flags & CLIENT_FREEZE)
return;
if (cc->flags & CLIENT_HMAXIMIZED) {
@ -491,9 +506,6 @@ client_ptrsave(struct client_ctx *cc)
void
client_hide(struct client_ctx *cc)
{
if (cc->flags & CLIENT_STICKY)
return;
XUnmapWindow(X_Dpy, cc->win);
cc->flags &= ~CLIENT_ACTIVE;
@ -507,9 +519,6 @@ client_hide(struct client_ctx *cc)
void
client_unhide(struct client_ctx *cc)
{
if (cc->flags & CLIENT_STICKY)
return;
XMapRaised(X_Dpy, cc->win);
cc->flags &= ~CLIENT_HIDDEN;
@ -647,29 +656,33 @@ match:
void
client_cycle(struct screen_ctx *sc, int flags)
{
struct client_ctx *oldcc, *newcc;
struct client_ctx *newcc, *oldcc;
int again = 1;
/* For X apps that ignore events. */
XGrabKeyboard(X_Dpy, sc->rootwin, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
if (TAILQ_EMPTY(&sc->clientq))
return;
oldcc = client_current();
if (oldcc == NULL)
oldcc = ((flags & CWM_RCYCLE) ?
oldcc = (flags & CWM_RCYCLE) ?
TAILQ_LAST(&sc->clientq, client_ctx_q) :
TAILQ_FIRST(&sc->clientq));
TAILQ_FIRST(&sc->clientq);
newcc = oldcc;
while (again) {
again = 0;
newcc = ((flags & CWM_RCYCLE) ? client_prev(newcc) :
client_next(newcc));
newcc = (flags & CWM_RCYCLE) ? client_prev(newcc) :
client_next(newcc);
/* Only cycle visible and non-ignored windows. */
if ((newcc->flags & (CLIENT_HIDDEN|CLIENT_IGNORE))
if ((newcc->flags & (CLIENT_HIDDEN | CLIENT_IGNORE))
|| ((flags & CWM_INGROUP) &&
(newcc->group != oldcc->group)))
(newcc->gc != oldcc->gc)))
again = 1;
/* Is oldcc the only non-hidden window? */
@ -694,9 +707,10 @@ client_cycle_leave(struct screen_ctx *sc)
sc->cycling = 0;
if ((cc = client_current())) {
if ((cc = client_current()) != NULL) {
client_mtf(cc);
group_toggle_membership_leave(cc);
cc->flags &= ~CLIENT_HIGHLIGHT;
client_draw_border(cc);
XUngrabKeyboard(X_Dpy, CurrentTime);
}
}
@ -705,20 +719,20 @@ static struct client_ctx *
client_next(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct client_ctx *ccc;
struct client_ctx *newcc;
return(((ccc = TAILQ_NEXT(cc, entry)) != NULL) ?
ccc : TAILQ_FIRST(&sc->clientq));
return(((newcc = TAILQ_NEXT(cc, entry)) != NULL) ?
newcc : TAILQ_FIRST(&sc->clientq));
}
static struct client_ctx *
client_prev(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct client_ctx *ccc;
struct client_ctx *newcc;
return(((ccc = TAILQ_PREV(cc, client_ctx_q, entry)) != NULL) ?
ccc : TAILQ_LAST(&sc->clientq, client_ctx_q));
return(((newcc = TAILQ_PREV(cc, client_ctx_q, entry)) != NULL) ?
newcc : TAILQ_LAST(&sc->clientq, client_ctx_q));
}
static void
@ -727,7 +741,7 @@ client_placecalc(struct client_ctx *cc)
struct screen_ctx *sc = cc->sc;
int xslack, yslack;
if (cc->hint.flags & (USPosition|PPosition)) {
if (cc->hint.flags & (USPosition | PPosition)) {
/*
* Ignore XINERAMA screens, just make sure it's somewhere
* in the virtual desktop. else it stops people putting xterms
@ -901,8 +915,8 @@ client_transient(struct client_ctx *cc)
Window trans;
if (XGetTransientForHint(X_Dpy, cc->win, &trans)) {
if ((tc = client_find(trans)) && tc->group) {
group_movetogroup(cc, tc->group->num);
if ((tc = client_find(trans)) != NULL && tc->gc) {
group_movetogroup(cc, tc->gc->num);
if (tc->flags & CLIENT_IGNORE)
cc->flags |= CLIENT_IGNORE;
}
@ -947,7 +961,7 @@ void
client_htile(struct client_ctx *cc)
{
struct client_ctx *ci;
struct group_ctx *gc = cc->group;
struct group_ctx *gc = cc->gc;
struct screen_ctx *sc = cc->sc;
struct geom area;
int i, n, mh, x, h, w;
@ -1006,7 +1020,7 @@ void
client_vtile(struct client_ctx *cc)
{
struct client_ctx *ci;
struct group_ctx *gc = cc->group;
struct group_ctx *gc = cc->gc;
struct screen_ctx *sc = cc->sc;
struct geom area;
int i, n, mw, y, h, w;

79
conf.c
View File

@ -40,7 +40,7 @@ static void conf_unbind_mouse(struct conf *, struct binding *);
int
conf_cmd_add(struct conf *c, const char *name, const char *path)
{
struct cmd *cmd, *prev;
struct cmd *cmd;
cmd = xmalloc(sizeof(*cmd));
@ -55,13 +55,6 @@ conf_cmd_add(struct conf *c, const char *name, const char *path)
TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry);
/* keep queue sorted by name */
while ((prev = TAILQ_PREV(cmd, cmd_q, entry)) &&
(strcmp(prev->name, cmd->name) > 0)) {
TAILQ_REMOVE(&c->cmdq, cmd, entry);
TAILQ_INSERT_BEFORE(prev, cmd, entry);
}
return(1);
}
@ -224,18 +217,18 @@ static const struct {
{ "M-j", "movedown" },
{ "M-k", "moveup" },
{ "M-l", "moveright" },
{ "M-H", "bigmoveleft" },
{ "M-J", "bigmovedown" },
{ "M-K", "bigmoveup" },
{ "M-L", "bigmoveright" },
{ "MS-h", "bigmoveleft" },
{ "MS-j", "bigmovedown" },
{ "MS-k", "bigmoveup" },
{ "MS-l", "bigmoveright" },
{ "CM-h", "resizeleft" },
{ "CM-j", "resizedown" },
{ "CM-k", "resizeup" },
{ "CM-l", "resizeright" },
{ "CM-H", "bigresizeleft" },
{ "CM-J", "bigresizedown" },
{ "CM-K", "bigresizeup" },
{ "CM-L", "bigresizeright" },
{ "CMS-h", "bigresizeleft" },
{ "CMS-j", "bigresizedown" },
{ "CMS-k", "bigresizeup" },
{ "CMS-l", "bigresizeright" },
{ "C-Left", "ptrmoveleft" },
{ "C-Down", "ptrmovedown" },
{ "C-Up", "ptrmoveup" },
@ -397,9 +390,9 @@ static const struct {
{ "cyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_CYCLE} },
{ "rcyclegroup", kbfunc_client_cyclegroup, 0, {.i = CWM_RCYCLE} },
{ "cycleingroup", kbfunc_client_cycle, CWM_WIN,
{.i = CWM_CYCLE|CWM_INGROUP} },
{.i = (CWM_CYCLE | CWM_INGROUP)} },
{ "rcycleingroup", kbfunc_client_cycle, CWM_WIN,
{.i = CWM_RCYCLE|CWM_INGROUP} },
{.i = (CWM_RCYCLE | CWM_INGROUP)} },
{ "grouptoggle", kbfunc_client_grouptoggle, CWM_WIN, {.i = 0}},
{ "sticky", kbfunc_client_toggle_sticky, CWM_WIN, {0} },
{ "fullscreen", kbfunc_client_toggle_fullscreen, CWM_WIN, {0} },
@ -415,53 +408,53 @@ static const struct {
{ "terminal", kbfunc_term, 0, {0} },
{ "lock", kbfunc_lock, 0, {0} },
{ "moveup", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_UP|CWM_MOVE)} },
{.i = (CWM_UP | CWM_MOVE)} },
{ "movedown", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_DOWN|CWM_MOVE)} },
{.i = (CWM_DOWN | CWM_MOVE)} },
{ "moveright", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_RIGHT|CWM_MOVE)} },
{.i = (CWM_RIGHT | CWM_MOVE)} },
{ "moveleft", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_LEFT|CWM_MOVE)} },
{.i = (CWM_LEFT | CWM_MOVE)} },
{ "bigmoveup", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_UP|CWM_MOVE|CWM_BIGMOVE)} },
{.i = (CWM_UP | CWM_MOVE | CWM_BIGMOVE)} },
{ "bigmovedown", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_DOWN|CWM_MOVE|CWM_BIGMOVE)} },
{.i = (CWM_DOWN | CWM_MOVE | CWM_BIGMOVE)} },
{ "bigmoveright", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_RIGHT|CWM_MOVE|CWM_BIGMOVE)} },
{.i = (CWM_RIGHT | CWM_MOVE | CWM_BIGMOVE)} },
{ "bigmoveleft", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_LEFT|CWM_MOVE|CWM_BIGMOVE)} },
{.i = (CWM_LEFT | CWM_MOVE | CWM_BIGMOVE)} },
{ "resizeup", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_UP|CWM_RESIZE)} },
{.i = (CWM_UP | CWM_RESIZE)} },
{ "resizedown", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_DOWN|CWM_RESIZE)} },
{.i = (CWM_DOWN | CWM_RESIZE)} },
{ "resizeright", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_RIGHT|CWM_RESIZE)} },
{.i = (CWM_RIGHT | CWM_RESIZE)} },
{ "resizeleft", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_LEFT|CWM_RESIZE)} },
{.i = (CWM_LEFT | CWM_RESIZE)} },
{ "bigresizeup", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_UP|CWM_RESIZE|CWM_BIGMOVE)} },
{.i = (CWM_UP | CWM_RESIZE | CWM_BIGMOVE)} },
{ "bigresizedown", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_DOWN|CWM_RESIZE|CWM_BIGMOVE)} },
{.i = (CWM_DOWN | CWM_RESIZE | CWM_BIGMOVE)} },
{ "bigresizeright", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_RIGHT|CWM_RESIZE|CWM_BIGMOVE)} },
{.i = (CWM_RIGHT | CWM_RESIZE | CWM_BIGMOVE)} },
{ "bigresizeleft", kbfunc_client_moveresize, CWM_WIN,
{.i = (CWM_LEFT|CWM_RESIZE|CWM_BIGMOVE)} },
{.i = (CWM_LEFT | CWM_RESIZE | CWM_BIGMOVE)} },
{ "ptrmoveup", kbfunc_client_moveresize, 0,
{.i = (CWM_UP|CWM_PTRMOVE)} },
{.i = (CWM_UP | CWM_PTRMOVE)} },
{ "ptrmovedown", kbfunc_client_moveresize, 0,
{.i = (CWM_DOWN|CWM_PTRMOVE)} },
{.i = (CWM_DOWN | CWM_PTRMOVE)} },
{ "ptrmoveleft", kbfunc_client_moveresize, 0,
{.i = (CWM_LEFT|CWM_PTRMOVE)} },
{.i = (CWM_LEFT | CWM_PTRMOVE)} },
{ "ptrmoveright", kbfunc_client_moveresize, 0,
{.i = (CWM_RIGHT|CWM_PTRMOVE)} },
{.i = (CWM_RIGHT | CWM_PTRMOVE)} },
{ "bigptrmoveup", kbfunc_client_moveresize, 0,
{.i = (CWM_UP|CWM_PTRMOVE|CWM_BIGMOVE)} },
{.i = (CWM_UP | CWM_PTRMOVE | CWM_BIGMOVE)} },
{ "bigptrmovedown", kbfunc_client_moveresize, 0,
{.i = (CWM_DOWN|CWM_PTRMOVE|CWM_BIGMOVE)} },
{.i = (CWM_DOWN | CWM_PTRMOVE | CWM_BIGMOVE)} },
{ "bigptrmoveleft", kbfunc_client_moveresize, 0,
{.i = (CWM_LEFT|CWM_PTRMOVE|CWM_BIGMOVE)} },
{.i = (CWM_LEFT | CWM_PTRMOVE | CWM_BIGMOVE)} },
{ "bigptrmoveright", kbfunc_client_moveresize, 0,
{.i = (CWM_RIGHT|CWM_PTRMOVE|CWM_BIGMOVE)} },
{.i = (CWM_RIGHT | CWM_PTRMOVE | CWM_BIGMOVE)} },
{ "htile", kbfunc_tile, CWM_WIN, {.i = CWM_TILE_HORIZ} },
{ "vtile", kbfunc_tile, CWM_WIN, {.i = CWM_TILE_VERT} },
{ "window_lower", kbfunc_client_lower, CWM_WIN, {0} },
@ -675,6 +668,7 @@ static char *ewmhints[] = {
"_NET_SUPPORTING_WM_CHECK",
"_NET_ACTIVE_WINDOW",
"_NET_CLIENT_LIST",
"_NET_CLIENT_LIST_STACKING",
"_NET_NUMBER_OF_DESKTOPS",
"_NET_CURRENT_DESKTOP",
"_NET_DESKTOP_VIEWPORT",
@ -693,6 +687,7 @@ static char *ewmhints[] = {
"_NET_WM_STATE_HIDDEN",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_STATE_DEMANDS_ATTENTION",
"_CWM_WM_STATE_FREEZE",
};
void

4
cwm.1
View File

@ -117,9 +117,9 @@ Toggle maximization of current window.
Toggle vertical maximization of current window.
.It Ic CMS-=
Toggle horizontal maximization of current window.
.It Ic C-[Up|Down|Left|Right]
.It Ic C-[Up | Down | Left | Right]
Move pointer by a small amount.
.It Ic CS-[Up|Down|Left|Right]
.It Ic CS-[Up | Down | Left | Right]
Move pointer by a large amount; see
.Xr cwmrc 5 .
.It Ic M-[hjkl]

150
group.c
View File

@ -32,7 +32,8 @@
#include "calmwm.h"
static void group_assign(struct group_ctx *, struct client_ctx *);
static struct group_ctx *group_next(struct group_ctx *);
static struct group_ctx *group_prev(struct group_ctx *);
static void group_restack(struct group_ctx *);
static void group_setactive(struct group_ctx *);
@ -41,15 +42,18 @@ const char *num_to_name[] = {
"seven", "eight", "nine"
};
static void
void
group_assign(struct group_ctx *gc, struct client_ctx *cc)
{
if (cc->group != NULL)
TAILQ_REMOVE(&cc->group->clientq, cc, group_entry);
if (cc->gc != NULL)
TAILQ_REMOVE(&cc->gc->clientq, cc, group_entry);
cc->group = gc;
if ((gc != NULL) && (gc->num == 0))
gc = NULL;
if (cc->group != NULL)
cc->gc = gc;
if (cc->gc != NULL)
TAILQ_INSERT_TAIL(&gc->clientq, cc, group_entry);
xu_ewmh_net_wm_desktop(cc);
@ -62,8 +66,10 @@ group_hide(struct group_ctx *gc)
screen_updatestackingorder(gc->sc);
TAILQ_FOREACH(cc, &gc->clientq, group_entry)
client_hide(cc);
TAILQ_FOREACH(cc, &gc->clientq, group_entry) {
if (!(cc->flags & CLIENT_STICKY))
client_hide(cc);
}
}
void
@ -71,8 +77,10 @@ group_show(struct group_ctx *gc)
{
struct client_ctx *cc;
TAILQ_FOREACH(cc, &gc->clientq, group_entry)
client_unhide(cc);
TAILQ_FOREACH(cc, &gc->clientq, group_entry) {
if (!(cc->flags & CLIENT_STICKY))
client_unhide(cc);
}
group_restack(gc);
group_setactive(gc);
@ -154,7 +162,7 @@ group_movetogroup(struct client_ctx *cc, int idx)
break;
}
if (cc->group == gc)
if (cc->gc == gc)
return;
if (group_holds_only_hidden(gc))
client_hide(cc);
@ -167,7 +175,7 @@ group_toggle_membership_enter(struct client_ctx *cc)
struct screen_ctx *sc = cc->sc;
struct group_ctx *gc = sc->group_active;
if (gc == cc->group) {
if (gc == cc->gc) {
group_assign(NULL, cc);
cc->flags |= CLIENT_UNGROUP;
} else {
@ -255,36 +263,31 @@ group_only(struct screen_ctx *sc, int idx)
}
}
/*
* Cycle through active groups. If none exist, then just stay put.
*/
void
group_cycle(struct screen_ctx *sc, int flags)
{
struct group_ctx *gc, *showgroup = NULL;
struct group_ctx *newgc, *oldgc, *showgroup = NULL;
if (((gc = sc->group_active)) == NULL)
errx(1, "group_cycle: no active group");
oldgc = sc->group_active;
newgc = oldgc;
for (;;) {
gc = (flags & CWM_RCYCLE) ? TAILQ_PREV(gc, group_ctx_q,
entry) : TAILQ_NEXT(gc, entry);
if (gc == NULL)
gc = (flags & CWM_RCYCLE) ? TAILQ_LAST(&sc->groupq,
group_ctx_q) : TAILQ_FIRST(&sc->groupq);
if (gc == sc->group_active)
newgc = (flags & CWM_RCYCLE) ? group_prev(newgc) :
group_next(newgc);
if (newgc == oldgc)
break;
if (!group_holds_only_sticky(gc) && showgroup == NULL)
showgroup = gc;
else if (!group_holds_only_hidden(gc))
group_hide(gc);
if (!group_holds_only_sticky(newgc) && showgroup == NULL)
showgroup = newgc;
else if (!group_holds_only_hidden(newgc))
group_hide(newgc);
}
if (showgroup == NULL)
return;
group_hide(sc->group_active);
group_hide(oldgc);
if (group_holds_only_hidden(showgroup))
group_show(showgroup);
@ -292,6 +295,26 @@ group_cycle(struct screen_ctx *sc, int flags)
group_setactive(showgroup);
}
static struct group_ctx *
group_next(struct group_ctx *gc)
{
struct screen_ctx *sc = gc->sc;
struct group_ctx *newgc;
return(((newgc = TAILQ_NEXT(gc, entry)) != NULL) ?
newgc : TAILQ_FIRST(&sc->groupq));
}
static struct group_ctx *
group_prev(struct group_ctx *gc)
{
struct screen_ctx *sc = gc->sc;
struct group_ctx *newgc;
return(((newgc = TAILQ_PREV(gc, group_ctx_q, entry)) != NULL) ?
newgc : TAILQ_LAST(&sc->groupq, group_ctx_q));
}
void
group_alltoggle(struct screen_ctx *sc)
{
@ -306,51 +329,58 @@ group_alltoggle(struct screen_ctx *sc)
sc->hideall = !sc->hideall;
}
void
int
group_restore(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct group_ctx *gc;
int num;
long *grpnum;
if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP], XA_CARDINAL, 1L,
(unsigned char **)&grpnum) <= 0)
return(0);
num = (*grpnum == -1) ? 0 : *grpnum;
num = MIN(num, (CALMWM_NGROUPS - 1));
XFree(grpnum);
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == num) {
group_assign(gc, cc);
return(1);
}
}
return(0);
}
int
group_autogroup(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct autogroupwin *aw;
struct group_ctx *gc;
int num = -2, both_match = 0;
long *grpnum;
int num = -1, both_match = 0;
if (cc->ch.res_class == NULL || cc->ch.res_name == NULL)
return;
return(0);
if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP],
XA_CARDINAL, 1, (unsigned char **)&grpnum) > 0) {
num = *grpnum;
if (num > CALMWM_NGROUPS || num < -1)
num = CALMWM_NGROUPS - 1;
XFree(grpnum);
} else {
TAILQ_FOREACH(aw, &Conf.autogroupq, entry) {
if (strcmp(aw->class, cc->ch.res_class) == 0) {
if ((aw->name != NULL) &&
(strcmp(aw->name, cc->ch.res_name) == 0)) {
num = aw->num;
both_match = 1;
} else if (aw->name == NULL && !both_match)
num = aw->num;
}
TAILQ_FOREACH(aw, &Conf.autogroupq, entry) {
if (strcmp(aw->class, cc->ch.res_class) == 0) {
if ((aw->name != NULL) &&
(strcmp(aw->name, cc->ch.res_name) == 0)) {
num = aw->num;
both_match = 1;
} else if (aw->name == NULL && !both_match)
num = aw->num;
}
}
if ((num == -1) || (num == 0)) {
group_assign(NULL, cc);
return;
}
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == num) {
group_assign(gc, cc);
return;
return(1);
}
}
if (Conf.flags & CONF_STICKY_GROUPS)
group_assign(sc->group_active, cc);
else
group_assign(NULL, cc);
return(0);
}

View File

@ -61,7 +61,7 @@ kbfunc_client_moveresize(struct client_ctx *cc, union arg *arg)
int x, y, flags, amt;
unsigned int mx, my;
if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY))
if (cc->flags & CLIENT_FREEZE)
return;
mx = my = 0;
@ -177,8 +177,13 @@ kbfunc_menu_cmd(struct client_ctx *cc, union arg *arg)
struct menu_q menuq;
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry)
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
if ((strcmp(cmd->name, "lock") == 0) ||
(strcmp(cmd->name, "term") == 0))
continue;
/* search_match_text() needs mi->text */
menuq_add(&menuq, cmd, "%s", cmd->name);
}
if ((mi = menu_filter(sc, &menuq, "application", NULL, 0,
search_match_text, search_print_cmd)) != NULL)
@ -215,13 +220,7 @@ kbfunc_menu_group(struct client_ctx *cc, union arg *arg)
void
kbfunc_client_cycle(struct client_ctx *cc, union arg *arg)
{
struct screen_ctx *sc = cc->sc;
/* XXX for X apps that ignore events */
XGrabKeyboard(X_Dpy, sc->rootwin, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
client_cycle(sc, arg->i);
client_cycle(cc->sc, arg->i);
}
void
@ -466,7 +465,7 @@ void
kbfunc_client_grouptoggle(struct client_ctx *cc, union arg *arg)
{
if (arg->i == 0) {
/* XXX for stupid X apps like xpdf and gvim */
/* For X apps that steal events. */
XGrabKeyboard(X_Dpy, cc->win, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
}

View File

@ -72,7 +72,7 @@ mousefunc_client_resize(struct client_ctx *cc, union arg *arg)
struct screen_ctx *sc = cc->sc;
int x = cc->geom.x, y = cc->geom.y;
if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY))
if (cc->flags & CLIENT_FREEZE)
return;
client_raise(cc);
@ -128,7 +128,7 @@ mousefunc_client_move(struct client_ctx *cc, union arg *arg)
client_raise(cc);
if (cc->flags & (CLIENT_FREEZE|CLIENT_STICKY))
if (cc->flags & CLIENT_FREEZE)
return;
if (xu_ptr_grab(cc->win, MOUSEMASK, Conf.cursor[CF_MOVE]) < 0)
@ -233,8 +233,12 @@ mousefunc_menu_cmd(struct client_ctx *cc, union arg *arg)
struct menu_q menuq;
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry)
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
if ((strcmp(cmd->name, "lock") == 0) ||
(strcmp(cmd->name, "term") == 0))
continue;
menuq_add(&menuq, cmd, NULL);
}
if ((mi = menu_filter(sc, &menuq, NULL, NULL, CWM_MENU_LIST,
NULL, search_print_cmd)) != NULL)

View File

@ -67,12 +67,12 @@ screen_init(int which)
xu_ewmh_net_virtual_roots(sc);
rootattr.cursor = Conf.cursor[CF_NORMAL];
rootattr.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|
PropertyChangeMask|EnterWindowMask|LeaveWindowMask|
ColormapChangeMask|BUTTONMASK;
rootattr.event_mask = SubstructureRedirectMask |
SubstructureNotifyMask | PropertyChangeMask | EnterWindowMask |
LeaveWindowMask | ColormapChangeMask | BUTTONMASK;
XChangeWindowAttributes(X_Dpy, sc->rootwin,
CWEventMask|CWCursor, &rootattr);
(CWEventMask | CWCursor), &rootattr);
/* Deal with existing clients. */
if (XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins)) {

View File

@ -127,14 +127,8 @@ void
search_print_cmd(struct menu *mi, int i)
{
struct cmd *cmd = (struct cmd *)mi->ctx;
int special = 0;
if ((strcmp(cmd->name, "lock") == 0) ||
(strcmp(cmd->name, "term") == 0))
special = 1;
(void)snprintf(mi->print, sizeof(mi->print),
(special) ? "[%s]" : "%s", cmd->name);
(void)snprintf(mi->print, sizeof(mi->print), "%s", cmd->name);
}
void
@ -162,7 +156,7 @@ search_print_client(struct menu *mi, int list)
cc->matchname = cc->name;
(void)snprintf(mi->print, sizeof(mi->print), "(%d) %c[%s] %s",
(cc->group) ? cc->group->num : 0, flag,
(cc->gc) ? cc->gc->num : 0, flag,
(cc->label) ? cc->label : "", cc->matchname);
}

View File

@ -77,7 +77,7 @@ xev_handle_maprequest(XEvent *ee)
XMapRequestEvent *e = &ee->xmaprequest;
struct client_ctx *cc = NULL, *old_cc;
if ((old_cc = client_current()))
if ((old_cc = client_current()) != NULL)
client_ptrsave(old_cc);
if ((cc = client_find(e->window)) == NULL)
@ -252,7 +252,7 @@ xev_handle_buttonrelease(XEvent *ee)
{
struct client_ctx *cc;
if ((cc = client_current()))
if ((cc = client_current()) != NULL)
group_toggle_membership_leave(cc);
}
@ -339,7 +339,7 @@ xev_handle_clientmessage(XEvent *ee)
}
} else if (e->message_type == ewmh[_NET_ACTIVE_WINDOW]) {
if ((cc = client_find(e->window)) != NULL) {
if ((old_cc = client_current()))
if ((old_cc = client_current()) != NULL)
client_ptrsave(old_cc);
client_ptrwarp(cc);
}

45
xutil.c
View File

@ -228,6 +228,27 @@ xu_ewmh_net_client_list(struct screen_ctx *sc)
free(winlist);
}
void
xu_ewmh_net_client_list_stacking(struct screen_ctx *sc)
{
struct client_ctx *cc;
Window *winlist;
int i = 0, j;
TAILQ_FOREACH(cc, &sc->clientq, entry)
i++;
if (i == 0)
return;
j = i;
winlist = xreallocarray(NULL, i, sizeof(*winlist));
TAILQ_FOREACH(cc, &sc->clientq, entry)
winlist[--j] = cc->win;
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_CLIENT_LIST_STACKING],
XA_WINDOW, 32, PropModeReplace, (unsigned char *)winlist, i);
free(winlist);
}
void
xu_ewmh_net_active_window(struct screen_ctx *sc, Window w)
{
@ -341,8 +362,8 @@ xu_ewmh_net_wm_desktop(struct client_ctx *cc)
{
long num = 0xffffffff;
if (cc->group)
num = cc->group->num;
if (cc->gc)
num = cc->gc->num;
XChangeProperty(X_Dpy, cc->win, ewmh[_NET_WM_DESKTOP],
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&num, 1);
@ -392,6 +413,9 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action,
{ _NET_WM_STATE_DEMANDS_ATTENTION,
CLIENT_URGENCY,
client_urgency },
{ _CWM_WM_STATE_FREEZE,
CLIENT_FREEZE,
client_toggle_freeze },
};
for (i = 0; i < nitems(handlers); i++) {
@ -423,16 +447,18 @@ xu_ewmh_restore_net_wm_state(struct client_ctx *cc)
for (i = 0; i < n; i++) {
if (atoms[i] == ewmh[_NET_WM_STATE_STICKY])
client_toggle_sticky(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ])
client_toggle_hmaximize(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT])
client_toggle_vmaximize(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ])
client_toggle_hmaximize(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_HIDDEN])
client_toggle_hidden(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_FULLSCREEN])
client_toggle_fullscreen(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_DEMANDS_ATTENTION])
client_urgency(cc);
if (atoms[i] == ewmh[_CWM_WM_STATE_FREEZE])
client_toggle_freeze(cc);
}
free(atoms);
}
@ -447,11 +473,12 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
atoms = xreallocarray(NULL, (n + _NET_WM_STATES_NITEMS), sizeof(Atom));
for (i = j = 0; i < n; i++) {
if (oatoms[i] != ewmh[_NET_WM_STATE_STICKY] &&
oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] &&
oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT] &&
oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] &&
oatoms[i] != ewmh[_NET_WM_STATE_HIDDEN] &&
oatoms[i] != ewmh[_NET_WM_STATE_FULLSCREEN] &&
oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION])
oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION] &&
oatoms[i] != ewmh[_CWM_WM_STATE_FREEZE])
atoms[j++] = oatoms[i];
}
free(oatoms);
@ -462,13 +489,15 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
if (cc->flags & CLIENT_FULLSCREEN)
atoms[j++] = ewmh[_NET_WM_STATE_FULLSCREEN];
else {
if (cc->flags & CLIENT_HMAXIMIZED)
atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_HORZ];
if (cc->flags & CLIENT_VMAXIMIZED)
atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_VERT];
if (cc->flags & CLIENT_HMAXIMIZED)
atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_HORZ];
}
if (cc->flags & CLIENT_URGENCY)
atoms[j++] = ewmh[_NET_WM_STATE_DEMANDS_ATTENTION];
if (cc->flags & CLIENT_FREEZE)
atoms[j++] = ewmh[_CWM_WM_STATE_FREEZE];
if (j > 0)
XChangeProperty(X_Dpy, cc->win, ewmh[_NET_WM_STATE],
XA_ATOM, 32, PropModeReplace, (unsigned char *)atoms, j);