about summary refs log tree commit diff
path: root/group.c
diff options
context:
space:
mode:
authorokan <okan>2015-08-28 12:07:28 +0000
committerokan <okan>2015-08-28 12:07:28 +0000
commit3f0b6cf4ea53d80ef7e2d9a96f4d93bb209aa2b6 (patch)
treec5a24ee9a664320b85b6a7db1101376c08f4bc7d /group.c
parentc0f2d0cc756f5ec7076946179efe2399f026c60a (diff)
parent47a10cc05549b0a94e3606ca7be9fe626754d12d (diff)
downloadcwm-3f0b6cf4ea53d80ef7e2d9a96f4d93bb209aa2b6.tar.gz
cwm-3f0b6cf4ea53d80ef7e2d9a96f4d93bb209aa2b6.tar.xz
cwm-3f0b6cf4ea53d80ef7e2d9a96f4d93bb209aa2b6.zip
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.
  ...
Diffstat (limited to 'group.c')
-rw-r--r--group.c150
1 files changed, 90 insertions, 60 deletions
diff --git a/group.c b/group.c
index 9fe6115..10130f4 100644
--- a/group.c
+++ b/group.c
@@ -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
-group_autogroup(struct client_ctx *cc)
+int
+group_restore(struct client_ctx *cc)
 {
 	struct screen_ctx	*sc = cc->sc;
-	struct autogroupwin	*aw;
 	struct group_ctx	*gc;
-	int			 num = -2, both_match = 0;
+	int			 num;
 	long			*grpnum;
 
-	if (cc->ch.res_class == NULL || cc->ch.res_name == NULL)
-		return;
+	if (xu_getprop(cc->win, ewmh[_NET_WM_DESKTOP], XA_CARDINAL, 1L,
+	    (unsigned char **)&grpnum) <= 0)
+		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;
-			}
+	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);
+}
 
-	if ((num == -1) || (num == 0)) {
-		group_assign(NULL, cc);
-		return;
+int
+group_autogroup(struct client_ctx *cc)
+{
+	struct screen_ctx	*sc = cc->sc;
+	struct autogroupwin	*aw;
+	struct group_ctx	*gc;
+	int			 num = -1, both_match = 0;
+
+	if (cc->ch.res_class == NULL || cc->ch.res_name == NULL)
+		return(0);
+
+	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(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);
 }