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

View File

@ -228,6 +228,38 @@ client_freeze(struct client_ctx *cc)
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
client_maximize(struct client_ctx *cc)
{
@ -238,9 +270,8 @@ client_maximize(struct client_ctx *cc)
return;
if ((cc->flags & CLIENT_MAXFLAGS) == CLIENT_MAXIMIZED) {
cc->flags &= ~CLIENT_MAXIMIZED;
cc->geom = cc->savegeom;
cc->bwidth = Conf.bwidth;
cc->flags &= ~CLIENT_MAXIMIZED;
goto resize;
}
@ -263,8 +294,10 @@ client_maximize(struct client_ctx *cc)
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
cc->geom = xine;
cc->bwidth = 0;
cc->geom.x = xine.x;
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;
resize:
@ -284,9 +317,6 @@ client_vmaximize(struct client_ctx *cc)
if (cc->flags & CLIENT_VMAXIMIZED) {
cc->geom.y = cc->savegeom.y;
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;
goto resize;
}
@ -294,12 +324,6 @@ client_vmaximize(struct client_ctx *cc)
cc->savegeom.y = cc->geom.y;
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,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
@ -325,9 +349,6 @@ client_hmaximize(struct client_ctx *cc)
if (cc->flags & CLIENT_HMAXIMIZED) {
cc->geom.x = cc->savegeom.x;
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;
goto resize;
}
@ -335,12 +356,6 @@ client_hmaximize(struct client_ctx *cc)
cc->savegeom.x = cc->geom.x;
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,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
@ -359,7 +374,6 @@ 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);
}

5
conf.c
View File

@ -178,7 +178,8 @@ static struct {
{ "M-Right", "cyclegroup" },
{ "M-Left", "rcyclegroup" },
{ "CM-g", "grouptoggle" },
{ "CM-f", "maximize" },
{ "CM-f", "fullscreen" },
{ "CM-m", "maximize" },
{ "CM-equal", "vmaximize" },
{ "CMS-equal", "hmaximize" },
{ "CMS-f", "freeze" },
@ -376,6 +377,7 @@ static struct {
{ "rcycleingroup", kbfunc_client_cycle, KBFLAG_NEEDCLIENT,
{.i = CWM_RCYCLE|CWM_INGROUP} },
{ "grouptoggle", kbfunc_client_grouptoggle, KBFLAG_NEEDCLIENT, {0}},
{ "fullscreen", kbfunc_client_fullscreen, KBFLAG_NEEDCLIENT, {0} },
{ "maximize", kbfunc_client_maximize, KBFLAG_NEEDCLIENT, {0} },
{ "vmaximize", kbfunc_client_vmaximize, KBFLAG_NEEDCLIENT, {0} },
{ "hmaximize", kbfunc_client_hmaximize, KBFLAG_NEEDCLIENT, {0} },
@ -688,6 +690,7 @@ static char *ewmhints[] = {
"_NET_WM_STATE",
"_NET_WM_STATE_MAXIMIZED_VERT",
"_NET_WM_STATE_MAXIMIZED_HORZ",
"_NET_WM_STATE_FULLSCREEN",
"_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
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: May 9 2012 $
.Dd $Mdocdate: October 31 2012 $
.Dt CWM 1
.Os
.Sh NAME
@ -91,7 +91,9 @@ Reverse cycle through active groups.
.It Ic CMS-f
Toggle freezing geometry of current window.
.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-=
Toggle vertical maximization of current window.
.It Ic CMS-=

10
cwmrc.5
View File

@ -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: November 27 2013 $
.Dd $Mdocdate: December 13 2013 $
.Dt CWMRC 5
.Os
.Sh NAME
@ -341,12 +341,14 @@ Raise current window.
Label current window.
.It freeze
Freeze current window geometry.
.It fullscreen
Full-screen current window (gap + border removed).
.It maximize
Maximize current window full-screen.
Maximize current window (gap + border honored).
.It vmaximize
Maximize current window vertically.
Vertically maximize current window (gap + border honored).
.It hmaximize
Maximize current window horizontally.
Horizontally maximize current window (gap + border honored).
.It moveup
Move window
.Ar moveamount

View File

@ -447,6 +447,12 @@ kbfunc_client_movetogroup(struct client_ctx *cc, union arg *arg)
group_movetogroup(cc, arg->i);
}
void
kbfunc_client_fullscreen(struct client_ctx *cc, union arg *arg)
{
client_fullscreen(cc);
}
void
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,
CLIENT_HMAXIMIZED,
client_hmaximize },
{ _NET_WM_STATE_FULLSCREEN,
CLIENT_FULLSCREEN,
client_fullscreen },
{ _NET_WM_STATE_DEMANDS_ATTENTION,
CLIENT_URGENCY,
client_urgency },
@ -369,6 +372,8 @@ xu_ewmh_restore_net_wm_state(struct client_ctx *cc)
client_hmaximize(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT])
client_vmaximize(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_FULLSCREEN])
client_fullscreen(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_DEMANDS_ATTENTION])
client_urgency(cc);
}
@ -386,14 +391,19 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
for (i = j = 0; i < n; i++) {
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_DEMANDS_ATTENTION])
atoms[j++] = oatoms[i];
}
free(oatoms);
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_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_URGENCY)
atoms[j++] = ewmh[_NET_WM_STATE_DEMANDS_ATTENTION];
if (j > 0)