Implement support for EWMH's _NET_WM_STATE_FULLSCREEN hint.

Since we already have a form of 'maximize', we need to differentiate
between 'maximize' and the new 'fullscreen' mode.  The 'maximize' mode
will continue to honor gap but now *retains* the border, matching the
'vert/horz maximize' behaviour.  The new 'fullscreen' mode supports and
follows the _NET_WM_STATE_FULLSCREEN hint, allowing the client perform
additional window modifications; in this mode, cwm(1) will *ignore* gap,
remove borders and freeze(move/resize) the client.  Additionally,
'fullscreen' mode will remember various combinations of previous states.

* default keybinding changes: CM-f 'fullscreen', CM-m 'maximize' (re-map
  as desired).

Positive feedback from a few, testing and ok sthen@
This commit is contained in:
okan 2013-12-16 19:02:17 +00:00
parent f98f4615c0
commit 19fc7f666b
7 changed files with 78 additions and 36 deletions

View File

@ -138,7 +138,7 @@ struct client_ctx {
Window win; Window win;
Colormap colormap; Colormap colormap;
u_int bwidth; /* border width */ u_int bwidth; /* border width */
struct geom geom, savegeom; struct geom geom, savegeom, fullgeom;
struct { struct {
long flags; /* defined hints */ long flags; /* defined hints */
int basew; /* desired width */ int basew; /* desired width */
@ -167,6 +167,7 @@ struct client_ctx {
#define CLIENT_WM_DELETE_WINDOW 0x0100 #define CLIENT_WM_DELETE_WINDOW 0x0100
#define CLIENT_WM_TAKE_FOCUS 0x0200 #define CLIENT_WM_TAKE_FOCUS 0x0200
#define CLIENT_URGENCY 0x0400 #define CLIENT_URGENCY 0x0400
#define CLIENT_FULLSCREEN 0x0800
#define CLIENT_HIGHLIGHT (CLIENT_GROUP | CLIENT_UNGROUP) #define CLIENT_HIGHLIGHT (CLIENT_GROUP | CLIENT_UNGROUP)
#define CLIENT_MAXFLAGS (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED) #define CLIENT_MAXFLAGS (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED)
@ -355,9 +356,10 @@ enum {
_NET_WM_DESKTOP, _NET_WM_DESKTOP,
_NET_CLOSE_WINDOW, _NET_CLOSE_WINDOW,
_NET_WM_STATE, _NET_WM_STATE,
#define _NET_WM_STATES_NITEMS 3 #define _NET_WM_STATES_NITEMS 4
_NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_VERT,
_NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_HORZ,
_NET_WM_STATE_FULLSCREEN,
_NET_WM_STATE_DEMANDS_ATTENTION, _NET_WM_STATE_DEMANDS_ATTENTION,
EWMH_NITEMS EWMH_NITEMS
}; };
@ -380,6 +382,7 @@ void client_delete(struct client_ctx *);
void client_draw_border(struct client_ctx *); void client_draw_border(struct client_ctx *);
struct client_ctx *client_find(Window); struct client_ctx *client_find(Window);
void client_freeze(struct client_ctx *); void client_freeze(struct client_ctx *);
void client_fullscreen(struct client_ctx *);
long client_get_wm_state(struct client_ctx *); long client_get_wm_state(struct client_ctx *);
void client_getsizehints(struct client_ctx *); void client_getsizehints(struct client_ctx *);
void client_hide(struct client_ctx *); void client_hide(struct client_ctx *);
@ -445,6 +448,8 @@ void kbfunc_client_cyclegroup(struct client_ctx *,
union arg *); union arg *);
void kbfunc_client_delete(struct client_ctx *, union arg *); void kbfunc_client_delete(struct client_ctx *, union arg *);
void kbfunc_client_freeze(struct client_ctx *, union arg *); void kbfunc_client_freeze(struct client_ctx *, union arg *);
void kbfunc_client_fullscreen(struct client_ctx *,
union arg *);
void kbfunc_client_group(struct client_ctx *, union arg *); void kbfunc_client_group(struct client_ctx *, union arg *);
void kbfunc_client_grouponly(struct client_ctx *, void kbfunc_client_grouponly(struct client_ctx *,
union arg *); union arg *);

View File

@ -228,6 +228,38 @@ client_freeze(struct client_ctx *cc)
cc->flags |= CLIENT_FREEZE; cc->flags |= CLIENT_FREEZE;
} }
void
client_fullscreen(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct geom xine;
if ((cc->flags & CLIENT_FREEZE) &&
!(cc->flags & CLIENT_FULLSCREEN))
return;
if ((cc->flags & CLIENT_FULLSCREEN)) {
cc->bwidth = Conf.bwidth;
cc->geom = cc->fullgeom;
cc->flags &= ~(CLIENT_FULLSCREEN | CLIENT_FREEZE);
goto resize;
}
cc->fullgeom = cc->geom;
xine = screen_find_xinerama(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_NOGAP);
cc->bwidth = 0;
cc->geom = xine;
cc->flags |= (CLIENT_FULLSCREEN | CLIENT_FREEZE);
resize:
client_resize(cc, 0);
xu_ewmh_set_net_wm_state(cc);
}
void void
client_maximize(struct client_ctx *cc) client_maximize(struct client_ctx *cc)
{ {
@ -238,9 +270,8 @@ client_maximize(struct client_ctx *cc)
return; return;
if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_MAXIMIZED) { if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_MAXIMIZED) {
cc->flags &= ~CLIENT_MAXIMIZED;
cc->geom = cc->savegeom; cc->geom = cc->savegeom;
cc->bwidth = Conf.bwidth; cc->flags &= ~CLIENT_MAXIMIZED;
goto resize; goto resize;
} }
@ -263,8 +294,10 @@ client_maximize(struct client_ctx *cc)
cc->geom.x + cc->geom.w / 2, cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP); cc->geom.y + cc->geom.h / 2, CWM_GAP);
cc->geom = xine; cc->geom.x = xine.x;
cc->bwidth = 0; cc->geom.y = xine.y;
cc->geom.w = xine.w - (cc->bwidth * 2);
cc->geom.h = xine.h - (cc->bwidth * 2);
cc->flags |= CLIENT_MAXIMIZED; cc->flags |= CLIENT_MAXIMIZED;
resize: resize:
@ -284,9 +317,6 @@ client_vmaximize(struct client_ctx *cc)
if (cc->flags & CLIENT_VMAXIMIZED) { if (cc->flags & CLIENT_VMAXIMIZED) {
cc->geom.y = cc->savegeom.y; cc->geom.y = cc->savegeom.y;
cc->geom.h = cc->savegeom.h; cc->geom.h = cc->savegeom.h;
cc->bwidth = Conf.bwidth;
if (cc->flags & CLIENT_HMAXIMIZED)
cc->geom.w -= cc->bwidth * 2;
cc->flags &= ~CLIENT_VMAXIMIZED; cc->flags &= ~CLIENT_VMAXIMIZED;
goto resize; goto resize;
} }
@ -294,12 +324,6 @@ client_vmaximize(struct client_ctx *cc)
cc->savegeom.y = cc->geom.y; cc->savegeom.y = cc->geom.y;
cc->savegeom.h = cc->geom.h; cc->savegeom.h = cc->geom.h;
/* if this will make us fully maximized then remove boundary */
if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_HMAXIMIZED) {
cc->geom.w += cc->bwidth * 2;
cc->bwidth = 0;
}
xine = screen_find_xinerama(sc, xine = screen_find_xinerama(sc,
cc->geom.x + cc->geom.w / 2, cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP); cc->geom.y + cc->geom.h / 2, CWM_GAP);
@ -325,9 +349,6 @@ client_hmaximize(struct client_ctx *cc)
if (cc->flags & CLIENT_HMAXIMIZED) { if (cc->flags & CLIENT_HMAXIMIZED) {
cc->geom.x = cc->savegeom.x; cc->geom.x = cc->savegeom.x;
cc->geom.w = cc->savegeom.w; cc->geom.w = cc->savegeom.w;
cc->bwidth = Conf.bwidth;
if (cc->flags & CLIENT_VMAXIMIZED)
cc->geom.h -= cc->bwidth * 2;
cc->flags &= ~CLIENT_HMAXIMIZED; cc->flags &= ~CLIENT_HMAXIMIZED;
goto resize; goto resize;
} }
@ -335,12 +356,6 @@ client_hmaximize(struct client_ctx *cc)
cc->savegeom.x = cc->geom.x; cc->savegeom.x = cc->geom.x;
cc->savegeom.w = cc->geom.w; cc->savegeom.w = cc->geom.w;
/* if this will make us fully maximized then remove boundary */
if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_VMAXIMIZED) {
cc->geom.h += cc->bwidth * 2;
cc->bwidth = 0;
}
xine = screen_find_xinerama(sc, xine = screen_find_xinerama(sc,
cc->geom.x + cc->geom.w / 2, cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP); cc->geom.y + cc->geom.h / 2, CWM_GAP);
@ -359,7 +374,6 @@ client_resize(struct client_ctx *cc, int reset)
{ {
if (reset) { if (reset) {
cc->flags &= ~CLIENT_MAXIMIZED; cc->flags &= ~CLIENT_MAXIMIZED;
cc->bwidth = Conf.bwidth;
xu_ewmh_set_net_wm_state(cc); xu_ewmh_set_net_wm_state(cc);
} }

5
conf.c
View File

@ -178,7 +178,8 @@ static struct {
{ "M-Right", "cyclegroup" }, { "M-Right", "cyclegroup" },
{ "M-Left", "rcyclegroup" }, { "M-Left", "rcyclegroup" },
{ "CM-g", "grouptoggle" }, { "CM-g", "grouptoggle" },
{ "CM-f", "maximize" }, { "CM-f", "fullscreen" },
{ "CM-m", "maximize" },
{ "CM-equal", "vmaximize" }, { "CM-equal", "vmaximize" },
{ "CMS-equal", "hmaximize" }, { "CMS-equal", "hmaximize" },
{ "CMS-f", "freeze" }, { "CMS-f", "freeze" },
@ -376,6 +377,7 @@ static struct {
{ "rcycleingroup", kbfunc_client_cycle, KBFLAG_NEEDCLIENT, { "rcycleingroup", kbfunc_client_cycle, KBFLAG_NEEDCLIENT,
{.i = CWM_RCYCLE|CWM_INGROUP} }, {.i = CWM_RCYCLE|CWM_INGROUP} },
{ "grouptoggle", kbfunc_client_grouptoggle, KBFLAG_NEEDCLIENT, {0}}, { "grouptoggle", kbfunc_client_grouptoggle, KBFLAG_NEEDCLIENT, {0}},
{ "fullscreen", kbfunc_client_fullscreen, KBFLAG_NEEDCLIENT, {0} },
{ "maximize", kbfunc_client_maximize, KBFLAG_NEEDCLIENT, {0} }, { "maximize", kbfunc_client_maximize, KBFLAG_NEEDCLIENT, {0} },
{ "vmaximize", kbfunc_client_vmaximize, KBFLAG_NEEDCLIENT, {0} }, { "vmaximize", kbfunc_client_vmaximize, KBFLAG_NEEDCLIENT, {0} },
{ "hmaximize", kbfunc_client_hmaximize, KBFLAG_NEEDCLIENT, {0} }, { "hmaximize", kbfunc_client_hmaximize, KBFLAG_NEEDCLIENT, {0} },
@ -688,6 +690,7 @@ static char *ewmhints[] = {
"_NET_WM_STATE", "_NET_WM_STATE",
"_NET_WM_STATE_MAXIMIZED_VERT", "_NET_WM_STATE_MAXIMIZED_VERT",
"_NET_WM_STATE_MAXIMIZED_HORZ", "_NET_WM_STATE_MAXIMIZED_HORZ",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_STATE_DEMANDS_ATTENTION", "_NET_WM_STATE_DEMANDS_ATTENTION",
}; };

6
cwm.1
View File

@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: May 9 2012 $ .Dd $Mdocdate: October 31 2012 $
.Dt CWM 1 .Dt CWM 1
.Os .Os
.Sh NAME .Sh NAME
@ -91,7 +91,9 @@ Reverse cycle through active groups.
.It Ic CMS-f .It Ic CMS-f
Toggle freezing geometry of current window. Toggle freezing geometry of current window.
.It Ic CM-f .It Ic CM-f
Toggle full-screen size of current window. Toggle full-screen mode of current window.
.It Ic CM-m
Toggle maximization of current window.
.It Ic CM-= .It Ic CM-=
Toggle vertical maximization of current window. Toggle vertical maximization of current window.
.It Ic CMS-= .It Ic CMS-=

10
cwmrc.5
View File

@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\" .\"
.Dd $Mdocdate: November 27 2013 $ .Dd $Mdocdate: December 13 2013 $
.Dt CWMRC 5 .Dt CWMRC 5
.Os .Os
.Sh NAME .Sh NAME
@ -341,12 +341,14 @@ Raise current window.
Label current window. Label current window.
.It freeze .It freeze
Freeze current window geometry. Freeze current window geometry.
.It fullscreen
Full-screen current window (gap + border removed).
.It maximize .It maximize
Maximize current window full-screen. Maximize current window (gap + border honored).
.It vmaximize .It vmaximize
Maximize current window vertically. Vertically maximize current window (gap + border honored).
.It hmaximize .It hmaximize
Maximize current window horizontally. Horizontally maximize current window (gap + border honored).
.It moveup .It moveup
Move window Move window
.Ar moveamount .Ar moveamount

View File

@ -447,6 +447,12 @@ kbfunc_client_movetogroup(struct client_ctx *cc, union arg *arg)
group_movetogroup(cc, arg->i); group_movetogroup(cc, arg->i);
} }
void
kbfunc_client_fullscreen(struct client_ctx *cc, union arg *arg)
{
client_fullscreen(cc);
}
void void
kbfunc_client_maximize(struct client_ctx *cc, union arg *arg) kbfunc_client_maximize(struct client_ctx *cc, union arg *arg)
{ {

18
xutil.c
View File

@ -333,6 +333,9 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action,
{ _NET_WM_STATE_MAXIMIZED_HORZ, { _NET_WM_STATE_MAXIMIZED_HORZ,
CLIENT_HMAXIMIZED, CLIENT_HMAXIMIZED,
client_hmaximize }, client_hmaximize },
{ _NET_WM_STATE_FULLSCREEN,
CLIENT_FULLSCREEN,
client_fullscreen },
{ _NET_WM_STATE_DEMANDS_ATTENTION, { _NET_WM_STATE_DEMANDS_ATTENTION,
CLIENT_URGENCY, CLIENT_URGENCY,
client_urgency }, client_urgency },
@ -369,6 +372,8 @@ xu_ewmh_restore_net_wm_state(struct client_ctx *cc)
client_hmaximize(cc); client_hmaximize(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT]) if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT])
client_vmaximize(cc); client_vmaximize(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_FULLSCREEN])
client_fullscreen(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_DEMANDS_ATTENTION]) if (atoms[i] == ewmh[_NET_WM_STATE_DEMANDS_ATTENTION])
client_urgency(cc); client_urgency(cc);
} }
@ -386,14 +391,19 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
for (i = j = 0; i < n; i++) { for (i = j = 0; i < n; i++) {
if (oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] && if (oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ] &&
oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT] && oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT] &&
oatoms[i] != ewmh[_NET_WM_STATE_FULLSCREEN] &&
oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION]) oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION])
atoms[j++] = oatoms[i]; atoms[j++] = oatoms[i];
} }
free(oatoms); free(oatoms);
if (cc->flags & CLIENT_HMAXIMIZED) if (cc->flags & CLIENT_FULLSCREEN)
atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_HORZ]; atoms[j++] = ewmh[_NET_WM_STATE_FULLSCREEN];
if (cc->flags & CLIENT_VMAXIMIZED) else {
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_VMAXIMIZED)
atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_VERT];
}
if (cc->flags & CLIENT_URGENCY) if (cc->flags & CLIENT_URGENCY)
atoms[j++] = ewmh[_NET_WM_STATE_DEMANDS_ATTENTION]; atoms[j++] = ewmh[_NET_WM_STATE_DEMANDS_ATTENTION];
if (j > 0) if (j > 0)