summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--calmwm.h7
-rw-r--r--client.c5
-rw-r--r--xutil.c61
3 files changed, 73 insertions, 0 deletions
diff --git a/calmwm.h b/calmwm.h
index 5671ece..e525cbf 100644
--- a/calmwm.h
+++ b/calmwm.h
@@ -481,6 +481,9 @@ void			 xu_ewmh_net_desktop_names(struct screen_ctx *, char *,
 			     int);
 
 void			 xu_ewmh_net_wm_desktop(struct client_ctx *);
+Atom 			*xu_ewmh_get_net_wm_state(struct client_ctx *, int *);
+void 			 xu_ewmh_set_net_wm_state(struct client_ctx *);
+void 			 xu_ewmh_restore_net_wm_state(struct client_ctx *);
 
 void			 u_exec(char *);
 void			 u_spawn(char *);
@@ -534,6 +537,10 @@ enum {
 	_NET_WM_NAME,
 	_NET_WM_DESKTOP,
 	_NET_CLOSE_WINDOW,
+	_NET_WM_STATE,
+#define	_NET_WM_STATES_NITEMS	2
+	_NET_WM_STATE_MAXIMIZED_VERT,
+	_NET_WM_STATE_MAXIMIZED_HORZ,
 	EWMH_NITEMS
 };
 struct atom_ctx {
diff --git a/client.c b/client.c
index 9ebd8bc..605c2a4 100644
--- a/client.c
+++ b/client.c
@@ -133,6 +133,7 @@ client_init(Window win, struct screen_ctx *sc, int mapped)
 	xu_ewmh_net_client_list(sc);
 
 	client_wm_protocols(cc);
+	xu_ewmh_restore_net_wm_state(cc);
 
 	if (mapped)
 		group_autogroup(cc);
@@ -301,6 +302,7 @@ client_maximize(struct client_ctx *cc)
 
 resize:
 	client_resize(cc, 0);
+	xu_ewmh_set_net_wm_state(cc);
 }
 
 void
@@ -341,6 +343,7 @@ client_vmaximize(struct client_ctx *cc)
 
 resize:
 	client_resize(cc, 0);
+	xu_ewmh_set_net_wm_state(cc);
 }
 
 void
@@ -381,6 +384,7 @@ client_hmaximize(struct client_ctx *cc)
 
 resize:
 	client_resize(cc, 0);
+	xu_ewmh_set_net_wm_state(cc);
 }
 
 void
@@ -389,6 +393,7 @@ client_resize(struct client_ctx *cc, int reset)
 	if (reset) {
 		cc->flags &= ~CLIENT_MAXIMIZED;
 		cc->bwidth = Conf.bwidth;
+		xu_ewmh_set_net_wm_state(cc);
 	}
 
 	client_draw_border(cc);
diff --git a/xutil.c b/xutil.c
index d5055f2..95bb0d4 100644
--- a/xutil.c
+++ b/xutil.c
@@ -257,6 +257,9 @@ struct atom_ctx ewmh[EWMH_NITEMS] = {
 	{"_NET_WM_NAME",		None},
 	{"_NET_WM_DESKTOP",		None},
 	{"_NET_CLOSE_WINDOW",		None},
+	{"_NET_WM_STATE", 		None},
+	{"_NET_WM_STATE_MAXIMIZED_VERT",None},
+	{"_NET_WM_STATE_MAXIMIZED_HORZ",None},
 };
 
 void
@@ -420,6 +423,64 @@ xu_ewmh_net_wm_desktop(struct client_ctx *cc)
 	    XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&no, 1);
 }
 
+Atom *
+xu_ewmh_get_net_wm_state(struct client_ctx *cc, int *n)
+{
+	Atom	*state, *p = NULL;
+
+	if ((*n = xu_getprop(cc->win, ewmh[_NET_WM_STATE].atom, XA_ATOM, 64L,
+	    (u_char **)&p)) <= 0)
+		return (NULL);
+
+	state = xmalloc(*n * sizeof(Atom));
+	memcpy(state, p, *n * sizeof(Atom));
+	XFree((char *)p);
+
+	return (state);
+}
+
+void
+xu_ewmh_restore_net_wm_state(struct client_ctx *cc)
+{
+	Atom	*atoms;
+	int	 i, n;
+
+	atoms = xu_ewmh_get_net_wm_state(cc, &n);
+	for (i = 0; i < n; i++) {
+		if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ].atom)
+			client_hmaximize(cc);
+		if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT].atom)
+			client_vmaximize(cc);
+	}
+	free(atoms);
+}
+
+void
+xu_ewmh_set_net_wm_state(struct client_ctx *cc)
+{
+	Atom	*atoms, *oatoms;
+	int	 n, i, j;
+
+	oatoms = xu_ewmh_get_net_wm_state(cc, &n);
+	atoms = xmalloc((n + _NET_WM_STATES_NITEMS) * sizeof(Atom));
+	for (i = j = 0; i < n; i++) {
+		if (oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ].atom &&
+		    oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT].atom)
+			atoms[j++] = oatoms[i];
+	}
+	free(oatoms);
+	if (cc->flags & CLIENT_HMAXIMIZED)
+		atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_HORZ].atom;
+	if (cc->flags & CLIENT_VMAXIMIZED)
+		atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_VERT].atom;
+	if (j > 0)
+		XChangeProperty(X_Dpy, cc->win, ewmh[_NET_WM_STATE].atom,
+		    XA_ATOM, 32, PropModeReplace, (unsigned char *)atoms, j);
+	else
+		XDeleteProperty(X_Dpy, cc->win, ewmh[_NET_WM_STATE].atom);
+	free(atoms);
+}
+
 void
 xu_xorcolor(XftColor a, XftColor b, XftColor *r)
 {