sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

dwm-fullscreenmodes-20260922-44dbc68.diff (9525B)


      1 From 19ffcdf58d0055c1d9bdefe72f9a23a10a13161f Mon Sep 17 00:00:00 2001
      2 From: Niky Kovalski <nikykovalski@gmail.com>
      3 Date: Tue, 22 Sep 2026 15:17:25 -0400
      4 Subject: [PATCH] fullscreenmodes
      5 
      6 - toggle actual fullscreen or fake fullscreen
      7 - switching between the two is possible
      8 - the client never exits fullscreen when switching between
      9 fullscreen modes
     10 ---
     11  config.def.h |  8 +++--
     12  dwm.1        |  6 ++++
     13  dwm.c        | 89 +++++++++++++++++++++++++++++++++++++++++++++++-----
     14  3 files changed, 92 insertions(+), 11 deletions(-)
     15 
     16 diff --git a/config.def.h b/config.def.h
     17 index 81c3fc0..a8ee865 100644
     18 --- a/config.def.h
     19 +++ b/config.def.h
     20 @@ -26,9 +26,9 @@ static const Rule rules[] = {
     21  	 *	WM_CLASS(STRING) = instance, class
     22  	 *	WM_NAME(STRING) = title
     23  	 */
     24 -	/* class      instance    title       tags mask     isfloating   monitor */
     25 -	{ "Gimp",     NULL,       NULL,       0,            1,           -1 },
     26 -	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 },
     27 +	/* class      instance    title       tags mask     isfloating   isfullscreen   isfakefullscreen  monitor */
     28 +	{ "Gimp",     NULL,       NULL,       0,            1,           0,             0,                -1 },
     29 +	{ "Firefox",  NULL,       NULL,       1 << 8,       0,           0,             1,                -1 },
     30  };
     31  
     32  /* layout(s) */
     33 @@ -80,6 +80,8 @@ static const Key keys[] = {
     34  	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} },
     35  	{ MODKEY,                       XK_space,  setlayout,      {0} },
     36  	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} },
     37 +	{ MODKEY|ShiftMask,             XK_f,      togglefullscreen,       {0} },
     38 +	{ MODKEY|ControlMask,           XK_f,      togglefakefullscreen,   {0} },
     39  	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } },
     40  	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } },
     41  	{ MODKEY,                       XK_comma,  focusmon,       {.i = -1 } },
     42 diff --git a/dwm.1 b/dwm.1
     43 index ddc8321..9d4436d 100644
     44 --- a/dwm.1
     45 +++ b/dwm.1
     46 @@ -116,6 +116,12 @@ Zooms/cycles focused window to/from master area (tiled layouts only).
     47  .B Mod1\-Shift\-c
     48  Close focused window.
     49  .TP
     50 +.B Mod1\-Shift\-f
     51 +Toggle fullscreen for focused window.
     52 +.TP
     53 +.B Mod1\-Control\-f
     54 +Toggle fake fullscreen for focused window.
     55 +.TP
     56  .B Mod1\-Shift\-space
     57  Toggle focused window between tiled and floating state.
     58  .TP
     59 diff --git a/dwm.c b/dwm.c
     60 index ab3a84c..859d3d0 100644
     61 --- a/dwm.c
     62 +++ b/dwm.c
     63 @@ -91,7 +91,7 @@ struct Client {
     64  	int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
     65  	int bw, oldbw;
     66  	unsigned int tags;
     67 -	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
     68 +	int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, isfakefullscreen;
     69  	Client *next;
     70  	Client *snext;
     71  	Monitor *mon;
     72 @@ -137,6 +137,8 @@ typedef struct {
     73  	const char *title;
     74  	unsigned int tags;
     75  	int isfloating;
     76 +	int isfullscreen;
     77 +    int isfakefullscreen;
     78  	int monitor;
     79  } Rule;
     80  
     81 @@ -199,6 +201,7 @@ static void sendmon(Client *c, Monitor *m);
     82  static void setclientstate(Client *c, long state);
     83  static void setfocus(Client *c);
     84  static void setfullscreen(Client *c, int fullscreen);
     85 +static void setfullscreenmode(Client *c, int fakefullscreen);
     86  static void setlayout(const Arg *arg);
     87  static void setmfact(const Arg *arg);
     88  static void setup(void);
     89 @@ -210,6 +213,8 @@ static void tagmon(const Arg *arg);
     90  static void tile(Monitor *m);
     91  static void togglebar(const Arg *arg);
     92  static void togglefloating(const Arg *arg);
     93 +static void togglefakefullscreen(const Arg *arg);
     94 +static void togglefullscreen(const Arg *arg);
     95  static void toggletag(const Arg *arg);
     96  static void toggleview(const Arg *arg);
     97  static void unfocus(Client *c, int setfocus);
     98 @@ -284,6 +289,8 @@ applyrules(Client *c)
     99  	XClassHint ch = { NULL, NULL };
    100  
    101  	/* rule matching */
    102 +	int isfullscreen = 0;
    103 +    c->isfakefullscreen = 0;
    104  	c->isfloating = 0;
    105  	c->tags = 0;
    106  	XGetClassHint(dpy, c->win, &ch);
    107 @@ -296,6 +303,8 @@ applyrules(Client *c)
    108  		&& (!r->class || strstr(class, r->class))
    109  		&& (!r->instance || strstr(instance, r->instance)))
    110  		{
    111 +			isfullscreen = r->isfullscreen;
    112 +			c->isfakefullscreen = r->isfakefullscreen;
    113  			c->isfloating = r->isfloating;
    114  			c->tags |= r->tags;
    115  			for (m = mons; m && m->num != r->monitor; m = m->next);
    116 @@ -307,6 +316,8 @@ applyrules(Client *c)
    117  		XFree(ch.res_class);
    118  	if (ch.res_name)
    119  		XFree(ch.res_name);
    120 +	if (isfullscreen)
    121 +		setfullscreen(c, 1);
    122  	c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
    123  }
    124  
    125 @@ -523,7 +534,7 @@ clientmessage(XEvent *e)
    126  		if (cme->data.l[1] == netatom[NetWMFullscreen]
    127  		|| cme->data.l[2] == netatom[NetWMFullscreen])
    128  			setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD    */
    129 -				|| (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
    130 +				|| (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && (!c->isfullscreen || c->isfakefullscreen))));
    131  	} else if (cme->message_type == netatom[NetActiveWindow]) {
    132  		if (c != selmon->sel && !c->isurgent)
    133  			seturgent(c, 1);
    134 @@ -567,7 +578,7 @@ configurenotify(XEvent *e)
    135  			updatebars();
    136  			for (m = mons; m; m = m->next) {
    137  				for (c = m->clients; c; c = c->next)
    138 -					if (c->isfullscreen)
    139 +					if (c->isfullscreen && !c->isfakefullscreen)
    140  						resizeclient(c, m->mx, m->my, m->mw, m->mh);
    141  				XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
    142  			}
    143 @@ -839,7 +850,7 @@ focusstack(const Arg *arg)
    144  {
    145  	Client *c = NULL, *i;
    146  
    147 -	if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen))
    148 +	if (!selmon->sel || (selmon->sel->isfullscreen && !selmon->sel->isfakefullscreen && lockfullscreen))
    149  		return;
    150  	if (arg->i > 0) {
    151  		for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
    152 @@ -1153,7 +1164,7 @@ movemouse(const Arg *arg)
    153  
    154  	if (!(c = selmon->sel))
    155  		return;
    156 -	if (c->isfullscreen) /* no support moving fullscreen windows by mouse */
    157 +	if (c->isfullscreen && !c->isfakefullscreen) /* no support moving fullscreen windows by mouse */
    158  		return;
    159  	restack(selmon);
    160  	ocx = c->x;
    161 @@ -1308,7 +1319,7 @@ resizemouse(const Arg *arg)
    162  
    163  	if (!(c = selmon->sel))
    164  		return;
    165 -	if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */
    166 +	if (c->isfullscreen && !c->isfakefullscreen) /* no support resizing fullscreen windows by mouse */
    167  		return;
    168  	restack(selmon);
    169  	ocx = c->x;
    170 @@ -1486,6 +1497,10 @@ setfullscreen(Client *c, int fullscreen)
    171  		XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
    172  			PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
    173  		c->isfullscreen = 1;
    174 +		if (c->isfakefullscreen) {
    175 +			resizeclient(c, c->x, c->y, c->w, c->h);
    176 +			return;
    177 +		}
    178  		c->oldstate = c->isfloating;
    179  		c->oldbw = c->bw;
    180  		c->bw = 0;
    181 @@ -1496,6 +1511,29 @@ setfullscreen(Client *c, int fullscreen)
    182  		XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
    183  			PropModeReplace, (unsigned char*)0, 0);
    184  		c->isfullscreen = 0;
    185 +		if (c->isfakefullscreen) {
    186 +			resizeclient(c, c->x, c->y, c->w, c->h);
    187 +			return;
    188 +		}
    189 +		c->isfloating = c->oldstate;
    190 +		c->bw = c->oldbw;
    191 +		c->x = c->oldx;
    192 +		c->y = c->oldy;
    193 +		c->w = c->oldw;
    194 +		c->h = c->oldh;
    195 +		resizeclient(c, c->x, c->y, c->w, c->h);
    196 +		arrange(c->mon);
    197 +	}
    198 +}
    199 +
    200 +void
    201 +setfullscreenmode(Client *c, int fakefullscreen) {
    202 +	if (!c->isfullscreen) {
    203 +		c->isfakefullscreen = fakefullscreen;
    204 +		return;
    205 +	}
    206 +	if (fakefullscreen && !c->isfakefullscreen) {
    207 +		c->isfakefullscreen = 1;
    208  		c->isfloating = c->oldstate;
    209  		c->bw = c->oldbw;
    210  		c->x = c->oldx;
    211 @@ -1505,6 +1543,15 @@ setfullscreen(Client *c, int fullscreen)
    212  		resizeclient(c, c->x, c->y, c->w, c->h);
    213  		arrange(c->mon);
    214  	}
    215 +	else if (!fakefullscreen && c->isfakefullscreen) {
    216 +		c->isfakefullscreen = 0;
    217 +		c->oldstate = c->isfloating;
    218 +		c->oldbw = c->bw;
    219 +		c->bw = 0;
    220 +		c->isfloating = 1;
    221 +		resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
    222 +		XRaiseWindow(dpy, c->win);
    223 +	}
    224  }
    225  
    226  void
    227 @@ -1634,7 +1681,7 @@ showhide(Client *c)
    228  	if (ISVISIBLE(c)) {
    229  		/* show clients top down */
    230  		XMoveWindow(dpy, c->win, c->x, c->y);
    231 -		if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && !c->isfullscreen)
    232 +		if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating) && (!c->isfullscreen || c->isfakefullscreen))
    233  			resize(c, c->x, c->y, c->w, c->h, 0);
    234  		showhide(c->snext);
    235  	} else {
    236 @@ -1726,7 +1773,7 @@ togglefloating(const Arg *arg)
    237  {
    238  	if (!selmon->sel)
    239  		return;
    240 -	if (selmon->sel->isfullscreen) /* no support for fullscreen windows */
    241 +	if (selmon->sel->isfullscreen && !selmon->sel->isfakefullscreen) /* no support for fullscreen windows */
    242  		return;
    243  	selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed;
    244  	if (selmon->sel->isfloating)
    245 @@ -1735,6 +1782,32 @@ togglefloating(const Arg *arg)
    246  	arrange(selmon);
    247  }
    248  
    249 +void
    250 +togglefakefullscreen(const Arg *arg)
    251 +{
    252 +	if (!selmon->sel)
    253 +		return;
    254 +	if (selmon->sel->isfullscreen && !selmon->sel->isfakefullscreen)
    255 +		setfullscreenmode(selmon->sel, 1);
    256 +    else {
    257 +		selmon->sel->isfakefullscreen = 1;
    258 +		setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
    259 +    }
    260 +}
    261 +
    262 +void
    263 +togglefullscreen(const Arg *arg)
    264 +{
    265 +	if (!selmon->sel)
    266 +		return;
    267 +	if (selmon->sel->isfullscreen && selmon->sel->isfakefullscreen)
    268 +		setfullscreenmode(selmon->sel, 0);
    269 +    else {
    270 +		selmon->sel->isfakefullscreen = 0;
    271 +		setfullscreen(selmon->sel, !selmon->sel->isfullscreen);
    272 +    }
    273 +}
    274 +
    275  void
    276  toggletag(const Arg *arg)
    277  {
    278 -- 
    279 2.55.0
    280