summary refs log tree commit diff
diff options
context:
space:
mode:
authorokan <okan>2014-08-25 12:49:19 +0000
committerokan <okan>2014-08-25 12:49:19 +0000
commit7314a3aefd33e901cfa1bd4a48eb4e75be4c01e2 (patch)
tree35bc0dd75f4e6dbd5072bbefd10d949e374b100d
parented164794cb3d375b24809f1f042124109ee1fbea (diff)
downloadcwm-7314a3aefd33e901cfa1bd4a48eb4e75be4c01e2.tar.gz
cwm-7314a3aefd33e901cfa1bd4a48eb4e75be4c01e2.tar.xz
cwm-7314a3aefd33e901cfa1bd4a48eb4e75be4c01e2.zip
Implement _NET_WM_STATE_STICKY, bound to CM-s by default; allows any
client to 'stick' to all desktops (ewmh speak) or groups - this
currently has the same affect as setting a client's group to 'nogroup',
with the exception that the client can also be in a group, so when
un-sticking, the client will go back to its original group/desktop.
-rw-r--r--calmwm.h6
-rw-r--r--client.c17
-rw-r--r--conf.c3
-rw-r--r--cwm.14
-rw-r--r--cwmrc.54
-rw-r--r--group.c2
-rw-r--r--kbfunc.c6
-rw-r--r--xutil.c8
8 files changed, 47 insertions, 3 deletions
diff --git a/calmwm.h b/calmwm.h
index 2f55d44..0cd1685 100644
--- a/calmwm.h
+++ b/calmwm.h
@@ -180,6 +180,7 @@ struct client_ctx {
 #define CLIENT_WM_TAKE_FOCUS		0x0200
 #define CLIENT_URGENCY			0x0400
 #define CLIENT_FULLSCREEN		0x0800
+#define CLIENT_STICKY			0x1000
 
 #define CLIENT_HIGHLIGHT		(CLIENT_GROUP | CLIENT_UNGROUP)
 #define CLIENT_MAXFLAGS			(CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED)
@@ -349,7 +350,8 @@ enum {
 	_NET_WM_DESKTOP,
 	_NET_CLOSE_WINDOW,
 	_NET_WM_STATE,
-#define	_NET_WM_STATES_NITEMS	4
+#define	_NET_WM_STATES_NITEMS	5
+	_NET_WM_STATE_STICKY,
 	_NET_WM_STATE_MAXIMIZED_VERT,
 	_NET_WM_STATE_MAXIMIZED_HORZ,
 	_NET_WM_STATE_FULLSCREEN,
@@ -396,6 +398,7 @@ void			 client_set_wm_state(struct client_ctx *, long);
 void			 client_setactive(struct client_ctx *);
 void			 client_setname(struct client_ctx *);
 int			 client_snapcalc(int, int, int, int, int);
+void			 client_sticky(struct client_ctx *);
 void			 client_transient(struct client_ctx *);
 void			 client_unhide(struct client_ctx *);
 void			 client_urgency(struct client_ctx *);
@@ -464,6 +467,7 @@ void			 kbfunc_client_nogroup(struct client_ctx *,
 void			 kbfunc_client_raise(struct client_ctx *, union arg *);
 void			 kbfunc_client_rcycle(struct client_ctx *, union arg *);
 void			 kbfunc_client_search(struct client_ctx *, union arg *);
+void			 kbfunc_client_sticky(struct client_ctx *, union arg *);
 void			 kbfunc_client_vmaximize(struct client_ctx *,
 			     union arg *);
 void			 kbfunc_cmdexec(struct client_ctx *, union arg *);
diff --git a/client.c b/client.c
index bacfb51..d8e7fc4 100644
--- a/client.c
+++ b/client.c
@@ -239,6 +239,17 @@ client_freeze(struct client_ctx *cc)
 }
 
 void
+client_sticky(struct client_ctx *cc)
+{
+	if (cc->flags & CLIENT_STICKY)
+		cc->flags &= ~CLIENT_STICKY;
+	else
+		cc->flags |= CLIENT_STICKY;
+
+	xu_ewmh_set_net_wm_state(cc);
+}
+
+void
 client_fullscreen(struct client_ctx *cc)
 {
 	struct screen_ctx	*sc = cc->sc;
@@ -468,6 +479,9 @@ 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->active = 0;
@@ -481,6 +495,9 @@ 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;
diff --git a/conf.c b/conf.c
index 2ad6727..fcae046 100644
--- a/conf.c
+++ b/conf.c
@@ -204,6 +204,7 @@ static const struct {
 	{ "CM-g",	"grouptoggle" },
 	{ "CM-f",	"fullscreen" },
 	{ "CM-m",	"maximize" },
+	{ "CM-s",	"sticky" },
 	{ "CM-equal",	"vmaximize" },
 	{ "CMS-equal",	"hmaximize" },
 	{ "CMS-f",	"freeze" },
@@ -389,6 +390,7 @@ static const struct {
 	{ "rcycleingroup", kbfunc_client_cycle, CWM_WIN,
 	    {.i = CWM_RCYCLE|CWM_INGROUP} },
 	{ "grouptoggle", kbfunc_client_grouptoggle, CWM_WIN, {0}},
+	{ "sticky", kbfunc_client_sticky, CWM_WIN, {0} },
 	{ "fullscreen", kbfunc_client_fullscreen, CWM_WIN, {0} },
 	{ "maximize", kbfunc_client_maximize, CWM_WIN, {0} },
 	{ "vmaximize", kbfunc_client_vmaximize, CWM_WIN, {0} },
@@ -678,6 +680,7 @@ static char *ewmhints[] = {
 	"_NET_WM_DESKTOP",
 	"_NET_CLOSE_WINDOW",
 	"_NET_WM_STATE",
+	"_NET_WM_STATE_STICKY",
 	"_NET_WM_STATE_MAXIMIZED_VERT",
 	"_NET_WM_STATE_MAXIMIZED_HORZ",
 	"_NET_WM_STATE_FULLSCREEN",
diff --git a/cwm.1 b/cwm.1
index b3a5c3d..eb6c9e7 100644
--- a/cwm.1
+++ b/cwm.1
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: December 16 2013 $
+.Dd $Mdocdate$
 .Dt CWM 1
 .Os
 .Sh NAME
@@ -90,6 +90,8 @@ Cycle through active groups.
 Reverse cycle through active groups.
 .It Ic CMS-f
 Toggle freezing geometry of current window.
+.It Ic CM-s
+Toggle stickiness of current window.
 .It Ic CM-f
 Toggle full-screen mode of current window.
 .It Ic CM-m
diff --git a/cwmrc.5 b/cwmrc.5
index bc6e9c2..a0b39d3 100644
--- a/cwmrc.5
+++ b/cwmrc.5
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: December 16 2013 $
+.Dd $Mdocdate$
 .Dt CWMRC 5
 .Os
 .Sh NAME
@@ -341,6 +341,8 @@ Raise current window.
 Label current window.
 .It freeze
 Freeze current window geometry.
+.It sticky
+Stick current window to all groups (same as assigning to nogroup).
 .It fullscreen
 Full-screen current window (gap + border removed).
 .It maximize
diff --git a/group.c b/group.c
index 1290621..3657fad 100644
--- a/group.c
+++ b/group.c
@@ -207,6 +207,8 @@ group_hidden_state(struct group_ctx *gc)
 	int			 hidden = 0, same = 0;
 
 	TAILQ_FOREACH(cc, &gc->clients, group_entry) {
+		if (cc->flags & CLIENT_STICKY)
+			continue;
 		if (hidden == ((cc->flags & CLIENT_HIDDEN) ? 1 : 0))
 			same++;
 	}
diff --git a/kbfunc.c b/kbfunc.c
index 813f8e6..241c0b4 100644
--- a/kbfunc.c
+++ b/kbfunc.c
@@ -433,6 +433,12 @@ kbfunc_client_movetogroup(struct client_ctx *cc, union arg *arg)
 }
 
 void
+kbfunc_client_sticky(struct client_ctx *cc, union arg *arg)
+{
+	client_sticky(cc);
+}
+
+void
 kbfunc_client_fullscreen(struct client_ctx *cc, union arg *arg)
 {
 	client_fullscreen(cc);
diff --git a/xutil.c b/xutil.c
index 847b148..b61b0ee 100644
--- a/xutil.c
+++ b/xutil.c
@@ -326,6 +326,9 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action,
 		int property;
 		void (*toggle)(struct client_ctx *);
 	} handlers[] = {
+		{ _NET_WM_STATE_STICKY,
+			CLIENT_STICKY,
+			client_sticky },
 		{ _NET_WM_STATE_MAXIMIZED_VERT,
 			CLIENT_VMAXIMIZED,
 			client_vmaximize },
@@ -367,6 +370,8 @@ xu_ewmh_restore_net_wm_state(struct client_ctx *cc)
 
 	atoms = xu_ewmh_get_net_wm_state(cc, &n);
 	for (i = 0; i < n; i++) {
+		if (atoms[i] == ewmh[_NET_WM_STATE_STICKY])
+			client_sticky(cc);
 		if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ])
 			client_hmaximize(cc);
 		if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT])
@@ -391,10 +396,13 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
 		if (oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] &&
 		    oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT] &&
 		    oatoms[i] != ewmh[_NET_WM_STATE_FULLSCREEN] &&
+		    oatoms[i] != ewmh[_NET_WM_STATE_STICKY] &&
 		    oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION])
 			atoms[j++] = oatoms[i];
 	}
 	free(oatoms);
+	if (cc->flags & CLIENT_STICKY)
+		atoms[j++] = ewmh[_NET_WM_STATE_STICKY];
 	if (cc->flags & CLIENT_FULLSCREEN)
 		atoms[j++] = ewmh[_NET_WM_STATE_FULLSCREEN];
 	else {