2019-09-04 22:16:39 +00:00
|
|
|
/* See LICENSE file for copyright and license details.
|
|
|
|
*
|
|
|
|
* dynamic window manager is designed like any other X client as well. It is
|
|
|
|
* driven through handling X events. In contrast to other X clients, a window
|
|
|
|
* manager selects for SubstructureRedirectMask on the root window, to receive
|
|
|
|
* events about window (dis-)appearance. Only one X connection at a time is
|
|
|
|
* allowed to select for this event mask.
|
|
|
|
*
|
|
|
|
* The event handlers of dwm are organized in an array which is accessed
|
|
|
|
* whenever a new event has been fetched. This allows event dispatching
|
|
|
|
* in O(1) time.
|
|
|
|
*
|
|
|
|
* Each child of the root window is called a client, except windows which have
|
|
|
|
* set the override_redirect flag. Clients are organized in a linked client
|
|
|
|
* list on each monitor, the focus history is remembered through a stack list
|
|
|
|
* on each monitor. Each client contains a bit array to indicate the tags of a
|
|
|
|
* client.
|
|
|
|
*
|
|
|
|
* Keys and tagging rules are organized as arrays and defined in config.h.
|
|
|
|
*
|
|
|
|
* To understand everything else, start reading main().
|
|
|
|
*/
|
|
|
|
#include <errno.h>
|
|
|
|
#include <locale.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <X11/cursorfont.h>
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xproto.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#ifdef XINERAMA
|
|
|
|
#include <X11/extensions/Xinerama.h>
|
|
|
|
#endif /* XINERAMA */
|
|
|
|
#include <X11/Xft/Xft.h>
|
|
|
|
|
2019-09-04 22:32:39 +00:00
|
|
|
#include "patches.h"
|
2019-09-04 22:16:39 +00:00
|
|
|
#include "drw.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_PANGO_PATCH
|
2020-06-11 17:42:00 +00:00
|
|
|
#include <pango/pango.h>
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_PANGO_PATCH
|
2020-06-11 17:42:00 +00:00
|
|
|
|
2019-10-10 21:50:30 +00:00
|
|
|
#if SPAWNCMD_PATCH
|
|
|
|
#include <assert.h>
|
|
|
|
#include <libgen.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#define SPAWN_CWD_DELIM " []{}()<>\"':"
|
|
|
|
#endif // SPAWNCMD_PATCH
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
/* macros */
|
2020-07-15 06:57:30 +00:00
|
|
|
#define BARRULES 20
|
2019-09-04 22:16:39 +00:00
|
|
|
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
|
|
|
|
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
|
|
|
|
#define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \
|
|
|
|
* MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy)))
|
2019-09-14 22:43:35 +00:00
|
|
|
#if ATTACHASIDE_PATCH && STICKY_PATCH
|
|
|
|
#define ISVISIBLEONTAG(C, T) ((C->tags & T) || C->issticky)
|
|
|
|
#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags])
|
|
|
|
#elif ATTACHASIDE_PATCH
|
2019-09-06 21:25:32 +00:00
|
|
|
#define ISVISIBLEONTAG(C, T) ((C->tags & T))
|
|
|
|
#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags])
|
2019-09-14 22:43:35 +00:00
|
|
|
#elif STICKY_PATCH
|
|
|
|
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky)
|
2019-09-06 21:25:32 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
|
2019-09-06 21:25:32 +00:00
|
|
|
#endif // ATTACHASIDE_PATCH
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_AWESOMEBAR_PATCH
|
2019-09-09 22:18:46 +00:00
|
|
|
#define HIDDEN(C) ((getstate(C->win) == IconicState))
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_AWESOMEBAR_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
#define LENGTH(X) (sizeof X / sizeof X[0])
|
|
|
|
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
|
|
|
|
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
|
|
|
|
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
|
2020-06-15 11:24:23 +00:00
|
|
|
#define WTYPE "_NET_WM_WINDOW_TYPE_"
|
2020-06-05 09:23:22 +00:00
|
|
|
#if SCRATCHPADS_PATCH
|
[dwm][PATCH] Multiple scratchpads
This patch enables multiple scratchpads, each with one assigned window.
This enables the same scratchpad workflow that you have in i3.
Scratchpads are implemented as special tags, whose mask does not
apply to new spawned windows. To assign a window to a scratchpad you
have to set up a rule, as you do with regular tags.
Windows tagged with scratchpad tags can be set floating or not in the
rules array. Most users would probably want them floating (i3 style),
but having them tiled does also perfectly work and might fit better the
DWM approach. In case they are set floating, the patch moves them to the
center of the screen whenever the are shown. The patch can easily be
modified to make this last feature configurable in the rules array (see
the center patch).
The togglescratch function, borrowed from the previous scratchpad patch
and slightly modified, can be used to spawn a registered scratchpad
process or toggle its view. This function looks for a window tagged on
the selected scratchpad. If it is found its view is toggled. If it is
not found the corresponding registered command is spawned. The
config.def.h shows three examples of its use to spawn a terminal in the
first scratchpad tag, a second terminal running ranger on the second
scratchpad tag and the keepassxc application to manage passwords on a
third scratchpad tag.
If you prefer to spawn your scratchpad applications from the startup
script, you might opt for binding keys to toggleview instead, as
scratchpads are just special tags (you may even extend the TAGKEYS macro
to generalize the key bindings).
2020-04-16 14:39:22 +00:00
|
|
|
#define NUMTAGS (LENGTH(tags) + LENGTH(scratchpads))
|
|
|
|
#define TAGMASK ((1 << NUMTAGS) - 1)
|
|
|
|
#define SPTAG(i) ((1 << LENGTH(tags)) << (i))
|
|
|
|
#define SPTAGMASK (((1 << LENGTH(scratchpads))-1) << LENGTH(tags))
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
#define TAGMASK ((1 << LENGTH(tags)) - 1)
|
2020-06-05 09:23:22 +00:00
|
|
|
#endif // SCRATCHPADS_PATCH
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_PANGO_PATCH
|
2020-06-11 17:42:00 +00:00
|
|
|
#define TEXTW(X) (drw_font_getwidth(drw, (X), False) + lrpad)
|
|
|
|
#define TEXTWM(X) (drw_font_getwidth(drw, (X), True) + lrpad)
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_PANGO_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
/* enums */
|
2020-06-25 09:56:41 +00:00
|
|
|
enum {
|
|
|
|
#if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH
|
|
|
|
CurResizeBR,
|
|
|
|
CurResizeBL,
|
|
|
|
CurResizeTR,
|
|
|
|
CurResizeTL,
|
|
|
|
#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
|
|
|
|
#if DRAGMFACT_PATCH
|
|
|
|
CurResizeHorzArrow,
|
|
|
|
CurResizeVertArrow,
|
|
|
|
#endif // DRAGMFACT_PATCH
|
|
|
|
#if DRAGCFACT_PATCH
|
|
|
|
CurIronCross,
|
|
|
|
#endif // DRAGCFACT_PATCH
|
|
|
|
CurNormal,
|
|
|
|
CurResize,
|
|
|
|
CurMove,
|
|
|
|
CurLast
|
|
|
|
}; /* cursor */
|
2019-09-13 21:56:05 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
SchemeNorm
|
|
|
|
,SchemeSel
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUSCOLORS_PATCH
|
2019-10-06 22:46:23 +00:00
|
|
|
,SchemeWarn
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSCOLORS_PATCH
|
|
|
|
#if URGENTBORDER_PATCH || BAR_STATUSCOLORS_PATCH
|
2019-09-15 22:13:03 +00:00
|
|
|
,SchemeUrg
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // URGENTBORDER_PATCH || BAR_STATUSCOLORS_PATCH
|
|
|
|
#if BAR_AWESOMEBAR_PATCH
|
2019-09-13 21:56:05 +00:00
|
|
|
,SchemeHid
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_AWESOMEBAR_PATCH
|
|
|
|
#if BAR_VTCOLORS_PATCH
|
2020-02-11 17:31:11 +00:00
|
|
|
,SchemeTagsNorm
|
|
|
|
,SchemeTagsSel
|
|
|
|
,SchemeTitleNorm
|
|
|
|
,SchemeTitleSel
|
|
|
|
,SchemeStatus
|
2020-07-15 06:57:30 +00:00
|
|
|
#elif BAR_TITLECOLOR_PATCH
|
2019-09-13 21:56:05 +00:00
|
|
|
,SchemeTitle
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_VTCOLORS_PATCH
|
2019-09-13 21:56:05 +00:00
|
|
|
}; /* color schemes */
|
|
|
|
|
2020-05-20 13:25:07 +00:00
|
|
|
enum {
|
|
|
|
NetSupported, NetWMName, NetWMState, NetWMCheck,
|
|
|
|
NetWMFullscreen, NetActiveWindow, NetWMWindowType,
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2020-05-20 13:25:07 +00:00
|
|
|
NetSystemTray, NetSystemTrayOP, NetSystemTrayOrientation,
|
|
|
|
NetSystemTrayVisual, NetWMWindowTypeDock, NetSystemTrayOrientationHorz,
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
|
|
|
#if BAR_EWMHTAGS_PATCH
|
2020-05-20 13:25:07 +00:00
|
|
|
NetDesktopNames, NetDesktopViewport, NetNumberOfDesktops, NetCurrentDesktop,
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EWMHTAGS_PATCH
|
2020-06-15 11:24:23 +00:00
|
|
|
NetClientList, NetLast
|
2019-09-11 22:48:29 +00:00
|
|
|
}; /* EWMH atoms */
|
|
|
|
|
2020-06-24 14:36:51 +00:00
|
|
|
enum {
|
|
|
|
WMProtocols,
|
|
|
|
WMDelete,
|
|
|
|
WMState,
|
|
|
|
WMTakeFocus,
|
|
|
|
#if WINDOWROLERULE_PATCH
|
|
|
|
WMWindowRole,
|
|
|
|
#endif // WINDOWROLERULE_PATCH
|
|
|
|
WMLast
|
|
|
|
}; /* default atoms */
|
|
|
|
|
|
|
|
enum {
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUSBUTTON_PATCH
|
2020-06-24 14:36:51 +00:00
|
|
|
ClkButton,
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSBUTTON_PATCH
|
2020-06-24 14:36:51 +00:00
|
|
|
ClkTagBar,
|
|
|
|
ClkLtSymbol,
|
|
|
|
ClkStatusText,
|
|
|
|
ClkWinTitle,
|
|
|
|
ClkClientWin,
|
|
|
|
ClkRootWin,
|
|
|
|
ClkLast
|
|
|
|
}; /* clicks */
|
2019-09-04 22:16:39 +00:00
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
enum {
|
|
|
|
BAR_ALIGN_LEFT,
|
|
|
|
BAR_ALIGN_CENTER,
|
|
|
|
BAR_ALIGN_RIGHT,
|
|
|
|
BAR_ALIGN_LEFT_LEFT,
|
|
|
|
BAR_ALIGN_LEFT_RIGHT,
|
|
|
|
BAR_ALIGN_LEFT_CENTER,
|
|
|
|
BAR_ALIGN_NONE,
|
|
|
|
BAR_ALIGN_RIGHT_LEFT,
|
|
|
|
BAR_ALIGN_RIGHT_RIGHT,
|
|
|
|
BAR_ALIGN_RIGHT_CENTER,
|
|
|
|
BAR_ALIGN_LAST
|
|
|
|
}; /* bar alignment */
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
typedef union {
|
|
|
|
int i;
|
|
|
|
unsigned int ui;
|
|
|
|
float f;
|
|
|
|
const void *v;
|
|
|
|
} Arg;
|
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
typedef struct Bar Bar;
|
|
|
|
struct Bar {
|
|
|
|
Window win;
|
|
|
|
int bx, by, bw, bh; /* bar geometry */
|
|
|
|
int w[BARRULES]; // width, array length == barrules, then use r index for lookup purposes
|
|
|
|
int x[BARRULES]; // x position, array length == ^
|
|
|
|
};
|
|
|
|
|
2020-07-15 12:10:47 +00:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int max_width;
|
|
|
|
} BarWidthArg;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int x;
|
|
|
|
int w;
|
|
|
|
} BarDrawArg;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int rel_x;
|
|
|
|
int rel_y;
|
|
|
|
int rel_w;
|
|
|
|
int rel_h;
|
|
|
|
} BarClickArg;
|
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
typedef struct Monitor Monitor;
|
|
|
|
typedef struct {
|
|
|
|
int monitor;
|
|
|
|
int bar;
|
|
|
|
int alignment; // see bar alignment enum
|
2020-07-15 12:10:47 +00:00
|
|
|
int (*widthfunc)(Monitor *m, BarWidthArg *a);
|
|
|
|
int (*drawfunc)(Monitor *m, BarDrawArg *a);
|
|
|
|
int (*clickfunc)(Monitor *m, Arg *arg, BarClickArg *a);
|
2020-07-15 06:57:30 +00:00
|
|
|
char *name; // for debugging
|
|
|
|
int x, w; // position, width for internal use
|
|
|
|
} BarRule;
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
typedef struct {
|
|
|
|
unsigned int click;
|
|
|
|
unsigned int mask;
|
|
|
|
unsigned int button;
|
|
|
|
void (*func)(const Arg *arg);
|
|
|
|
const Arg arg;
|
|
|
|
} Button;
|
|
|
|
|
|
|
|
typedef struct Client Client;
|
|
|
|
struct Client {
|
|
|
|
char name[256];
|
|
|
|
float mina, maxa;
|
2019-09-08 22:18:47 +00:00
|
|
|
#if CFACTS_PATCH
|
|
|
|
float cfact;
|
|
|
|
#endif // CFACTS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
int x, y, w, h;
|
2019-10-24 06:47:00 +00:00
|
|
|
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
|
2019-09-07 21:08:53 +00:00
|
|
|
int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */
|
2019-10-24 06:47:00 +00:00
|
|
|
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
int oldx, oldy, oldw, oldh;
|
|
|
|
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
|
|
|
|
int bw, oldbw;
|
|
|
|
unsigned int tags;
|
2019-11-26 19:23:58 +00:00
|
|
|
#if SWITCHTAG_PATCH
|
|
|
|
unsigned int switchtag;
|
|
|
|
#endif // SWITCHTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
|
2020-03-20 15:45:20 +00:00
|
|
|
#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH
|
2019-11-21 11:15:16 +00:00
|
|
|
int fakefullscreen;
|
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
2019-10-24 06:47:00 +00:00
|
|
|
#if EXRESIZE_PATCH
|
|
|
|
unsigned char expandmask;
|
|
|
|
int expandx1, expandy1, expandx2, expandy2;
|
|
|
|
#if !MAXIMIZE_PATCH
|
|
|
|
int wasfloating;
|
|
|
|
#endif // MAXIMIZE_PATCH
|
|
|
|
#endif // EXRESIZE_PATCH
|
2019-10-04 20:46:47 +00:00
|
|
|
#if MAXIMIZE_PATCH
|
|
|
|
int ismax, wasfloating;
|
|
|
|
#endif // MAXIMIZE_PATCH
|
2019-09-12 22:06:54 +00:00
|
|
|
#if AUTORESIZE_PATCH
|
|
|
|
int needresize;
|
|
|
|
#endif // AUTORESIZE_PATCH
|
2019-09-07 22:23:30 +00:00
|
|
|
#if CENTER_PATCH
|
|
|
|
int iscentered;
|
|
|
|
#endif // CENTER_PATCH
|
2019-10-22 16:30:00 +00:00
|
|
|
#if ISPERMANENT_PATCH
|
|
|
|
int ispermanent;
|
|
|
|
#endif // ISPERMANENT_PATCH
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
int isterminal, noswallow;
|
|
|
|
pid_t pid;
|
|
|
|
#endif // SWALLOW_PATCH
|
2019-09-14 22:43:35 +00:00
|
|
|
#if STICKY_PATCH
|
|
|
|
int issticky;
|
|
|
|
#endif // STICKY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
Client *next;
|
|
|
|
Client *snext;
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
Client *swallowing;
|
|
|
|
#endif // SWALLOW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
Monitor *mon;
|
|
|
|
Window win;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
unsigned int mod;
|
|
|
|
KeySym keysym;
|
|
|
|
void (*func)(const Arg *);
|
|
|
|
const Arg arg;
|
|
|
|
} Key;
|
|
|
|
|
2019-09-30 21:52:51 +00:00
|
|
|
#if FLEXTILE_DELUXE_LAYOUT
|
|
|
|
typedef struct {
|
|
|
|
int nmaster;
|
|
|
|
int nstack;
|
|
|
|
int layout;
|
|
|
|
int masteraxis; // master stack area
|
|
|
|
int stack1axis; // primary stack area
|
|
|
|
int stack2axis; // secondary stack area, e.g. centered master
|
|
|
|
void (*symbolfunc)(Monitor *, unsigned int);
|
|
|
|
} LayoutPreset;
|
|
|
|
#endif // FLEXTILE_DELUXE_LAYOUT
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
typedef struct {
|
|
|
|
const char *symbol;
|
|
|
|
void (*arrange)(Monitor *);
|
2019-09-30 21:52:51 +00:00
|
|
|
#if FLEXTILE_DELUXE_LAYOUT
|
|
|
|
LayoutPreset preset;
|
|
|
|
#endif // FLEXTILE_DELUXE_LAYOUT
|
2019-09-04 22:16:39 +00:00
|
|
|
} Layout;
|
|
|
|
|
2019-09-05 20:58:16 +00:00
|
|
|
#if PERTAG_PATCH
|
|
|
|
typedef struct Pertag Pertag;
|
|
|
|
#endif // PERTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
struct Monitor {
|
|
|
|
char ltsymbol[16];
|
|
|
|
float mfact;
|
2019-09-30 21:52:51 +00:00
|
|
|
#if FLEXTILE_DELUXE_LAYOUT
|
|
|
|
int ltaxis[4];
|
|
|
|
int nstack;
|
|
|
|
#endif // FLEXTILE_DELUXE_LAYOUT
|
2019-09-04 22:16:39 +00:00
|
|
|
int nmaster;
|
|
|
|
int num;
|
|
|
|
int mx, my, mw, mh; /* screen size */
|
|
|
|
int wx, wy, ww, wh; /* window area */
|
2019-09-08 22:18:47 +00:00
|
|
|
#if VANITYGAPS_PATCH
|
|
|
|
int gappih; /* horizontal gap between windows */
|
|
|
|
int gappiv; /* vertical gap between windows */
|
|
|
|
int gappoh; /* horizontal outer gaps */
|
|
|
|
int gappov; /* vertical outer gaps */
|
|
|
|
#endif // VANITYGAPS_PATCH
|
2019-09-14 21:28:04 +00:00
|
|
|
#if SETBORDERPX_PATCH
|
|
|
|
unsigned int borderpx;
|
|
|
|
#endif // SETBORDERPX_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
unsigned int seltags;
|
|
|
|
unsigned int sellt;
|
|
|
|
unsigned int tagset[2];
|
|
|
|
int showbar;
|
|
|
|
int topbar;
|
|
|
|
Client *clients;
|
|
|
|
Client *sel;
|
|
|
|
Client *stack;
|
|
|
|
Monitor *next;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EXTRABAR_PATCH
|
|
|
|
Bar *bars[2];
|
|
|
|
#else
|
|
|
|
Bar *bars[1];
|
|
|
|
#endif // BAR_EXTRABAR_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
const Layout *lt[2];
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_ALTERNATIVE_TAGS_PATCH
|
2019-09-09 21:27:10 +00:00
|
|
|
unsigned int alttag;
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_ALTERNATIVE_TAGS_PATCH
|
2019-09-05 20:58:16 +00:00
|
|
|
#if PERTAG_PATCH
|
|
|
|
Pertag *pertag;
|
|
|
|
#endif // PERTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
const char *class;
|
2019-09-07 21:46:08 +00:00
|
|
|
#if WINDOWROLERULE_PATCH
|
|
|
|
const char *role;
|
|
|
|
#endif // WINDOWROLERULE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
const char *instance;
|
|
|
|
const char *title;
|
2020-06-15 11:24:23 +00:00
|
|
|
const char *wintype;
|
2019-09-04 22:16:39 +00:00
|
|
|
unsigned int tags;
|
2019-09-07 22:23:30 +00:00
|
|
|
#if SWITCHTAG_PATCH
|
|
|
|
int switchtag;
|
|
|
|
#endif // SWITCHTAG_PATCH
|
|
|
|
#if CENTER_PATCH
|
|
|
|
int iscentered;
|
|
|
|
#endif // CENTER_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
int isfloating;
|
2019-10-22 16:30:00 +00:00
|
|
|
#if ISPERMANENT_PATCH
|
|
|
|
int ispermanent;
|
|
|
|
#endif // ISPERMANENT_PATCH
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
int isterminal;
|
|
|
|
int noswallow;
|
|
|
|
#endif // SWALLOW_PATCH
|
2020-06-21 13:33:29 +00:00
|
|
|
#if FLOATPOS_PATCH
|
|
|
|
const char *floatpos;
|
|
|
|
#endif // FLOATPOS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
int monitor;
|
|
|
|
} Rule;
|
|
|
|
|
2020-06-15 13:34:44 +00:00
|
|
|
#define RULE(...) { .monitor = -1, ##__VA_ARGS__ },
|
2020-06-14 13:52:47 +00:00
|
|
|
|
2020-06-15 13:34:44 +00:00
|
|
|
/* Cross patch compatibility rule macro helper macros */
|
|
|
|
#define FLOATING , .isfloating = 1
|
|
|
|
#if CENTER_PATCH
|
|
|
|
#define CENTERED , .iscentered = 1
|
|
|
|
#else
|
|
|
|
#define CENTERED
|
|
|
|
#endif // CENTER_PATCH
|
|
|
|
#if ISPERMANENT_PATCH
|
|
|
|
#define PERMANENT , .ispermanent = 1
|
|
|
|
#else
|
|
|
|
#define PERMANENT
|
|
|
|
#endif // ISPERMANENT_PATCH
|
|
|
|
#if SWALLOW_PATCH
|
|
|
|
#define NOSWALLOW , .noswallow = 1
|
|
|
|
#define TERMINAL , .isterminal = 1
|
|
|
|
#else
|
|
|
|
#define NOSWALLOW
|
|
|
|
#define TERMINAL
|
|
|
|
#endif // SWALLOW_PATCH
|
|
|
|
#if SWITCHTAG_PATCH
|
|
|
|
#define SWITCHTAG , .switchtag = 1
|
|
|
|
#else
|
|
|
|
#define SWITCHTAG
|
|
|
|
#endif // SWITCHTAG_PATCH
|
2020-06-14 13:52:47 +00:00
|
|
|
|
2019-09-11 06:28:00 +00:00
|
|
|
#if MONITOR_RULES_PATCH
|
|
|
|
typedef struct {
|
|
|
|
int monitor;
|
2019-09-30 21:52:51 +00:00
|
|
|
#if PERTAG_PATCH
|
|
|
|
int tag;
|
|
|
|
#endif // PERTAG_PATCH
|
2019-09-11 06:28:00 +00:00
|
|
|
int layout;
|
2019-09-30 21:52:51 +00:00
|
|
|
float mfact;
|
2020-04-26 14:26:36 +00:00
|
|
|
int nmaster;
|
|
|
|
int showbar;
|
|
|
|
int topbar;
|
2019-09-11 06:28:00 +00:00
|
|
|
} MonitorRule;
|
|
|
|
#endif // MONITOR_RULES_PATCH
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
/* function declarations */
|
|
|
|
static void applyrules(Client *c);
|
|
|
|
static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
|
|
|
|
static void arrange(Monitor *m);
|
|
|
|
static void arrangemon(Monitor *m);
|
|
|
|
static void attach(Client *c);
|
|
|
|
static void attachstack(Client *c);
|
|
|
|
static void buttonpress(XEvent *e);
|
|
|
|
static void checkotherwm(void);
|
|
|
|
static void cleanup(void);
|
|
|
|
static void cleanupmon(Monitor *mon);
|
|
|
|
static void clientmessage(XEvent *e);
|
|
|
|
static void configure(Client *c);
|
|
|
|
static void configurenotify(XEvent *e);
|
|
|
|
static void configurerequest(XEvent *e);
|
|
|
|
static Monitor *createmon(void);
|
|
|
|
static void destroynotify(XEvent *e);
|
|
|
|
static void detach(Client *c);
|
|
|
|
static void detachstack(Client *c);
|
|
|
|
static Monitor *dirtomon(int dir);
|
|
|
|
static void drawbar(Monitor *m);
|
|
|
|
static void drawbars(void);
|
2019-09-15 22:32:28 +00:00
|
|
|
#if !FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static void enternotify(XEvent *e);
|
2019-09-15 22:32:28 +00:00
|
|
|
#endif // FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static void expose(XEvent *e);
|
|
|
|
static void focus(Client *c);
|
|
|
|
static void focusin(XEvent *e);
|
|
|
|
static void focusmon(const Arg *arg);
|
2020-03-23 11:15:50 +00:00
|
|
|
#if !STACKER_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static void focusstack(const Arg *arg);
|
2020-03-23 11:15:50 +00:00
|
|
|
#endif // STACKER_PATCH
|
2020-04-23 06:00:22 +00:00
|
|
|
static Atom getatomprop(Client *c, Atom prop);
|
2019-09-04 22:16:39 +00:00
|
|
|
static int getrootptr(int *x, int *y);
|
|
|
|
static long getstate(Window w);
|
|
|
|
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
|
|
|
|
static void grabbuttons(Client *c, int focused);
|
2020-05-31 13:14:29 +00:00
|
|
|
#if KEYMODES_PATCH
|
|
|
|
static void grabdefkeys(void);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
static void grabkeys(void);
|
2020-05-31 13:14:29 +00:00
|
|
|
#endif // KEYMODES_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static void incnmaster(const Arg *arg);
|
2020-05-31 13:14:29 +00:00
|
|
|
#if KEYMODES_PATCH
|
|
|
|
static void keydefpress(XEvent *e);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
static void keypress(XEvent *e);
|
2020-05-31 13:14:29 +00:00
|
|
|
#endif // KEYMODES_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static void killclient(const Arg *arg);
|
|
|
|
static void manage(Window w, XWindowAttributes *wa);
|
|
|
|
static void mappingnotify(XEvent *e);
|
|
|
|
static void maprequest(XEvent *e);
|
2019-09-15 22:32:28 +00:00
|
|
|
#if !FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static void motionnotify(XEvent *e);
|
2019-09-15 22:32:28 +00:00
|
|
|
#endif // FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static void movemouse(const Arg *arg);
|
|
|
|
static Client *nexttiled(Client *c);
|
2019-10-06 21:43:51 +00:00
|
|
|
#if !ZOOMSWAP_PATCH || TAGINTOSTACK_ALLMASTER_PATCH || TAGINTOSTACK_ONEMASTER_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static void pop(Client *);
|
2019-10-06 21:43:51 +00:00
|
|
|
#endif // !ZOOMSWAP_PATCH / TAGINTOSTACK_ALLMASTER_PATCH / TAGINTOSTACK_ONEMASTER_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static void propertynotify(XEvent *e);
|
|
|
|
static void quit(const Arg *arg);
|
|
|
|
static Monitor *recttomon(int x, int y, int w, int h);
|
|
|
|
static void resize(Client *c, int x, int y, int w, int h, int interact);
|
|
|
|
static void resizeclient(Client *c, int x, int y, int w, int h);
|
|
|
|
static void resizemouse(const Arg *arg);
|
|
|
|
static void restack(Monitor *m);
|
|
|
|
static void run(void);
|
|
|
|
static void scan(void);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
static int sendevent(Window w, Atom proto, int m, long d0, long d1, long d2, long d3, long d4);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
static int sendevent(Client *c, Atom proto);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static void sendmon(Client *c, Monitor *m);
|
|
|
|
static void setclientstate(Client *c, long state);
|
|
|
|
static void setfocus(Client *c);
|
|
|
|
static void setfullscreen(Client *c, int fullscreen);
|
|
|
|
static void setlayout(const Arg *arg);
|
|
|
|
static void setmfact(const Arg *arg);
|
|
|
|
static void setup(void);
|
|
|
|
static void seturgent(Client *c, int urg);
|
|
|
|
static void showhide(Client *c);
|
|
|
|
static void sigchld(int unused);
|
|
|
|
static void spawn(const Arg *arg);
|
|
|
|
static void tag(const Arg *arg);
|
|
|
|
static void tagmon(const Arg *arg);
|
|
|
|
static void togglebar(const Arg *arg);
|
|
|
|
static void togglefloating(const Arg *arg);
|
|
|
|
static void toggletag(const Arg *arg);
|
|
|
|
static void toggleview(const Arg *arg);
|
|
|
|
static void unfocus(Client *c, int setfocus);
|
|
|
|
static void unmanage(Client *c, int destroyed);
|
|
|
|
static void unmapnotify(XEvent *e);
|
|
|
|
static void updatebarpos(Monitor *m);
|
|
|
|
static void updatebars(void);
|
|
|
|
static void updateclientlist(void);
|
|
|
|
static int updategeom(void);
|
|
|
|
static void updatenumlockmask(void);
|
|
|
|
static void updatesizehints(Client *c);
|
|
|
|
static void updatestatus(void);
|
|
|
|
static void updatetitle(Client *c);
|
|
|
|
static void updatewmhints(Client *c);
|
|
|
|
static void view(const Arg *arg);
|
|
|
|
static Client *wintoclient(Window w);
|
|
|
|
static Monitor *wintomon(Window w);
|
|
|
|
static int xerror(Display *dpy, XErrorEvent *ee);
|
|
|
|
static int xerrordummy(Display *dpy, XErrorEvent *ee);
|
|
|
|
static int xerrorstart(Display *dpy, XErrorEvent *ee);
|
|
|
|
static void zoom(const Arg *arg);
|
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
/* bar functions */
|
|
|
|
|
2019-09-05 20:10:00 +00:00
|
|
|
#include "patch/include.h"
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
/* variables */
|
|
|
|
static const char broken[] = "broken";
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_PANGO_PATCH || BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH
|
2020-05-26 18:53:53 +00:00
|
|
|
static char stext[1024];
|
|
|
|
#else
|
2020-07-07 16:25:00 +00:00
|
|
|
static char stext[512];
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUS2D_PATCH
|
2020-07-15 12:10:47 +00:00
|
|
|
#if BAR_EXTRABAR_PATCH || BAR_STATUSCMD_PATCH
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUS2D_PATCH
|
2020-07-05 19:53:36 +00:00
|
|
|
static char rawstext[1024];
|
|
|
|
#else
|
|
|
|
static char rawstext[512];
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUS2D_PATCH
|
2020-07-15 12:10:47 +00:00
|
|
|
#endif // BAR_EXTRABAR_PATCH | BAR_STATUSCMD_PATCH
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EXTRABAR_PATCH
|
|
|
|
#if BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH
|
2020-05-26 18:53:53 +00:00
|
|
|
static char estext[1024];
|
|
|
|
#else
|
2020-07-07 16:25:00 +00:00
|
|
|
static char estext[512];
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUS2D_PATCH
|
|
|
|
#if BAR_STATUSCMD_PATCH
|
2020-07-05 19:53:36 +00:00
|
|
|
static char rawestext[1024];
|
|
|
|
#else
|
|
|
|
static char rawestext[512];
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSCMD_PATCH
|
|
|
|
#endif // BAR_EXTRABAR_PATCH
|
2020-07-05 19:53:36 +00:00
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
static int screen;
|
|
|
|
static int sw, sh; /* X display screen geometry width, height */
|
2020-07-15 06:57:30 +00:00
|
|
|
static int bh; /* bar geometry */
|
2019-09-04 22:16:39 +00:00
|
|
|
static int lrpad; /* sum of left and right padding for text */
|
|
|
|
static int (*xerrorxlib)(Display *, XErrorEvent *);
|
|
|
|
static unsigned int numlockmask = 0;
|
|
|
|
static void (*handler[LASTEvent]) (XEvent *) = {
|
|
|
|
[ButtonPress] = buttonpress,
|
2020-07-15 06:57:30 +00:00
|
|
|
#if COMBO_PATCH || BAR_HOLDBAR_PATCH
|
2019-09-11 21:35:43 +00:00
|
|
|
[ButtonRelease] = keyrelease,
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // COMBO_PATCH / BAR_HOLDBAR_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
[ClientMessage] = clientmessage,
|
|
|
|
[ConfigureRequest] = configurerequest,
|
|
|
|
[ConfigureNotify] = configurenotify,
|
|
|
|
[DestroyNotify] = destroynotify,
|
2019-09-15 22:32:28 +00:00
|
|
|
#if !FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
[EnterNotify] = enternotify,
|
2019-09-15 22:32:28 +00:00
|
|
|
#endif // FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
[Expose] = expose,
|
|
|
|
[FocusIn] = focusin,
|
|
|
|
[KeyPress] = keypress,
|
2020-07-15 06:57:30 +00:00
|
|
|
#if COMBO_PATCH || BAR_HOLDBAR_PATCH
|
2019-09-11 21:35:43 +00:00
|
|
|
[KeyRelease] = keyrelease,
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // COMBO_PATCH / BAR_HOLDBAR_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
[MappingNotify] = mappingnotify,
|
|
|
|
[MapRequest] = maprequest,
|
2019-09-15 22:32:28 +00:00
|
|
|
#if !FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
[MotionNotify] = motionnotify,
|
2019-09-15 22:32:28 +00:00
|
|
|
#endif // FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
[PropertyNotify] = propertynotify,
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
[ResizeRequest] = resizerequest,
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
[UnmapNotify] = unmapnotify
|
|
|
|
};
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
static Atom wmatom[WMLast], netatom[NetLast];
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static int running = 1;
|
|
|
|
static Cur *cursor[CurLast];
|
|
|
|
static Clr **scheme;
|
|
|
|
static Display *dpy;
|
|
|
|
static Drw *drw;
|
|
|
|
static Monitor *mons, *selmon;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATICSTATUS_PATCH && !BAR_STATUSALLMONS_PATCH
|
2020-06-10 09:52:35 +00:00
|
|
|
static Monitor *statmon;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EXTRABAR_PATCH
|
2020-07-08 12:13:29 +00:00
|
|
|
static Monitor *statebmon;
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EXTRABAR_PATCH
|
|
|
|
#endif // BAR_STATICSTATUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
static Window root, wmcheckwin;
|
|
|
|
|
|
|
|
/* configuration, allows nested code to access above variables */
|
|
|
|
#include "config.h"
|
|
|
|
|
2019-09-04 22:32:39 +00:00
|
|
|
#include "patch/include.c"
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
/* compile-time check if all tags fit into an unsigned int bit array. */
|
2020-06-05 07:43:27 +00:00
|
|
|
#if SCRATCHPAD_ALT_1_PATCH
|
|
|
|
struct NumTags { char limitexceeded[LENGTH(tags) > 30 ? -1 : 1]; };
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
|
2020-06-05 07:43:27 +00:00
|
|
|
#endif // SCRATCHPAD_ALT_1_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
/* function implementations */
|
|
|
|
void
|
|
|
|
applyrules(Client *c)
|
|
|
|
{
|
|
|
|
const char *class, *instance;
|
2020-06-15 11:24:23 +00:00
|
|
|
Atom wintype;
|
2019-09-07 21:46:08 +00:00
|
|
|
#if WINDOWROLERULE_PATCH
|
|
|
|
char role[64];
|
|
|
|
#endif // WINDOWROLERULE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
unsigned int i;
|
2020-07-03 11:30:21 +00:00
|
|
|
#if SWITCHTAG_PATCH
|
|
|
|
unsigned int newtagset;
|
|
|
|
#endif // SWITCHTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
const Rule *r;
|
|
|
|
Monitor *m;
|
|
|
|
XClassHint ch = { NULL, NULL };
|
|
|
|
|
|
|
|
/* rule matching */
|
|
|
|
c->isfloating = 0;
|
|
|
|
c->tags = 0;
|
|
|
|
XGetClassHint(dpy, c->win, &ch);
|
|
|
|
class = ch.res_class ? ch.res_class : broken;
|
|
|
|
instance = ch.res_name ? ch.res_name : broken;
|
2020-06-15 11:24:23 +00:00
|
|
|
wintype = getatomprop(c, netatom[NetWMWindowType]);
|
2019-09-07 21:46:08 +00:00
|
|
|
#if WINDOWROLERULE_PATCH
|
|
|
|
gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role));
|
|
|
|
#endif // WINDOWROLERULE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
for (i = 0; i < LENGTH(rules); i++) {
|
|
|
|
r = &rules[i];
|
|
|
|
if ((!r->title || strstr(c->name, r->title))
|
|
|
|
&& (!r->class || strstr(class, r->class))
|
2019-09-07 21:46:08 +00:00
|
|
|
#if WINDOWROLERULE_PATCH
|
|
|
|
&& (!r->role || strstr(role, r->role))
|
|
|
|
#endif // WINDOWROLERULE_PATCH
|
2020-06-15 11:24:23 +00:00
|
|
|
&& (!r->instance || strstr(instance, r->instance))
|
|
|
|
&& (!r->wintype || wintype == XInternAtom(dpy, r->wintype, False)))
|
2019-09-04 22:16:39 +00:00
|
|
|
{
|
2019-09-07 22:23:30 +00:00
|
|
|
#if CENTER_PATCH
|
|
|
|
c->iscentered = r->iscentered;
|
|
|
|
#endif // CENTER_PATCH
|
2019-10-22 16:30:00 +00:00
|
|
|
#if ISPERMANENT_PATCH
|
|
|
|
c->ispermanent = r->ispermanent;
|
|
|
|
#endif // ISPERMANENT_PATCH
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
c->isterminal = r->isterminal;
|
|
|
|
c->noswallow = r->noswallow;
|
|
|
|
#endif // SWALLOW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
c->isfloating = r->isfloating;
|
|
|
|
c->tags |= r->tags;
|
2020-06-05 09:23:22 +00:00
|
|
|
#if SCRATCHPADS_PATCH && !SCRATCHPAD_KEEP_POSITION_AND_SIZE_PATCH
|
[dwm][PATCH] Multiple scratchpads
This patch enables multiple scratchpads, each with one assigned window.
This enables the same scratchpad workflow that you have in i3.
Scratchpads are implemented as special tags, whose mask does not
apply to new spawned windows. To assign a window to a scratchpad you
have to set up a rule, as you do with regular tags.
Windows tagged with scratchpad tags can be set floating or not in the
rules array. Most users would probably want them floating (i3 style),
but having them tiled does also perfectly work and might fit better the
DWM approach. In case they are set floating, the patch moves them to the
center of the screen whenever the are shown. The patch can easily be
modified to make this last feature configurable in the rules array (see
the center patch).
The togglescratch function, borrowed from the previous scratchpad patch
and slightly modified, can be used to spawn a registered scratchpad
process or toggle its view. This function looks for a window tagged on
the selected scratchpad. If it is found its view is toggled. If it is
not found the corresponding registered command is spawned. The
config.def.h shows three examples of its use to spawn a terminal in the
first scratchpad tag, a second terminal running ranger on the second
scratchpad tag and the keepassxc application to manage passwords on a
third scratchpad tag.
If you prefer to spawn your scratchpad applications from the startup
script, you might opt for binding keys to toggleview instead, as
scratchpads are just special tags (you may even extend the TAGKEYS macro
to generalize the key bindings).
2020-04-16 14:39:22 +00:00
|
|
|
if ((r->tags & SPTAGMASK) && r->isfloating) {
|
|
|
|
c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
|
|
|
|
c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
|
|
|
|
}
|
2020-06-05 09:23:22 +00:00
|
|
|
#endif // SCRATCHPADS_PATCH | SCRATCHPAD_KEEP_POSITION_AND_SIZE_PATCH
|
2020-06-23 09:55:55 +00:00
|
|
|
for (m = mons; m && m->num != r->monitor; m = m->next);
|
|
|
|
if (m)
|
|
|
|
c->mon = m;
|
2020-06-21 13:33:29 +00:00
|
|
|
#if FLOATPOS_PATCH
|
|
|
|
if (c->isfloating && r->floatpos)
|
|
|
|
setfloatpos(c, r->floatpos);
|
|
|
|
#endif // FLOATPOS_PATCH
|
|
|
|
|
2019-09-07 22:23:30 +00:00
|
|
|
#if SWITCHTAG_PATCH
|
2020-04-23 15:19:17 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
if (r->switchtag && (c->noswallow || !termforwin(c)))
|
|
|
|
#else
|
|
|
|
if (r->switchtag)
|
|
|
|
#endif // SWALLOW_PATCH
|
|
|
|
{
|
2020-07-03 11:30:21 +00:00
|
|
|
selmon = c->mon;
|
|
|
|
if (r->switchtag == 2 || r->switchtag == 4)
|
2019-09-07 22:23:30 +00:00
|
|
|
newtagset = c->mon->tagset[c->mon->seltags] ^ c->tags;
|
|
|
|
else
|
|
|
|
newtagset = c->tags;
|
|
|
|
|
2020-07-02 08:09:24 +00:00
|
|
|
/* Switch to the client's tag, but only if that tag is not already shown */
|
2020-07-03 11:30:21 +00:00
|
|
|
if (newtagset && !(c->tags & c->mon->tagset[c->mon->seltags])) {
|
|
|
|
if (r->switchtag == 3 || r->switchtag == 4)
|
|
|
|
c->switchtag = c->mon->tagset[c->mon->seltags];
|
|
|
|
if (r->switchtag == 1 || r->switchtag == 3) {
|
2019-11-26 19:23:58 +00:00
|
|
|
#if PERTAG_PATCH
|
2019-09-30 21:52:51 +00:00
|
|
|
pertagview(&((Arg) { .ui = newtagset }));
|
2020-07-03 11:30:21 +00:00
|
|
|
arrange(c->mon);
|
2019-11-26 19:23:58 +00:00
|
|
|
#else
|
|
|
|
view(&((Arg) { .ui = newtagset }));
|
|
|
|
#endif // PERTAG_PATCH
|
2020-07-03 13:57:14 +00:00
|
|
|
} else {
|
|
|
|
c->mon->tagset[c->mon->seltags] = newtagset;
|
2020-07-03 11:30:21 +00:00
|
|
|
arrange(c->mon);
|
2020-07-03 13:57:14 +00:00
|
|
|
}
|
2019-09-07 22:23:30 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // SWITCHTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
}
|
2020-04-23 11:16:13 +00:00
|
|
|
if (ch.res_class)
|
|
|
|
XFree(ch.res_class);
|
|
|
|
if (ch.res_name)
|
|
|
|
XFree(ch.res_name);
|
2019-10-02 21:22:04 +00:00
|
|
|
#if EMPTYVIEW_PATCH
|
2020-04-23 11:16:13 +00:00
|
|
|
if (c->tags & TAGMASK) c->tags = c->tags & TAGMASK;
|
2020-06-05 09:23:22 +00:00
|
|
|
#if SCRATCHPADS_PATCH
|
2020-04-23 11:16:13 +00:00
|
|
|
else if (c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags] & ~SPTAGMASK;
|
2020-06-05 07:43:27 +00:00
|
|
|
#elif SCRATCHPAD_ALT_1_PATCH
|
|
|
|
else if (c->tags != SCRATCHPAD_MASK && c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags];
|
[dwm][PATCH] Multiple scratchpads
This patch enables multiple scratchpads, each with one assigned window.
This enables the same scratchpad workflow that you have in i3.
Scratchpads are implemented as special tags, whose mask does not
apply to new spawned windows. To assign a window to a scratchpad you
have to set up a rule, as you do with regular tags.
Windows tagged with scratchpad tags can be set floating or not in the
rules array. Most users would probably want them floating (i3 style),
but having them tiled does also perfectly work and might fit better the
DWM approach. In case they are set floating, the patch moves them to the
center of the screen whenever the are shown. The patch can easily be
modified to make this last feature configurable in the rules array (see
the center patch).
The togglescratch function, borrowed from the previous scratchpad patch
and slightly modified, can be used to spawn a registered scratchpad
process or toggle its view. This function looks for a window tagged on
the selected scratchpad. If it is found its view is toggled. If it is
not found the corresponding registered command is spawned. The
config.def.h shows three examples of its use to spawn a terminal in the
first scratchpad tag, a second terminal running ranger on the second
scratchpad tag and the keepassxc application to manage passwords on a
third scratchpad tag.
If you prefer to spawn your scratchpad applications from the startup
script, you might opt for binding keys to toggleview instead, as
scratchpads are just special tags (you may even extend the TAGKEYS macro
to generalize the key bindings).
2020-04-16 14:39:22 +00:00
|
|
|
#else
|
2020-04-23 11:16:13 +00:00
|
|
|
else if (c->mon->tagset[c->mon->seltags]) c->tags = c->mon->tagset[c->mon->seltags];
|
2020-06-05 09:23:22 +00:00
|
|
|
#endif // SCRATCHPADS_PATCH
|
2020-07-03 11:30:21 +00:00
|
|
|
else c->tags = 1;
|
2020-06-05 09:23:22 +00:00
|
|
|
#elif SCRATCHPADS_PATCH
|
[dwm][PATCH] Multiple scratchpads
This patch enables multiple scratchpads, each with one assigned window.
This enables the same scratchpad workflow that you have in i3.
Scratchpads are implemented as special tags, whose mask does not
apply to new spawned windows. To assign a window to a scratchpad you
have to set up a rule, as you do with regular tags.
Windows tagged with scratchpad tags can be set floating or not in the
rules array. Most users would probably want them floating (i3 style),
but having them tiled does also perfectly work and might fit better the
DWM approach. In case they are set floating, the patch moves them to the
center of the screen whenever the are shown. The patch can easily be
modified to make this last feature configurable in the rules array (see
the center patch).
The togglescratch function, borrowed from the previous scratchpad patch
and slightly modified, can be used to spawn a registered scratchpad
process or toggle its view. This function looks for a window tagged on
the selected scratchpad. If it is found its view is toggled. If it is
not found the corresponding registered command is spawned. The
config.def.h shows three examples of its use to spawn a terminal in the
first scratchpad tag, a second terminal running ranger on the second
scratchpad tag and the keepassxc application to manage passwords on a
third scratchpad tag.
If you prefer to spawn your scratchpad applications from the startup
script, you might opt for binding keys to toggleview instead, as
scratchpads are just special tags (you may even extend the TAGKEYS macro
to generalize the key bindings).
2020-04-16 14:39:22 +00:00
|
|
|
c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : (c->mon->tagset[c->mon->seltags] & ~SPTAGMASK);
|
2020-06-05 07:43:27 +00:00
|
|
|
#elif SCRATCHPAD_ALT_1_PATCH
|
|
|
|
if (c->tags != SCRATCHPAD_MASK)
|
|
|
|
c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
|
2019-10-02 21:22:04 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
c->tags = c->tags & TAGMASK ? c->tags & TAGMASK : c->mon->tagset[c->mon->seltags];
|
2019-10-02 21:22:04 +00:00
|
|
|
#endif // EMPTYVIEW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
|
|
|
|
{
|
|
|
|
int baseismin;
|
|
|
|
Monitor *m = c->mon;
|
|
|
|
|
|
|
|
/* set minimum possible */
|
|
|
|
*w = MAX(1, *w);
|
|
|
|
*h = MAX(1, *h);
|
|
|
|
if (interact) {
|
|
|
|
if (*x > sw)
|
|
|
|
*x = sw - WIDTH(c);
|
|
|
|
if (*y > sh)
|
|
|
|
*y = sh - HEIGHT(c);
|
|
|
|
if (*x + *w + 2 * c->bw < 0)
|
|
|
|
*x = 0;
|
|
|
|
if (*y + *h + 2 * c->bw < 0)
|
|
|
|
*y = 0;
|
|
|
|
} else {
|
|
|
|
if (*x >= m->wx + m->ww)
|
|
|
|
*x = m->wx + m->ww - WIDTH(c);
|
|
|
|
if (*y >= m->wy + m->wh)
|
|
|
|
*y = m->wy + m->wh - HEIGHT(c);
|
|
|
|
if (*x + *w + 2 * c->bw <= m->wx)
|
|
|
|
*x = m->wx;
|
|
|
|
if (*y + *h + 2 * c->bw <= m->wy)
|
|
|
|
*y = m->wy;
|
|
|
|
}
|
|
|
|
if (*h < bh)
|
|
|
|
*h = bh;
|
|
|
|
if (*w < bh)
|
|
|
|
*w = bh;
|
|
|
|
if (resizehints || c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) {
|
|
|
|
/* see last two sentences in ICCCM 4.1.2.3 */
|
|
|
|
baseismin = c->basew == c->minw && c->baseh == c->minh;
|
|
|
|
if (!baseismin) { /* temporarily remove base dimensions */
|
|
|
|
*w -= c->basew;
|
|
|
|
*h -= c->baseh;
|
|
|
|
}
|
|
|
|
/* adjust for aspect limits */
|
|
|
|
if (c->mina > 0 && c->maxa > 0) {
|
|
|
|
if (c->maxa < (float)*w / *h)
|
|
|
|
*w = *h * c->maxa + 0.5;
|
|
|
|
else if (c->mina < (float)*h / *w)
|
|
|
|
*h = *w * c->mina + 0.5;
|
|
|
|
}
|
|
|
|
if (baseismin) { /* increment calculation requires this */
|
|
|
|
*w -= c->basew;
|
|
|
|
*h -= c->baseh;
|
|
|
|
}
|
|
|
|
/* adjust for increment value */
|
|
|
|
if (c->incw)
|
|
|
|
*w -= *w % c->incw;
|
|
|
|
if (c->inch)
|
|
|
|
*h -= *h % c->inch;
|
|
|
|
/* restore base dimensions */
|
|
|
|
*w = MAX(*w + c->basew, c->minw);
|
|
|
|
*h = MAX(*h + c->baseh, c->minh);
|
|
|
|
if (c->maxw)
|
|
|
|
*w = MIN(*w, c->maxw);
|
|
|
|
if (c->maxh)
|
|
|
|
*h = MIN(*h, c->maxh);
|
|
|
|
}
|
|
|
|
return *x != c->x || *y != c->y || *w != c->w || *h != c->h;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
arrange(Monitor *m)
|
|
|
|
{
|
|
|
|
if (m)
|
|
|
|
showhide(m->stack);
|
|
|
|
else for (m = mons; m; m = m->next)
|
|
|
|
showhide(m->stack);
|
|
|
|
if (m) {
|
|
|
|
arrangemon(m);
|
|
|
|
restack(m);
|
|
|
|
} else for (m = mons; m; m = m->next)
|
|
|
|
arrangemon(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
arrangemon(Monitor *m)
|
|
|
|
{
|
|
|
|
strncpy(m->ltsymbol, m->lt[m->sellt]->symbol, sizeof m->ltsymbol);
|
|
|
|
if (m->lt[m->sellt]->arrange)
|
|
|
|
m->lt[m->sellt]->arrange(m);
|
2020-03-31 06:21:00 +00:00
|
|
|
#if ROUNDED_CORNERS_PATCH
|
|
|
|
Client *c;
|
|
|
|
for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
|
|
|
|
drawroundedcorners(c);
|
|
|
|
#endif // ROUNDED_CORNERS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
attach(Client *c)
|
|
|
|
{
|
|
|
|
c->next = c->mon->clients;
|
|
|
|
c->mon->clients = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
attachstack(Client *c)
|
|
|
|
{
|
|
|
|
c->snext = c->mon->stack;
|
|
|
|
c->mon->stack = c;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
buttonpress(XEvent *e)
|
|
|
|
{
|
2020-07-15 06:57:30 +00:00
|
|
|
int click, i, b, r, mi;
|
2019-09-04 22:16:39 +00:00
|
|
|
Arg arg = {0};
|
|
|
|
Client *c;
|
|
|
|
Monitor *m;
|
|
|
|
XButtonPressedEvent *ev = &e->xbutton;
|
2020-07-15 06:57:30 +00:00
|
|
|
const BarRule *br;
|
2020-07-15 12:10:47 +00:00
|
|
|
BarClickArg carg = { 0, 0, 0, 0 };
|
2020-07-15 06:57:30 +00:00
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
click = ClkRootWin;
|
|
|
|
/* focus monitor if necessary */
|
2019-09-15 22:32:28 +00:00
|
|
|
if ((m = wintomon(ev->window)) && m != selmon
|
|
|
|
#if FOCUSONCLICK_PATCH
|
|
|
|
&& (focusonwheel || (ev->button != Button4 && ev->button != Button5))
|
|
|
|
#endif // FOCUSONCLICK_PATCH
|
|
|
|
) {
|
2019-09-04 22:16:39 +00:00
|
|
|
unfocus(selmon->sel, 1);
|
|
|
|
selmon = m;
|
|
|
|
focus(NULL);
|
|
|
|
}
|
2019-09-09 22:18:46 +00:00
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
for (mi = 0, m = mons; m && m != selmon; m = m->next, mi++); // get the monitor index
|
|
|
|
for (b = 0; b < LENGTH(selmon->bars); b++) {
|
|
|
|
if (ev->window == selmon->bars[b]->win) {
|
|
|
|
for (r = 0; r < LENGTH(barrules); r++) {
|
|
|
|
br = &barrules[r];
|
|
|
|
if (br->bar != b || (br->monitor == 'A' && m != selmon) || (br->monitor != -1 && br->monitor != mi) || br->clickfunc == NULL)
|
|
|
|
continue;
|
|
|
|
if (selmon->bars[b]->x[r] <= ev->x && ev->x <= selmon->bars[b]->x[r] + selmon->bars[b]->w[r]) {
|
2020-07-15 12:10:47 +00:00
|
|
|
carg.rel_x = ev->x - selmon->bars[b]->x[r];
|
|
|
|
carg.rel_y = ev->y;
|
|
|
|
carg.rel_w = selmon->bars[b]->w[r];
|
|
|
|
carg.rel_h = selmon->bars[b]->bh;
|
|
|
|
click = br->clickfunc(m, &arg, &carg);
|
|
|
|
if (click < 0)
|
|
|
|
return;
|
2020-07-15 06:57:30 +00:00
|
|
|
break;
|
2020-07-05 19:53:36 +00:00
|
|
|
}
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
break;
|
2020-07-05 19:53:36 +00:00
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (click == ClkRootWin && (c = wintoclient(ev->window))) {
|
2019-09-15 22:32:28 +00:00
|
|
|
#if FOCUSONCLICK_PATCH
|
|
|
|
if (focusonwheel || (ev->button != Button4 && ev->button != Button5))
|
|
|
|
focus(c);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
focus(c);
|
|
|
|
restack(selmon);
|
2019-09-15 22:32:28 +00:00
|
|
|
#endif // FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
XAllowEvents(dpy, ReplayPointer, CurrentTime);
|
|
|
|
click = ClkClientWin;
|
|
|
|
}
|
2020-07-15 12:10:47 +00:00
|
|
|
|
|
|
|
for (i = 0; i < LENGTH(buttons); i++) {
|
2019-09-04 22:16:39 +00:00
|
|
|
if (click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
|
2020-07-15 12:10:47 +00:00
|
|
|
&& CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_AWESOMEBAR_PATCH
|
2019-09-09 22:18:46 +00:00
|
|
|
buttons[i].func((click == ClkTagBar || click == ClkWinTitle) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
|
2019-09-09 22:18:46 +00:00
|
|
|
#endif
|
2020-07-15 06:57:30 +00:00
|
|
|
}
|
2020-07-15 12:10:47 +00:00
|
|
|
}
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
checkotherwm(void)
|
|
|
|
{
|
|
|
|
xerrorxlib = XSetErrorHandler(xerrorstart);
|
|
|
|
/* this causes an error if some other window manager is running */
|
|
|
|
XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
|
|
|
|
XSync(dpy, False);
|
|
|
|
XSetErrorHandler(xerror);
|
|
|
|
XSync(dpy, False);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cleanup(void)
|
|
|
|
{
|
|
|
|
Arg a = {.ui = ~0};
|
|
|
|
Layout foo = { "", NULL };
|
|
|
|
Monitor *m;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
view(&a);
|
|
|
|
selmon->lt[selmon->sellt] = &foo;
|
|
|
|
for (m = mons; m; m = m->next)
|
|
|
|
while (m->stack)
|
|
|
|
unmanage(m->stack, 0);
|
|
|
|
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
|
|
|
while (mons)
|
|
|
|
cleanupmon(mons);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
if (showsystray) {
|
|
|
|
XUnmapWindow(dpy, systray->win);
|
|
|
|
XDestroyWindow(dpy, systray->win);
|
|
|
|
free(systray);
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
for (i = 0; i < CurLast; i++)
|
|
|
|
drw_cur_free(drw, cursor[i]);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH
|
2020-05-26 18:53:53 +00:00
|
|
|
for (i = 0; i < LENGTH(colors) + 1; i++)
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
for (i = 0; i < LENGTH(colors); i++)
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUS2D_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
free(scheme[i]);
|
2020-01-27 08:15:20 +00:00
|
|
|
free(scheme);
|
2019-09-04 22:16:39 +00:00
|
|
|
XDestroyWindow(dpy, wmcheckwin);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_PANGO_PATCH
|
2020-06-11 17:42:00 +00:00
|
|
|
drw_font_free(drw->font);
|
|
|
|
#else
|
2020-01-27 08:15:20 +00:00
|
|
|
drw_fontset_free(drw->fonts);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_PANGO_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
drw_free(drw);
|
|
|
|
XSync(dpy, False);
|
|
|
|
XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
|
|
|
|
XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cleanupmon(Monitor *mon)
|
|
|
|
{
|
|
|
|
Monitor *m;
|
2020-07-15 06:57:30 +00:00
|
|
|
int b;
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
if (mon == mons)
|
|
|
|
mons = mons->next;
|
|
|
|
else {
|
|
|
|
for (m = mons; m && m->next != mon; m = m->next);
|
|
|
|
m->next = mon->next;
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
for (b = 0; b < LENGTH(mon->bars); b++) {
|
|
|
|
if (mon->bars[b]) {
|
|
|
|
XUnmapWindow(dpy, mon->bars[b]->win);
|
|
|
|
XDestroyWindow(dpy, mon->bars[b]->win);
|
|
|
|
}
|
|
|
|
free(mon->bars[b]);
|
2020-07-07 16:25:00 +00:00
|
|
|
}
|
2019-09-04 22:16:39 +00:00
|
|
|
free(mon);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
clientmessage(XEvent *e)
|
|
|
|
{
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
XWindowAttributes wa;
|
|
|
|
XSetWindowAttributes swa;
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
XClientMessageEvent *cme = &e->xclient;
|
|
|
|
Client *c = wintoclient(cme->window);
|
2019-09-06 22:03:04 +00:00
|
|
|
#if FOCUSONNETACTIVE_PATCH
|
|
|
|
unsigned int i;
|
|
|
|
#endif // FOCUSONNETACTIVE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
if (showsystray && cme->window == systray->win && cme->message_type == netatom[NetSystemTrayOP]) {
|
|
|
|
/* add systray icons */
|
|
|
|
if (cme->data.l[1] == SYSTEM_TRAY_REQUEST_DOCK) {
|
|
|
|
if (!(c = (Client *)calloc(1, sizeof(Client))))
|
|
|
|
die("fatal: could not malloc() %u bytes\n", sizeof(Client));
|
|
|
|
if (!(c->win = cme->data.l[2])) {
|
|
|
|
free(c);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
c->mon = systray->mon;
|
2019-09-05 20:10:00 +00:00
|
|
|
c->next = systray->icons;
|
|
|
|
systray->icons = c;
|
|
|
|
XGetWindowAttributes(dpy, c->win, &wa);
|
|
|
|
c->x = c->oldx = c->y = c->oldy = 0;
|
|
|
|
c->w = c->oldw = wa.width;
|
|
|
|
c->h = c->oldh = wa.height;
|
|
|
|
c->oldbw = wa.border_width;
|
|
|
|
c->bw = 0;
|
|
|
|
c->isfloating = True;
|
|
|
|
/* reuse tags field as mapped status */
|
|
|
|
c->tags = 1;
|
|
|
|
updatesizehints(c);
|
|
|
|
updatesystrayicongeom(c, wa.width, wa.height);
|
|
|
|
XAddToSaveSet(dpy, c->win);
|
|
|
|
XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | ResizeRedirectMask);
|
|
|
|
XReparentWindow(dpy, c->win, systray->win, 0, 0);
|
|
|
|
/* use parents background color */
|
|
|
|
swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
|
|
|
|
XChangeWindowAttributes(dpy, c->win, CWBackPixel, &swa);
|
|
|
|
sendevent(c->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_EMBEDDED_NOTIFY, 0 , systray->win, XEMBED_EMBEDDED_VERSION);
|
|
|
|
XSync(dpy, False);
|
|
|
|
setclientstate(c, NormalState);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!c)
|
|
|
|
return;
|
|
|
|
if (cme->message_type == netatom[NetWMState]) {
|
|
|
|
if (cme->data.l[1] == netatom[NetWMFullscreen]
|
2020-04-03 14:57:19 +00:00
|
|
|
|| cme->data.l[2] == netatom[NetWMFullscreen]) {
|
|
|
|
#if FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
if (c->fakefullscreen)
|
|
|
|
resizeclient(c, c->x, c->y, c->w, c->h);
|
|
|
|
else
|
|
|
|
setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */
|
|
|
|
|| (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */
|
|
|
|
#if !FAKEFULLSCREEN_PATCH
|
|
|
|
&& !c->isfullscreen
|
|
|
|
#endif // !FAKEFULLSCREEN_PATCH
|
|
|
|
)));
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */
|
2019-10-08 21:15:11 +00:00
|
|
|
|| (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */
|
|
|
|
#if !FAKEFULLSCREEN_PATCH
|
|
|
|
&& !c->isfullscreen
|
|
|
|
#endif // !FAKEFULLSCREEN_PATCH
|
|
|
|
)));
|
2020-04-03 14:57:19 +00:00
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
}
|
2019-09-04 22:16:39 +00:00
|
|
|
} else if (cme->message_type == netatom[NetActiveWindow]) {
|
2019-09-06 22:03:04 +00:00
|
|
|
#if FOCUSONNETACTIVE_PATCH
|
2020-07-02 08:09:24 +00:00
|
|
|
if (c->tags & c->mon->tagset[c->mon->seltags]) {
|
2019-09-06 22:03:04 +00:00
|
|
|
selmon = c->mon;
|
|
|
|
focus(c);
|
2020-07-02 08:09:24 +00:00
|
|
|
} else {
|
|
|
|
for (i = 0; i < LENGTH(tags) && !((1 << i) & c->tags); i++);
|
|
|
|
if (i < LENGTH(tags)) {
|
|
|
|
const Arg a = {.ui = 1 << i};
|
|
|
|
selmon = c->mon;
|
|
|
|
view(&a);
|
|
|
|
focus(c);
|
|
|
|
restack(selmon);
|
|
|
|
}
|
2019-09-06 22:03:04 +00:00
|
|
|
}
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (c != selmon->sel && !c->isurgent)
|
|
|
|
seturgent(c, 1);
|
2019-09-06 22:03:04 +00:00
|
|
|
#endif // FOCUSONNETACTIVE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
configure(Client *c)
|
|
|
|
{
|
|
|
|
XConfigureEvent ce;
|
|
|
|
|
|
|
|
ce.type = ConfigureNotify;
|
|
|
|
ce.display = dpy;
|
|
|
|
ce.event = c->win;
|
|
|
|
ce.window = c->win;
|
|
|
|
ce.x = c->x;
|
|
|
|
ce.y = c->y;
|
|
|
|
ce.width = c->w;
|
|
|
|
ce.height = c->h;
|
|
|
|
ce.border_width = c->bw;
|
|
|
|
ce.above = None;
|
|
|
|
ce.override_redirect = False;
|
|
|
|
XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&ce);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
configurenotify(XEvent *e)
|
|
|
|
{
|
|
|
|
Monitor *m;
|
2019-10-08 21:15:11 +00:00
|
|
|
#if !FAKEFULLSCREEN_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
Client *c;
|
2019-10-08 21:15:11 +00:00
|
|
|
#endif // !FAKEFULLSCREEN_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
XConfigureEvent *ev = &e->xconfigure;
|
|
|
|
int dirty;
|
2020-07-15 06:57:30 +00:00
|
|
|
int b;
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
/* TODO: updategeom handling sucks, needs to be simplified */
|
|
|
|
if (ev->window == root) {
|
|
|
|
dirty = (sw != ev->width || sh != ev->height);
|
|
|
|
sw = ev->width;
|
|
|
|
sh = ev->height;
|
|
|
|
if (updategeom() || dirty) {
|
|
|
|
drw_resize(drw, sw, bh);
|
|
|
|
updatebars();
|
|
|
|
for (m = mons; m; m = m->next) {
|
2019-10-08 21:15:11 +00:00
|
|
|
#if !FAKEFULLSCREEN_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
for (c = m->clients; c; c = c->next)
|
2019-11-21 11:15:16 +00:00
|
|
|
#if FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
if (c->isfullscreen && !c->fakefullscreen)
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (c->isfullscreen)
|
2019-11-21 11:15:16 +00:00
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
resizeclient(c, m->mx, m->my, m->mw, m->mh);
|
2019-10-08 21:15:11 +00:00
|
|
|
#endif // !FAKEFULLSCREEN_PATCH
|
2020-07-15 06:57:30 +00:00
|
|
|
for (b = 0; b < LENGTH(m->bars); b++)
|
|
|
|
if (m->bars[b])
|
|
|
|
XMoveResizeWindow(dpy, m->bars[b]->win, m->bars[b]->bx, m->bars[b]->by, m->bars[b]->bw, m->bars[b]->bh);
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
focus(NULL);
|
|
|
|
arrange(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
configurerequest(XEvent *e)
|
|
|
|
{
|
|
|
|
Client *c;
|
|
|
|
Monitor *m;
|
|
|
|
XConfigureRequestEvent *ev = &e->xconfigurerequest;
|
|
|
|
XWindowChanges wc;
|
|
|
|
|
|
|
|
if ((c = wintoclient(ev->window))) {
|
|
|
|
if (ev->value_mask & CWBorderWidth)
|
|
|
|
c->bw = ev->border_width;
|
|
|
|
else if (c->isfloating || !selmon->lt[selmon->sellt]->arrange) {
|
|
|
|
m = c->mon;
|
|
|
|
if (ev->value_mask & CWX) {
|
|
|
|
c->oldx = c->x;
|
|
|
|
c->x = m->mx + ev->x;
|
|
|
|
}
|
|
|
|
if (ev->value_mask & CWY) {
|
|
|
|
c->oldy = c->y;
|
|
|
|
c->y = m->my + ev->y;
|
|
|
|
}
|
|
|
|
if (ev->value_mask & CWWidth) {
|
|
|
|
c->oldw = c->w;
|
|
|
|
c->w = ev->width;
|
|
|
|
}
|
|
|
|
if (ev->value_mask & CWHeight) {
|
|
|
|
c->oldh = c->h;
|
|
|
|
c->h = ev->height;
|
|
|
|
}
|
|
|
|
if ((c->x + c->w) > m->mx + m->mw && c->isfloating)
|
|
|
|
c->x = m->mx + (m->mw / 2 - WIDTH(c) / 2); /* center in x direction */
|
|
|
|
if ((c->y + c->h) > m->my + m->mh && c->isfloating)
|
|
|
|
c->y = m->my + (m->mh / 2 - HEIGHT(c) / 2); /* center in y direction */
|
|
|
|
if ((ev->value_mask & (CWX|CWY)) && !(ev->value_mask & (CWWidth|CWHeight)))
|
|
|
|
configure(c);
|
|
|
|
if (ISVISIBLE(c))
|
|
|
|
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
2019-09-12 22:06:54 +00:00
|
|
|
#if AUTORESIZE_PATCH
|
|
|
|
else
|
|
|
|
c->needresize = 1;
|
|
|
|
#endif // AUTORESIZE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
} else
|
|
|
|
configure(c);
|
|
|
|
} else {
|
|
|
|
wc.x = ev->x;
|
|
|
|
wc.y = ev->y;
|
|
|
|
wc.width = ev->width;
|
|
|
|
wc.height = ev->height;
|
|
|
|
wc.border_width = ev->border_width;
|
|
|
|
wc.sibling = ev->above;
|
|
|
|
wc.stack_mode = ev->detail;
|
|
|
|
XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
|
|
|
|
}
|
|
|
|
XSync(dpy, False);
|
|
|
|
}
|
|
|
|
|
|
|
|
Monitor *
|
|
|
|
createmon(void)
|
|
|
|
{
|
|
|
|
Monitor *m;
|
2019-09-05 20:58:16 +00:00
|
|
|
int i;
|
2019-09-11 06:28:00 +00:00
|
|
|
#if MONITOR_RULES_PATCH
|
2019-09-30 21:52:51 +00:00
|
|
|
int mc, j;
|
2019-09-11 06:28:00 +00:00
|
|
|
Monitor *mi;
|
|
|
|
const MonitorRule *mr;
|
|
|
|
#endif // MONITOR_RULES_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
m = ecalloc(1, sizeof(Monitor));
|
2019-10-02 21:22:04 +00:00
|
|
|
#if EMPTYVIEW_PATCH
|
|
|
|
m->tagset[0] = m->tagset[1] = 0;
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
m->tagset[0] = m->tagset[1] = 1;
|
2019-10-02 21:22:04 +00:00
|
|
|
#endif // EMPTYVIEW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
m->mfact = mfact;
|
|
|
|
m->nmaster = nmaster;
|
2019-09-30 21:52:51 +00:00
|
|
|
#if FLEXTILE_DELUXE_LAYOUT
|
|
|
|
m->nstack = nstack;
|
|
|
|
#endif // FLEXTILE_DELUXE_LAYOUT
|
2019-09-04 22:16:39 +00:00
|
|
|
m->showbar = showbar;
|
|
|
|
m->topbar = topbar;
|
2019-09-14 21:28:04 +00:00
|
|
|
#if SETBORDERPX_PATCH
|
|
|
|
m->borderpx = borderpx;
|
|
|
|
#endif // SETBORDERPX_PATCH
|
2019-09-08 22:18:47 +00:00
|
|
|
#if VANITYGAPS_PATCH
|
|
|
|
m->gappih = gappih;
|
|
|
|
m->gappiv = gappiv;
|
|
|
|
m->gappoh = gappoh;
|
|
|
|
m->gappov = gappov;
|
|
|
|
#endif // VANITYGAPS_PATCH
|
2020-07-15 06:57:30 +00:00
|
|
|
for (i = 0; i < LENGTH(m->bars); i++)
|
|
|
|
m->bars[i] = ecalloc(1, sizeof(Bar));
|
|
|
|
// for (r = 0; r < LENGTH(barrules); r++) {
|
|
|
|
|
|
|
|
// for (b = 0; b < LENGTH(selmon->bars); b++) {
|
|
|
|
|
2019-09-11 06:28:00 +00:00
|
|
|
#if MONITOR_RULES_PATCH
|
|
|
|
for (mc = 0, mi = mons; mi; mi = mi->next, mc++);
|
2019-09-30 21:52:51 +00:00
|
|
|
for (j = 0; j < LENGTH(monrules); j++) {
|
|
|
|
mr = &monrules[j];
|
|
|
|
if ((mr->monitor == -1 || mr->monitor == mc)
|
|
|
|
#if PERTAG_PATCH
|
|
|
|
&& (mr->tag == -1 || mr->tag == 0)
|
|
|
|
#endif // PERTAG_PATCH
|
|
|
|
) {
|
2019-09-11 06:28:00 +00:00
|
|
|
m->lt[0] = &layouts[mr->layout];
|
|
|
|
m->lt[1] = &layouts[1 % LENGTH(layouts)];
|
|
|
|
strncpy(m->ltsymbol, layouts[mr->layout].symbol, sizeof m->ltsymbol);
|
2020-04-26 14:26:36 +00:00
|
|
|
|
|
|
|
if (mr->mfact > -1)
|
|
|
|
m->mfact = mr->mfact;
|
|
|
|
if (mr->nmaster > -1)
|
|
|
|
m->nmaster = mr->nmaster;
|
|
|
|
if (mr->showbar > -1)
|
|
|
|
m->showbar = mr->showbar;
|
|
|
|
if (mr->topbar > -1)
|
|
|
|
m->topbar = mr->topbar;
|
2019-09-11 06:28:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
m->lt[0] = &layouts[0];
|
|
|
|
m->lt[1] = &layouts[1 % LENGTH(layouts)];
|
|
|
|
strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
|
|
|
|
#endif // MONITOR_RULES_PATCH
|
2019-09-09 20:25:19 +00:00
|
|
|
|
2019-09-30 21:52:51 +00:00
|
|
|
#if FLEXTILE_DELUXE_LAYOUT
|
|
|
|
m->ltaxis[LAYOUT] = m->lt[0]->preset.layout;
|
|
|
|
m->ltaxis[MASTER] = m->lt[0]->preset.masteraxis;
|
|
|
|
m->ltaxis[STACK] = m->lt[0]->preset.stack1axis;
|
|
|
|
m->ltaxis[STACK2] = m->lt[0]->preset.stack2axis;
|
|
|
|
#endif // FLEXTILE_DELUXE_LAYOUT
|
|
|
|
|
2019-09-05 20:58:16 +00:00
|
|
|
#if PERTAG_PATCH
|
|
|
|
if (!(m->pertag = (Pertag *)calloc(1, sizeof(Pertag))))
|
|
|
|
die("fatal: could not malloc() %u bytes\n", sizeof(Pertag));
|
|
|
|
m->pertag->curtag = m->pertag->prevtag = 1;
|
2019-09-11 06:28:00 +00:00
|
|
|
for (i = 0; i <= LENGTH(tags); i++) {
|
2019-09-30 21:52:51 +00:00
|
|
|
#if FLEXTILE_DELUXE_LAYOUT
|
|
|
|
m->pertag->nstacks[i] = m->nstack;
|
|
|
|
#endif // FLEXTILE_DELUXE_LAYOUT
|
|
|
|
|
2020-04-26 14:26:36 +00:00
|
|
|
#if !MONITOR_RULES_PATCH
|
|
|
|
/* init nmaster */
|
|
|
|
m->pertag->nmasters[i] = m->nmaster;
|
|
|
|
|
2019-09-05 20:58:16 +00:00
|
|
|
/* init mfacts */
|
|
|
|
m->pertag->mfacts[i] = m->mfact;
|
|
|
|
|
2020-04-26 14:26:36 +00:00
|
|
|
#if PERTAGBAR_PATCH
|
|
|
|
/* init showbar */
|
|
|
|
m->pertag->showbars[i] = m->showbar;
|
|
|
|
#endif // PERTAGBAR_PATCH
|
|
|
|
#endif // MONITOR_RULES_PATCH
|
|
|
|
|
|
|
|
#if ZOOMSWAP_PATCH
|
|
|
|
m->pertag->prevzooms[i] = NULL;
|
|
|
|
#endif // ZOOMSWAP_PATCH
|
|
|
|
|
2019-09-05 20:58:16 +00:00
|
|
|
/* init layouts */
|
2019-09-30 21:52:51 +00:00
|
|
|
#if MONITOR_RULES_PATCH
|
|
|
|
for (j = 0; j < LENGTH(monrules); j++) {
|
|
|
|
mr = &monrules[j];
|
|
|
|
if ((mr->monitor == -1 || mr->monitor == mc) && (mr->tag == -1 || mr->tag == i)) {
|
|
|
|
m->pertag->ltidxs[i][0] = &layouts[mr->layout];
|
|
|
|
m->pertag->ltidxs[i][1] = m->lt[0];
|
2020-04-26 14:26:36 +00:00
|
|
|
m->pertag->nmasters[i] = (mr->nmaster > -1 ? mr->nmaster : m->nmaster);
|
|
|
|
m->pertag->mfacts[i] = (mr->mfact > -1 ? mr->mfact : m->mfact);
|
|
|
|
#if PERTAGBAR_PATCH
|
|
|
|
m->pertag->showbars[i] = (mr->showbar > -1 ? mr->showbar : m->showbar);
|
|
|
|
#endif // PERTAGBAR_PATCH
|
2019-09-30 21:52:51 +00:00
|
|
|
#if FLEXTILE_DELUXE_LAYOUT
|
|
|
|
m->pertag->ltaxis[i][LAYOUT] = m->pertag->ltidxs[i][0]->preset.layout;
|
|
|
|
m->pertag->ltaxis[i][MASTER] = m->pertag->ltidxs[i][0]->preset.masteraxis;
|
|
|
|
m->pertag->ltaxis[i][STACK] = m->pertag->ltidxs[i][0]->preset.stack1axis;
|
|
|
|
m->pertag->ltaxis[i][STACK2] = m->pertag->ltidxs[i][0]->preset.stack2axis;
|
|
|
|
#endif // FLEXTILE_DELUXE_LAYOUT
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
2019-09-05 20:58:16 +00:00
|
|
|
m->pertag->ltidxs[i][0] = m->lt[0];
|
|
|
|
m->pertag->ltidxs[i][1] = m->lt[1];
|
2019-09-30 21:52:51 +00:00
|
|
|
#if FLEXTILE_DELUXE_LAYOUT
|
2019-09-09 20:25:19 +00:00
|
|
|
/* init flextile axes */
|
2019-09-30 21:52:51 +00:00
|
|
|
m->pertag->ltaxis[i][LAYOUT] = m->ltaxis[LAYOUT];
|
|
|
|
m->pertag->ltaxis[i][MASTER] = m->ltaxis[MASTER];
|
|
|
|
m->pertag->ltaxis[i][STACK] = m->ltaxis[STACK];
|
|
|
|
m->pertag->ltaxis[i][STACK2] = m->ltaxis[STACK2];
|
|
|
|
#endif // FLEXTILE_DELUXE_LAYOUT
|
|
|
|
#endif // MONITOR_RULES_PATCH
|
|
|
|
m->pertag->sellts[i] = m->sellt;
|
2019-09-09 20:25:19 +00:00
|
|
|
|
2020-03-07 11:44:42 +00:00
|
|
|
#if VANITYGAPS_PATCH
|
|
|
|
m->pertag->enablegaps[i] = 1;
|
|
|
|
#endif // VANITYGAPS_PATCH
|
2019-09-05 20:58:16 +00:00
|
|
|
}
|
|
|
|
#endif // PERTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
destroynotify(XEvent *e)
|
|
|
|
{
|
|
|
|
Client *c;
|
|
|
|
XDestroyWindowEvent *ev = &e->xdestroywindow;
|
|
|
|
|
|
|
|
if ((c = wintoclient(ev->window)))
|
|
|
|
unmanage(c, 1);
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
else if ((c = swallowingclient(ev->window)))
|
|
|
|
unmanage(c->swallowing, 1);
|
|
|
|
#endif // SWALLOW_PATCH
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
else if (showsystray && (c = wintosystrayicon(ev->window))) {
|
|
|
|
removesystrayicon(c);
|
|
|
|
updatesystray();
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
detach(Client *c)
|
|
|
|
{
|
|
|
|
Client **tc;
|
|
|
|
|
|
|
|
for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
|
|
|
|
*tc = c->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
detachstack(Client *c)
|
|
|
|
{
|
|
|
|
Client **tc, *t;
|
|
|
|
|
|
|
|
for (tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
|
|
|
|
*tc = c->snext;
|
|
|
|
|
|
|
|
if (c == c->mon->sel) {
|
|
|
|
for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
|
|
|
|
c->mon->sel = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Monitor *
|
|
|
|
dirtomon(int dir)
|
|
|
|
{
|
|
|
|
Monitor *m = NULL;
|
|
|
|
|
|
|
|
if (dir > 0) {
|
|
|
|
if (!(m = selmon->next))
|
|
|
|
m = mons;
|
|
|
|
} else if (selmon == mons)
|
|
|
|
for (m = mons; m->next; m = m->next);
|
|
|
|
else
|
|
|
|
for (m = mons; m->next != selmon; m = m->next);
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
drawbar(Monitor *m)
|
|
|
|
{
|
2020-07-15 06:57:30 +00:00
|
|
|
Monitor *mon;
|
2020-07-15 12:10:47 +00:00
|
|
|
int b, r, w, mi;
|
2020-07-15 06:57:30 +00:00
|
|
|
int rx, lx, rw, lw; // bar size, split between left and right if a center module is added
|
|
|
|
const BarRule *br;
|
|
|
|
Bar *bar;
|
2020-07-15 12:10:47 +00:00
|
|
|
BarWidthArg warg = { 0 };
|
|
|
|
BarDrawArg darg = { 0, 0 };
|
2020-07-15 06:57:30 +00:00
|
|
|
|
|
|
|
for (mi = 0, mon = mons; mon && mon != m; mon = mon->next, mi++); // get the monitor index
|
|
|
|
for (b = LENGTH(m->bars) - 1; b >= 0; b--) {
|
|
|
|
bar = m->bars[b];
|
2020-07-15 12:10:47 +00:00
|
|
|
if (!bar->win)
|
2020-07-15 06:57:30 +00:00
|
|
|
continue;
|
2019-09-04 22:16:39 +00:00
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
rw = lw = bar->bw;
|
|
|
|
rx = lx = 0;
|
2019-09-05 20:10:00 +00:00
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_VTCOLORS_PATCH
|
|
|
|
drw_setscheme(drw, scheme[SchemeTagsNorm]);
|
2020-02-11 17:31:11 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
drw_setscheme(drw, scheme[SchemeNorm]);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_VTCOLORS_PATCH
|
|
|
|
drw_rect(drw, lx, 0, lw, bh, 1, 1);
|
|
|
|
for (r = 0; r < LENGTH(barrules); r++) {
|
|
|
|
br = &barrules[r];
|
|
|
|
if (br->bar != b || (br->monitor == 'A' && m != selmon) || (br->monitor != -1 && br->monitor != mi) || br->drawfunc == NULL)
|
2019-10-06 22:46:23 +00:00
|
|
|
continue;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_VTCOLORS_PATCH
|
|
|
|
drw_setscheme(drw, scheme[SchemeTagsNorm]);
|
2020-02-11 17:31:11 +00:00
|
|
|
#else
|
2020-01-30 07:43:00 +00:00
|
|
|
drw_setscheme(drw, scheme[SchemeNorm]);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_VTCOLORS_PATCH
|
2020-07-15 12:10:47 +00:00
|
|
|
warg.max_width = (br->alignment < BAR_ALIGN_RIGHT_LEFT ? lw : rw);
|
|
|
|
w = br->widthfunc(m, &warg);
|
|
|
|
w = MIN(warg.max_width, w);
|
|
|
|
|
|
|
|
if (lw <= 0) { // if left is exhausted, switch to right side
|
|
|
|
lw = rw;
|
|
|
|
lx = rx;
|
|
|
|
} else if (rw <= 0) {
|
|
|
|
rw = lw;
|
|
|
|
rx = lx;
|
2019-09-06 21:47:06 +00:00
|
|
|
}
|
2020-07-15 12:10:47 +00:00
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
switch(br->alignment) {
|
|
|
|
default:
|
|
|
|
case BAR_ALIGN_NONE:
|
|
|
|
case BAR_ALIGN_LEFT_LEFT:
|
|
|
|
case BAR_ALIGN_LEFT:
|
|
|
|
bar->x[r] = lx;
|
|
|
|
bar->w[r] = w;
|
|
|
|
if (lx == rx) {
|
|
|
|
rx += w;
|
|
|
|
rw -= w;
|
|
|
|
}
|
|
|
|
lx += w;
|
|
|
|
lw -= w;
|
|
|
|
break;
|
|
|
|
case BAR_ALIGN_LEFT_RIGHT:
|
|
|
|
case BAR_ALIGN_RIGHT:
|
|
|
|
bar->x[r] = lx + lw - w;
|
|
|
|
bar->w[r] = w;
|
|
|
|
if (lx == rx)
|
|
|
|
rw -= w;
|
|
|
|
lw -= w;
|
|
|
|
break;
|
|
|
|
case BAR_ALIGN_LEFT_CENTER:
|
|
|
|
case BAR_ALIGN_CENTER:
|
|
|
|
bar->x[r] = lx + lw / 2 - w / 2;
|
|
|
|
bar->w[r] = w;
|
|
|
|
if (lx == rx) {
|
|
|
|
rw = rx + rw - bar->x[r] - bar->w[r];
|
|
|
|
rx = bar->x[r] + bar->w[r];
|
|
|
|
}
|
|
|
|
lw = bar->x[r] - lx;
|
|
|
|
break;
|
|
|
|
case BAR_ALIGN_RIGHT_LEFT:
|
|
|
|
bar->x[r] = rx;
|
|
|
|
bar->w[r] = w;
|
|
|
|
if (lx == rx) {
|
|
|
|
lx += w;
|
|
|
|
lw -= w;
|
|
|
|
}
|
|
|
|
rx += w;
|
|
|
|
rw -= w;
|
|
|
|
break;
|
|
|
|
case BAR_ALIGN_RIGHT_RIGHT:
|
|
|
|
bar->x[r] = rx + rw - w;
|
|
|
|
bar->w[r] = w;
|
|
|
|
if (lx == rx)
|
|
|
|
lw -= w;
|
|
|
|
rw -= w;
|
|
|
|
break;
|
|
|
|
case BAR_ALIGN_RIGHT_CENTER:
|
|
|
|
bar->x[r] = rx + rw / 2 - w / 2;
|
|
|
|
bar->w[r] = w;
|
|
|
|
if (lx == rx) {
|
|
|
|
lw = lx + lw - bar->x[r] + bar->w[r];
|
|
|
|
lx = bar->x[r] + bar->w[r];
|
|
|
|
}
|
|
|
|
rw = bar->x[r] - rx;
|
|
|
|
break;
|
|
|
|
}
|
2020-07-15 12:10:47 +00:00
|
|
|
darg.x = bar->x[r];
|
|
|
|
darg.w = bar->w[r];
|
|
|
|
br->drawfunc(m, &darg);
|
2020-01-30 07:43:00 +00:00
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
drw_map(drw, bar->win, 0, 0, bar->bw, bar->bh);
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
drawbars(void)
|
|
|
|
{
|
|
|
|
Monitor *m;
|
|
|
|
for (m = mons; m; m = m->next)
|
|
|
|
drawbar(m);
|
|
|
|
}
|
|
|
|
|
2019-09-15 22:32:28 +00:00
|
|
|
#if !FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
void
|
|
|
|
enternotify(XEvent *e)
|
|
|
|
{
|
|
|
|
Client *c;
|
|
|
|
Monitor *m;
|
|
|
|
XCrossingEvent *ev = &e->xcrossing;
|
|
|
|
|
|
|
|
if ((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
|
|
|
|
return;
|
|
|
|
c = wintoclient(ev->window);
|
|
|
|
m = c ? c->mon : wintomon(ev->window);
|
|
|
|
if (m != selmon) {
|
|
|
|
unfocus(selmon->sel, 1);
|
|
|
|
selmon = m;
|
|
|
|
} else if (!c || c == selmon->sel)
|
|
|
|
return;
|
|
|
|
focus(c);
|
|
|
|
}
|
2019-09-15 22:32:28 +00:00
|
|
|
#endif // FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
expose(XEvent *e)
|
|
|
|
{
|
|
|
|
Monitor *m;
|
|
|
|
XExposeEvent *ev = &e->xexpose;
|
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
if (ev->count == 0 && (m = wintomon(ev->window)))
|
2019-09-04 22:16:39 +00:00
|
|
|
drawbar(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
focus(Client *c)
|
|
|
|
{
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_AWESOMEBAR_PATCH
|
2019-09-09 22:18:46 +00:00
|
|
|
if (!c || !ISVISIBLE(c) || HIDDEN(c))
|
|
|
|
for (c = selmon->stack; c && (!ISVISIBLE(c) || HIDDEN(c)); c = c->snext);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!c || !ISVISIBLE(c))
|
|
|
|
for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_AWESOMEBAR_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (selmon->sel && selmon->sel != c)
|
|
|
|
unfocus(selmon->sel, 0);
|
|
|
|
if (c) {
|
|
|
|
if (c->mon != selmon)
|
|
|
|
selmon = c->mon;
|
|
|
|
if (c->isurgent)
|
|
|
|
seturgent(c, 0);
|
|
|
|
detachstack(c);
|
|
|
|
attachstack(c);
|
|
|
|
grabbuttons(c, 1);
|
2019-09-10 22:51:37 +00:00
|
|
|
#if FLOAT_BORDER_COLOR_PATCH
|
|
|
|
if (c->isfloating)
|
|
|
|
XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColFloat].pixel);
|
|
|
|
else
|
|
|
|
XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
|
2019-09-10 22:51:37 +00:00
|
|
|
#endif // FLOAT_BORDER_COLOR_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
setfocus(c);
|
|
|
|
} else {
|
|
|
|
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
|
|
|
|
XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
|
|
|
|
}
|
|
|
|
selmon->sel = c;
|
|
|
|
drawbars();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* there are some broken focus acquiring clients needing extra handling */
|
|
|
|
void
|
|
|
|
focusin(XEvent *e)
|
|
|
|
{
|
|
|
|
XFocusChangeEvent *ev = &e->xfocus;
|
|
|
|
|
|
|
|
if (selmon->sel && ev->window != selmon->sel->win)
|
|
|
|
setfocus(selmon->sel);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
focusmon(const Arg *arg)
|
|
|
|
{
|
|
|
|
Monitor *m;
|
|
|
|
|
|
|
|
if (!mons->next)
|
|
|
|
return;
|
|
|
|
if ((m = dirtomon(arg->i)) == selmon)
|
|
|
|
return;
|
|
|
|
unfocus(selmon->sel, 0);
|
|
|
|
selmon = m;
|
|
|
|
focus(NULL);
|
2019-09-14 22:43:35 +00:00
|
|
|
#if WARP_PATCH
|
|
|
|
warp(selmon->sel);
|
|
|
|
#endif // WARP_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
2020-03-23 11:15:50 +00:00
|
|
|
#if !STACKER_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
void
|
|
|
|
focusstack(const Arg *arg)
|
|
|
|
{
|
|
|
|
Client *c = NULL, *i;
|
|
|
|
|
|
|
|
if (!selmon->sel)
|
|
|
|
return;
|
2019-09-12 22:06:54 +00:00
|
|
|
#if ALWAYSFULLSCREEN_PATCH
|
|
|
|
if (selmon->sel->isfullscreen)
|
2020-01-30 07:43:00 +00:00
|
|
|
return;
|
2019-09-12 22:06:54 +00:00
|
|
|
#endif // ALWAYSFULLSCREEN_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (arg->i > 0) {
|
|
|
|
for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
|
|
|
|
if (!c)
|
|
|
|
for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next);
|
|
|
|
} else {
|
|
|
|
for (i = selmon->clients; i != selmon->sel; i = i->next)
|
|
|
|
if (ISVISIBLE(i))
|
|
|
|
c = i;
|
|
|
|
if (!c)
|
|
|
|
for (; i; i = i->next)
|
|
|
|
if (ISVISIBLE(i))
|
|
|
|
c = i;
|
|
|
|
}
|
|
|
|
if (c) {
|
|
|
|
focus(c);
|
|
|
|
restack(selmon);
|
|
|
|
}
|
|
|
|
}
|
2020-03-23 11:15:50 +00:00
|
|
|
#endif // STACKER_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
Atom
|
|
|
|
getatomprop(Client *c, Atom prop)
|
|
|
|
{
|
|
|
|
int di;
|
|
|
|
unsigned long dl;
|
|
|
|
unsigned char *p = NULL;
|
|
|
|
Atom da, atom = None;
|
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
/* FIXME getatomprop should return the number of items and a pointer to
|
|
|
|
* the stored data instead of this workaround */
|
|
|
|
Atom req = XA_ATOM;
|
|
|
|
if (prop == xatom[XembedInfo])
|
|
|
|
req = xatom[XembedInfo];
|
|
|
|
|
|
|
|
if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
|
|
|
|
&da, &di, &dl, &dl, &p) == Success && p) {
|
|
|
|
atom = *(Atom *)p;
|
|
|
|
if (da == xatom[XembedInfo] && dl == 2)
|
|
|
|
atom = ((Atom *)p)[1];
|
|
|
|
XFree(p);
|
|
|
|
}
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
|
|
|
|
&da, &di, &dl, &dl, &p) == Success && p) {
|
|
|
|
atom = *(Atom *)p;
|
|
|
|
XFree(p);
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
return atom;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
getrootptr(int *x, int *y)
|
|
|
|
{
|
|
|
|
int di;
|
|
|
|
unsigned int dui;
|
|
|
|
Window dummy;
|
|
|
|
|
|
|
|
return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
|
|
|
|
}
|
|
|
|
|
|
|
|
long
|
|
|
|
getstate(Window w)
|
|
|
|
{
|
|
|
|
int format;
|
|
|
|
long result = -1;
|
|
|
|
unsigned char *p = NULL;
|
|
|
|
unsigned long n, extra;
|
|
|
|
Atom real;
|
|
|
|
|
|
|
|
if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
|
|
|
|
&real, &format, &n, &extra, (unsigned char **)&p) != Success)
|
|
|
|
return -1;
|
|
|
|
if (n != 0)
|
|
|
|
result = *p;
|
|
|
|
XFree(p);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
gettextprop(Window w, Atom atom, char *text, unsigned int size)
|
|
|
|
{
|
|
|
|
char **list = NULL;
|
|
|
|
int n;
|
|
|
|
XTextProperty name;
|
|
|
|
|
|
|
|
if (!text || size == 0)
|
|
|
|
return 0;
|
|
|
|
text[0] = '\0';
|
|
|
|
if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems)
|
|
|
|
return 0;
|
|
|
|
if (name.encoding == XA_STRING)
|
|
|
|
strncpy(text, (char *)name.value, size - 1);
|
|
|
|
else {
|
|
|
|
if (XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success && n > 0 && *list) {
|
|
|
|
strncpy(text, *list, size - 1);
|
|
|
|
XFreeStringList(list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
text[size - 1] = '\0';
|
|
|
|
XFree(name.value);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
grabbuttons(Client *c, int focused)
|
|
|
|
{
|
|
|
|
updatenumlockmask();
|
|
|
|
{
|
|
|
|
unsigned int i, j;
|
|
|
|
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
|
|
|
|
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
|
|
|
|
if (!focused)
|
|
|
|
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
|
|
|
|
BUTTONMASK, GrabModeSync, GrabModeSync, None, None);
|
|
|
|
for (i = 0; i < LENGTH(buttons); i++)
|
|
|
|
if (buttons[i].click == ClkClientWin)
|
|
|
|
for (j = 0; j < LENGTH(modifiers); j++)
|
|
|
|
XGrabButton(dpy, buttons[i].button,
|
|
|
|
buttons[i].mask | modifiers[j],
|
|
|
|
c->win, False, BUTTONMASK,
|
|
|
|
GrabModeAsync, GrabModeSync, None, None);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-05-31 13:14:29 +00:00
|
|
|
#if KEYMODES_PATCH
|
|
|
|
grabdefkeys(void)
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
grabkeys(void)
|
2020-05-31 13:14:29 +00:00
|
|
|
#endif // KEYMODES_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
{
|
|
|
|
updatenumlockmask();
|
|
|
|
{
|
|
|
|
unsigned int i, j;
|
|
|
|
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
|
|
|
|
KeyCode code;
|
|
|
|
|
|
|
|
XUngrabKey(dpy, AnyKey, AnyModifier, root);
|
|
|
|
for (i = 0; i < LENGTH(keys); i++)
|
|
|
|
if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
|
|
|
|
for (j = 0; j < LENGTH(modifiers); j++)
|
|
|
|
XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
|
|
|
|
True, GrabModeAsync, GrabModeAsync);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
incnmaster(const Arg *arg)
|
|
|
|
{
|
2019-09-05 20:58:16 +00:00
|
|
|
#if PERTAG_PATCH
|
|
|
|
selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag] = MAX(selmon->nmaster + arg->i, 0);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
|
2019-09-05 20:58:16 +00:00
|
|
|
#endif // PERTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
arrange(selmon);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef XINERAMA
|
|
|
|
static int
|
|
|
|
isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
|
|
|
|
{
|
|
|
|
while (n--)
|
|
|
|
if (unique[n].x_org == info->x_org && unique[n].y_org == info->y_org
|
|
|
|
&& unique[n].width == info->width && unique[n].height == info->height)
|
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif /* XINERAMA */
|
|
|
|
|
|
|
|
void
|
2020-05-31 13:14:29 +00:00
|
|
|
#if KEYMODES_PATCH
|
|
|
|
keydefpress(XEvent *e)
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
keypress(XEvent *e)
|
2020-05-31 13:14:29 +00:00
|
|
|
#endif // KEYMODES_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
{
|
|
|
|
unsigned int i;
|
|
|
|
KeySym keysym;
|
|
|
|
XKeyEvent *ev;
|
|
|
|
|
|
|
|
ev = &e->xkey;
|
|
|
|
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
|
|
|
|
for (i = 0; i < LENGTH(keys); i++)
|
|
|
|
if (keysym == keys[i].keysym
|
|
|
|
&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
|
|
|
|
&& keys[i].func)
|
|
|
|
keys[i].func(&(keys[i].arg));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
killclient(const Arg *arg)
|
|
|
|
{
|
2019-10-22 16:30:00 +00:00
|
|
|
#if ISPERMANENT_PATCH
|
|
|
|
if (!selmon->sel || selmon->sel->ispermanent)
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!selmon->sel)
|
2019-10-22 16:30:00 +00:00
|
|
|
#endif // ISPERMANENT_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
return;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
if (!sendevent(selmon->sel->win, wmatom[WMDelete], NoEventMask, wmatom[WMDelete], CurrentTime, 0, 0, 0)) {
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!sendevent(selmon->sel, wmatom[WMDelete])) {
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
XGrabServer(dpy);
|
|
|
|
XSetErrorHandler(xerrordummy);
|
|
|
|
XSetCloseDownMode(dpy, DestroyAll);
|
|
|
|
XKillClient(dpy, selmon->sel->win);
|
|
|
|
XSync(dpy, False);
|
|
|
|
XSetErrorHandler(xerror);
|
|
|
|
XUngrabServer(dpy);
|
|
|
|
}
|
2020-01-29 07:31:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
selmon->pertag->prevclient[selmon->pertag->curtag] = NULL;
|
|
|
|
#endif // SWAPFOCUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
manage(Window w, XWindowAttributes *wa)
|
|
|
|
{
|
|
|
|
Client *c, *t = NULL;
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
Client *term = NULL;
|
|
|
|
#endif // SWALLOW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
Window trans = None;
|
|
|
|
XWindowChanges wc;
|
|
|
|
|
|
|
|
c = ecalloc(1, sizeof(Client));
|
|
|
|
c->win = w;
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
c->pid = winpid(w);
|
|
|
|
#endif // SWALLOW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
/* geometry */
|
|
|
|
c->x = c->oldx = wa->x;
|
|
|
|
c->y = c->oldy = wa->y;
|
|
|
|
c->w = c->oldw = wa->width;
|
|
|
|
c->h = c->oldh = wa->height;
|
|
|
|
c->oldbw = wa->border_width;
|
2019-09-08 22:18:47 +00:00
|
|
|
#if CFACTS_PATCH
|
|
|
|
c->cfact = 1.0;
|
|
|
|
#endif // CFACTS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
updatetitle(c);
|
|
|
|
if (XGetTransientForHint(dpy, w, &trans) && (t = wintoclient(trans))) {
|
|
|
|
c->mon = t->mon;
|
|
|
|
c->tags = t->tags;
|
2020-06-23 09:55:55 +00:00
|
|
|
#if FLOATPOS_PATCH
|
|
|
|
#if SETBORDERPX_PATCH
|
|
|
|
c->bw = c->mon->borderpx;
|
|
|
|
#else
|
|
|
|
c->bw = borderpx;
|
|
|
|
#endif // SETBORDERPX_PATCH
|
|
|
|
#endif // FLOATPOS_PATCH
|
2020-07-04 19:40:29 +00:00
|
|
|
#if CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH
|
|
|
|
c->x = t->x + WIDTH(t) / 2 - WIDTH(c) / 2;
|
|
|
|
c->y = t->y + HEIGHT(t) / 2 - HEIGHT(c) / 2;
|
|
|
|
#elif CENTER_TRANSIENT_WINDOWS_PATCH
|
|
|
|
c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
|
|
|
|
c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
|
|
|
|
#endif // CENTER_TRANSIENT_WINDOWS_PATCH | CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
} else {
|
|
|
|
c->mon = selmon;
|
2020-06-21 13:33:29 +00:00
|
|
|
#if FLOATPOS_PATCH
|
|
|
|
#if SETBORDERPX_PATCH
|
|
|
|
c->bw = c->mon->borderpx;
|
|
|
|
#else
|
|
|
|
c->bw = borderpx;
|
|
|
|
#endif // SETBORDERPX_PATCH
|
|
|
|
#endif // FLOATPOS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
applyrules(c);
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
term = termforwin(c);
|
|
|
|
#endif // SWALLOW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (c->x + WIDTH(c) > c->mon->mx + c->mon->mw)
|
|
|
|
c->x = c->mon->mx + c->mon->mw - WIDTH(c);
|
|
|
|
if (c->y + HEIGHT(c) > c->mon->my + c->mon->mh)
|
|
|
|
c->y = c->mon->my + c->mon->mh - HEIGHT(c);
|
|
|
|
c->x = MAX(c->x, c->mon->mx);
|
|
|
|
/* only fix client y-offset, if the client center might cover the bar */
|
2020-07-15 06:57:30 +00:00
|
|
|
c->y = MAX(c->y, ((c->mon->bars[0]->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
|
2019-09-04 22:16:39 +00:00
|
|
|
&& (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
|
2020-06-21 13:33:29 +00:00
|
|
|
#if !FLOATPOS_PATCH
|
2019-09-14 21:28:04 +00:00
|
|
|
#if SETBORDERPX_PATCH
|
|
|
|
c->bw = c->mon->borderpx;
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
c->bw = borderpx;
|
2019-09-14 21:28:04 +00:00
|
|
|
#endif // SETBORDERPX_PATCH
|
2020-06-21 13:33:29 +00:00
|
|
|
#endif // FLOATPOS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
wc.border_width = c->bw;
|
|
|
|
XConfigureWindow(dpy, w, CWBorderWidth, &wc);
|
2019-09-10 22:51:37 +00:00
|
|
|
#if FLOAT_BORDER_COLOR_PATCH
|
|
|
|
if (c->isfloating)
|
|
|
|
XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel);
|
|
|
|
else
|
|
|
|
XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColBorder].pixel);
|
2019-09-10 22:51:37 +00:00
|
|
|
#endif // FLOAT_BORDER_COLOR_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
configure(c); /* propagates border_width, if size doesn't change */
|
2020-06-23 09:55:55 +00:00
|
|
|
#if !FLOATPOS_PATCH
|
|
|
|
updatesizehints(c);
|
|
|
|
#endif // FLOATPOS_PATCH
|
2020-06-15 11:24:23 +00:00
|
|
|
if (getatomprop(c, netatom[NetWMState]) == netatom[NetWMFullscreen])
|
|
|
|
setfullscreen(c, 1);
|
2019-09-04 22:16:39 +00:00
|
|
|
updatewmhints(c);
|
2019-09-07 22:23:30 +00:00
|
|
|
#if CENTER_PATCH
|
|
|
|
if (c->iscentered) {
|
2020-06-21 13:33:29 +00:00
|
|
|
c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
|
|
|
|
c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
|
2019-09-07 22:23:30 +00:00
|
|
|
}
|
|
|
|
#endif // CENTER_PATCH
|
2019-10-24 06:47:00 +00:00
|
|
|
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
|
2019-09-07 21:08:53 +00:00
|
|
|
c->sfx = -9999;
|
|
|
|
c->sfy = -9999;
|
|
|
|
c->sfw = c->w;
|
|
|
|
c->sfh = c->h;
|
2019-10-24 06:47:00 +00:00
|
|
|
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
|
2019-09-07 21:08:53 +00:00
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
|
|
|
|
grabbuttons(c, 0);
|
2019-10-04 20:46:47 +00:00
|
|
|
#if MAXIMIZE_PATCH
|
|
|
|
c->wasfloating = 0;
|
|
|
|
c->ismax = 0;
|
2019-10-24 06:47:00 +00:00
|
|
|
#elif EXRESIZE_PATCH
|
|
|
|
c->wasfloating = 0;
|
|
|
|
#endif // MAXIMIZE_PATCH / EXRESIZE_PATCH
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!c->isfloating)
|
|
|
|
c->isfloating = c->oldstate = trans != None || c->isfixed;
|
|
|
|
if (c->isfloating)
|
|
|
|
XRaiseWindow(dpy, c->win);
|
2019-09-10 22:51:37 +00:00
|
|
|
#if FLOAT_BORDER_COLOR_PATCH
|
|
|
|
if (c->isfloating)
|
|
|
|
XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel);
|
|
|
|
#endif // FLOAT_BORDER_COLOR_PATCH
|
2019-09-06 21:25:32 +00:00
|
|
|
#if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH
|
|
|
|
attachx(c);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
attach(c);
|
2019-09-06 21:25:32 +00:00
|
|
|
#endif
|
2019-09-04 22:16:39 +00:00
|
|
|
attachstack(c);
|
|
|
|
XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
|
|
|
|
(unsigned char *) &(c->win), 1);
|
|
|
|
XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
|
2019-09-09 22:18:46 +00:00
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_AWESOMEBAR_PATCH
|
2019-09-09 22:18:46 +00:00
|
|
|
if (!HIDDEN(c))
|
|
|
|
setclientstate(c, NormalState);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
setclientstate(c, NormalState);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_AWESOMEBAR_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (c->mon == selmon)
|
|
|
|
unfocus(selmon->sel, 0);
|
|
|
|
c->mon->sel = c;
|
|
|
|
arrange(c->mon);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_AWESOMEBAR_PATCH
|
2019-09-09 22:18:46 +00:00
|
|
|
if (!HIDDEN(c))
|
|
|
|
XMapWindow(dpy, c->win);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
XMapWindow(dpy, c->win);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_AWESOMEBAR_PATCH
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
if (term)
|
|
|
|
swallow(term, c);
|
|
|
|
#endif // SWALLOW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
focus(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mappingnotify(XEvent *e)
|
|
|
|
{
|
|
|
|
XMappingEvent *ev = &e->xmapping;
|
|
|
|
|
|
|
|
XRefreshKeyboardMapping(ev);
|
|
|
|
if (ev->request == MappingKeyboard)
|
|
|
|
grabkeys();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
maprequest(XEvent *e)
|
|
|
|
{
|
|
|
|
static XWindowAttributes wa;
|
|
|
|
XMapRequestEvent *ev = &e->xmaprequest;
|
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
Client *i;
|
|
|
|
if (showsystray && (i = wintosystrayicon(ev->window))) {
|
|
|
|
sendevent(i->win, netatom[Xembed], StructureNotifyMask, CurrentTime, XEMBED_WINDOW_ACTIVATE, 0, systray->win, XEMBED_EMBEDDED_VERSION);
|
|
|
|
updatesystray();
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!XGetWindowAttributes(dpy, ev->window, &wa))
|
|
|
|
return;
|
|
|
|
if (wa.override_redirect)
|
|
|
|
return;
|
|
|
|
if (!wintoclient(ev->window))
|
|
|
|
manage(ev->window, &wa);
|
|
|
|
}
|
|
|
|
|
2019-09-15 22:32:28 +00:00
|
|
|
#if !FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
void
|
|
|
|
motionnotify(XEvent *e)
|
|
|
|
{
|
|
|
|
static Monitor *mon = NULL;
|
|
|
|
Monitor *m;
|
|
|
|
XMotionEvent *ev = &e->xmotion;
|
|
|
|
|
|
|
|
if (ev->window != root)
|
|
|
|
return;
|
|
|
|
if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) {
|
|
|
|
unfocus(selmon->sel, 1);
|
|
|
|
selmon = m;
|
|
|
|
focus(NULL);
|
|
|
|
}
|
|
|
|
mon = m;
|
|
|
|
}
|
2019-09-15 22:32:28 +00:00
|
|
|
#endif // FOCUSONCLICK_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
movemouse(const Arg *arg)
|
|
|
|
{
|
|
|
|
int x, y, ocx, ocy, nx, ny;
|
|
|
|
Client *c;
|
|
|
|
Monitor *m;
|
|
|
|
XEvent ev;
|
|
|
|
Time lasttime = 0;
|
|
|
|
|
|
|
|
if (!(c = selmon->sel))
|
|
|
|
return;
|
2019-10-08 21:15:11 +00:00
|
|
|
#if !FAKEFULLSCREEN_PATCH
|
2019-11-21 11:15:16 +00:00
|
|
|
#if FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
if (c->isfullscreen && !c->fakefullscreen) /* no support moving fullscreen windows by mouse */
|
|
|
|
return;
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (c->isfullscreen) /* no support moving fullscreen windows by mouse */
|
|
|
|
return;
|
2019-11-21 11:15:16 +00:00
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
2019-10-08 21:15:11 +00:00
|
|
|
#endif // FAKEFULLSCREEN_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
restack(selmon);
|
|
|
|
ocx = c->x;
|
|
|
|
ocy = c->y;
|
|
|
|
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
|
|
|
None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
|
|
|
|
return;
|
|
|
|
if (!getrootptr(&x, &y))
|
|
|
|
return;
|
|
|
|
do {
|
|
|
|
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
|
|
|
|
switch(ev.type) {
|
|
|
|
case ConfigureRequest:
|
|
|
|
case Expose:
|
|
|
|
case MapRequest:
|
|
|
|
handler[ev.type](&ev);
|
|
|
|
break;
|
|
|
|
case MotionNotify:
|
|
|
|
if ((ev.xmotion.time - lasttime) <= (1000 / 60))
|
|
|
|
continue;
|
|
|
|
lasttime = ev.xmotion.time;
|
|
|
|
|
|
|
|
nx = ocx + (ev.xmotion.x - x);
|
|
|
|
ny = ocy + (ev.xmotion.y - y);
|
|
|
|
if (abs(selmon->wx - nx) < snap)
|
|
|
|
nx = selmon->wx;
|
|
|
|
else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap)
|
|
|
|
nx = selmon->wx + selmon->ww - WIDTH(c);
|
|
|
|
if (abs(selmon->wy - ny) < snap)
|
|
|
|
ny = selmon->wy;
|
|
|
|
else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap)
|
|
|
|
ny = selmon->wy + selmon->wh - HEIGHT(c);
|
|
|
|
if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
|
|
|
|
&& (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
|
|
|
|
togglefloating(NULL);
|
2019-09-07 21:08:53 +00:00
|
|
|
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
|
2019-10-24 06:47:00 +00:00
|
|
|
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
resize(c, nx, ny, c->w, c->h, 1);
|
2019-09-07 21:08:53 +00:00
|
|
|
/* save last known float coordinates */
|
|
|
|
c->sfx = nx;
|
|
|
|
c->sfy = ny;
|
|
|
|
#else
|
|
|
|
resize(c, nx, ny, c->w, c->h, 1);
|
2019-10-24 06:47:00 +00:00
|
|
|
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
|
2019-09-07 21:08:53 +00:00
|
|
|
}
|
2020-03-31 06:21:00 +00:00
|
|
|
#if ROUNDED_CORNERS_PATCH
|
|
|
|
drawroundedcorners(c);
|
|
|
|
#endif // ROUNDED_CORNERS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (ev.type != ButtonRelease);
|
|
|
|
XUngrabPointer(dpy, CurrentTime);
|
|
|
|
if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
|
|
|
|
sendmon(c, m);
|
|
|
|
selmon = m;
|
|
|
|
focus(NULL);
|
|
|
|
}
|
2020-03-31 06:21:00 +00:00
|
|
|
#if ROUNDED_CORNERS_PATCH
|
|
|
|
drawroundedcorners(c);
|
|
|
|
#endif // ROUNDED_CORNERS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Client *
|
|
|
|
nexttiled(Client *c)
|
|
|
|
{
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_AWESOMEBAR_PATCH
|
2019-09-09 22:18:46 +00:00
|
|
|
for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_AWESOMEBAR_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2019-10-06 21:43:51 +00:00
|
|
|
#if !ZOOMSWAP_PATCH || TAGINTOSTACK_ALLMASTER_PATCH || TAGINTOSTACK_ONEMASTER_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
void
|
|
|
|
pop(Client *c)
|
|
|
|
{
|
|
|
|
detach(c);
|
|
|
|
attach(c);
|
|
|
|
focus(c);
|
|
|
|
arrange(c->mon);
|
|
|
|
}
|
2019-10-06 21:43:51 +00:00
|
|
|
#endif // !ZOOMSWAP_PATCH / TAGINTOSTACK_ALLMASTER_PATCH / TAGINTOSTACK_ONEMASTER_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
propertynotify(XEvent *e)
|
|
|
|
{
|
|
|
|
Client *c;
|
|
|
|
Window trans;
|
|
|
|
XPropertyEvent *ev = &e->xproperty;
|
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
if (showsystray && (c = wintosystrayicon(ev->window))) {
|
|
|
|
if (ev->atom == XA_WM_NORMAL_HINTS) {
|
|
|
|
updatesizehints(c);
|
|
|
|
updatesystrayicongeom(c, c->w, c->h);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
updatesystrayiconstate(c, ev);
|
|
|
|
updatesystray();
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
|
2019-10-07 21:34:23 +00:00
|
|
|
if ((ev->window == root) && (ev->atom == XA_WM_NAME)) {
|
2020-02-02 10:40:24 +00:00
|
|
|
#if DWMC_PATCH || FSIGNAL_PATCH
|
2019-10-07 21:34:23 +00:00
|
|
|
if (!fake_signal())
|
2020-02-02 10:40:24 +00:00
|
|
|
updatestatus();
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
updatestatus();
|
2020-02-02 10:40:24 +00:00
|
|
|
#endif // DWMC_PATCH / FSIGNAL_PATCH
|
2019-10-07 21:34:23 +00:00
|
|
|
} else if (ev->state == PropertyDelete) {
|
2019-09-04 22:16:39 +00:00
|
|
|
return; /* ignore */
|
2019-10-07 21:34:23 +00:00
|
|
|
} else if ((c = wintoclient(ev->window))) {
|
2019-09-04 22:16:39 +00:00
|
|
|
switch(ev->atom) {
|
|
|
|
default: break;
|
|
|
|
case XA_WM_TRANSIENT_FOR:
|
|
|
|
if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) &&
|
|
|
|
(c->isfloating = (wintoclient(trans)) != NULL))
|
|
|
|
arrange(c->mon);
|
|
|
|
break;
|
|
|
|
case XA_WM_NORMAL_HINTS:
|
|
|
|
updatesizehints(c);
|
|
|
|
break;
|
|
|
|
case XA_WM_HINTS:
|
|
|
|
updatewmhints(c);
|
|
|
|
drawbars();
|
2019-10-06 22:46:23 +00:00
|
|
|
#if URGENTBORDER_PATCH
|
|
|
|
if (c->isurgent)
|
|
|
|
XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColBorder].pixel);
|
|
|
|
#endif // URGENTBORDER_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
|
|
|
|
updatetitle(c);
|
|
|
|
if (c == c->mon->sel)
|
|
|
|
drawbar(c->mon);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
quit(const Arg *arg)
|
|
|
|
{
|
2019-10-03 20:58:58 +00:00
|
|
|
#if ONLYQUITONEMPTY_PATCH
|
|
|
|
unsigned int n;
|
|
|
|
Window *junk = malloc(1);
|
|
|
|
|
|
|
|
XQueryTree(dpy, root, junk, junk, &junk, &n);
|
|
|
|
|
2019-10-06 21:43:51 +00:00
|
|
|
if (n <= quit_empty_window_count) {
|
2019-10-03 20:58:58 +00:00
|
|
|
#if RESTARTSIG_PATCH
|
|
|
|
if (arg->i)
|
|
|
|
restart = 1;
|
|
|
|
#endif // RESTARTSIG_PATCH
|
|
|
|
running = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
printf("[dwm] not exiting (n=%d)\n", n);
|
|
|
|
|
|
|
|
free(junk);
|
|
|
|
#else
|
2019-10-02 21:22:04 +00:00
|
|
|
#if RESTARTSIG_PATCH
|
|
|
|
if (arg->i)
|
|
|
|
restart = 1;
|
|
|
|
#endif // RESTARTSIG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
running = 0;
|
2019-10-03 20:58:58 +00:00
|
|
|
#endif // ONLYQUITONEMPTY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Monitor *
|
|
|
|
recttomon(int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
Monitor *m, *r = selmon;
|
|
|
|
int a, area = 0;
|
|
|
|
|
|
|
|
for (m = mons; m; m = m->next)
|
|
|
|
if ((a = INTERSECT(x, y, w, h, m)) > area) {
|
|
|
|
area = a;
|
|
|
|
r = m;
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
resize(Client *c, int x, int y, int w, int h, int interact)
|
|
|
|
{
|
|
|
|
if (applysizehints(c, &x, &y, &w, &h, interact))
|
|
|
|
resizeclient(c, x, y, w, h);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
resizeclient(Client *c, int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
XWindowChanges wc;
|
|
|
|
|
|
|
|
c->oldx = c->x; c->x = wc.x = x;
|
|
|
|
c->oldy = c->y; c->y = wc.y = y;
|
|
|
|
c->oldw = c->w; c->w = wc.width = w;
|
|
|
|
c->oldh = c->h; c->h = wc.height = h;
|
2019-10-24 06:47:00 +00:00
|
|
|
#if EXRESIZE_PATCH
|
|
|
|
c->expandmask = 0;
|
|
|
|
#endif // EXRESIZE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
wc.border_width = c->bw;
|
2019-10-04 21:39:01 +00:00
|
|
|
#if NOBORDER_PATCH
|
|
|
|
if (((nexttiled(c->mon->clients) == c && !nexttiled(c->next))
|
2019-10-06 21:43:51 +00:00
|
|
|
#if MONOCLE_LAYOUT
|
|
|
|
|| &monocle == c->mon->lt[c->mon->sellt]->arrange
|
|
|
|
#endif // MONOCLE_LAYOUT
|
2020-06-10 10:24:46 +00:00
|
|
|
) && !c->isfullscreen && !c->isfloating
|
|
|
|
&& c->mon->lt[c->mon->sellt]->arrange) {
|
2019-10-04 21:39:01 +00:00
|
|
|
c->w = wc.width += c->bw * 2;
|
|
|
|
c->h = wc.height += c->bw * 2;
|
|
|
|
wc.border_width = 0;
|
|
|
|
}
|
|
|
|
#endif // NOBORDER_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
|
|
|
|
configure(c);
|
|
|
|
XSync(dpy, False);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
resizemouse(const Arg *arg)
|
|
|
|
{
|
|
|
|
int ocx, ocy, nw, nh;
|
2020-06-25 09:56:41 +00:00
|
|
|
#if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH
|
2020-06-24 12:49:30 +00:00
|
|
|
int opx, opy, och, ocw, nx, ny;
|
|
|
|
int horizcorner, vertcorner;
|
|
|
|
unsigned int dui;
|
|
|
|
Window dummy;
|
|
|
|
#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
Client *c;
|
|
|
|
Monitor *m;
|
|
|
|
XEvent ev;
|
|
|
|
Time lasttime = 0;
|
|
|
|
|
|
|
|
if (!(c = selmon->sel))
|
|
|
|
return;
|
2019-10-08 21:15:11 +00:00
|
|
|
#if !FAKEFULLSCREEN_PATCH
|
2019-11-21 11:15:16 +00:00
|
|
|
#if FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
if (c->isfullscreen && !c->fakefullscreen) /* no support resizing fullscreen windows by mouse */
|
|
|
|
return;
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */
|
|
|
|
return;
|
2019-11-21 11:15:16 +00:00
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
2019-10-08 21:15:11 +00:00
|
|
|
#endif // !FAKEFULLSCREEN_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
restack(selmon);
|
|
|
|
ocx = c->x;
|
|
|
|
ocy = c->y;
|
2020-06-24 12:49:30 +00:00
|
|
|
#if RESIZEPOINT_PATCH
|
|
|
|
och = c->h;
|
|
|
|
ocw = c->w;
|
|
|
|
#elif RESIZECORNERS_PATCH
|
2020-06-25 09:56:41 +00:00
|
|
|
och = c->y + c->h;
|
|
|
|
ocw = c->x + c->w;
|
2020-06-24 12:49:30 +00:00
|
|
|
#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
|
2020-06-25 09:56:41 +00:00
|
|
|
#if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH
|
2020-06-24 12:49:30 +00:00
|
|
|
if (!XQueryPointer(dpy, c->win, &dummy, &dummy, &opx, &opy, &nx, &ny, &dui))
|
|
|
|
return;
|
|
|
|
horizcorner = nx < c->w / 2;
|
|
|
|
vertcorner = ny < c->h / 2;
|
2020-06-25 09:56:41 +00:00
|
|
|
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
|
|
|
None, cursor[horizcorner | (vertcorner << 1)]->cursor, CurrentTime) != GrabSuccess)
|
2020-01-30 07:43:00 +00:00
|
|
|
return;
|
2020-06-25 09:56:41 +00:00
|
|
|
#if RESIZECORNERS_PATCH
|
2019-09-07 20:35:37 +00:00
|
|
|
XWarpPointer (dpy, None, c->win, 0, 0, 0, 0,
|
2019-10-24 04:52:00 +00:00
|
|
|
horizcorner ? (-c->bw) : (c->w + c->bw - 1),
|
|
|
|
vertcorner ? (-c->bw) : (c->h + c->bw - 1));
|
2020-06-25 09:56:41 +00:00
|
|
|
#endif // RESIZECORNERS_PATCH
|
2019-09-07 20:35:37 +00:00
|
|
|
#else
|
2020-06-25 09:56:41 +00:00
|
|
|
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
|
|
|
|
None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
|
|
|
|
return;
|
2019-09-04 22:16:39 +00:00
|
|
|
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
|
2020-06-24 12:49:30 +00:00
|
|
|
#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
do {
|
|
|
|
XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
|
|
|
|
switch(ev.type) {
|
|
|
|
case ConfigureRequest:
|
|
|
|
case Expose:
|
|
|
|
case MapRequest:
|
|
|
|
handler[ev.type](&ev);
|
|
|
|
break;
|
|
|
|
case MotionNotify:
|
|
|
|
if ((ev.xmotion.time - lasttime) <= (1000 / 60))
|
|
|
|
continue;
|
|
|
|
lasttime = ev.xmotion.time;
|
|
|
|
|
2020-06-24 12:49:30 +00:00
|
|
|
#if RESIZEPOINT_PATCH
|
|
|
|
nx = horizcorner ? (ocx + ev.xmotion.x - opx) : c->x;
|
|
|
|
ny = vertcorner ? (ocy + ev.xmotion.y - opy) : c->y;
|
|
|
|
nw = MAX(horizcorner ? (ocx + ocw - nx) : (ocw + (ev.xmotion.x - opx)), 1);
|
|
|
|
nh = MAX(vertcorner ? (ocy + och - ny) : (och + (ev.xmotion.y - opy)), 1);
|
|
|
|
#elif RESIZECORNERS_PATCH
|
2019-09-07 20:35:37 +00:00
|
|
|
nx = horizcorner ? ev.xmotion.x : c->x;
|
|
|
|
ny = vertcorner ? ev.xmotion.y : c->y;
|
2020-06-25 09:56:41 +00:00
|
|
|
nw = MAX(horizcorner ? (ocw - nx) : (ev.xmotion.x - ocx - 2 * c->bw + 1), 1);
|
|
|
|
nh = MAX(vertcorner ? (och - ny) : (ev.xmotion.y - ocy - 2 * c->bw + 1), 1);
|
2020-06-24 12:49:30 +00:00
|
|
|
#else
|
|
|
|
nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
|
|
|
|
nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
|
|
|
|
#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= selmon->wx + selmon->ww
|
|
|
|
&& c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= selmon->wy + selmon->wh)
|
|
|
|
{
|
|
|
|
if (!c->isfloating && selmon->lt[selmon->sellt]->arrange
|
|
|
|
&& (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
|
|
|
|
togglefloating(NULL);
|
|
|
|
}
|
2019-09-07 20:35:37 +00:00
|
|
|
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
|
2020-06-24 12:49:30 +00:00
|
|
|
#if RESIZECORNERS_PATCH || RESIZEPOINT_PATCH
|
|
|
|
resizeclient(c, nx, ny, nw, nh);
|
2019-10-24 06:47:00 +00:00
|
|
|
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
|
2020-01-30 07:43:00 +00:00
|
|
|
/* save last known float dimensions */
|
|
|
|
c->sfx = nx;
|
|
|
|
c->sfy = ny;
|
|
|
|
c->sfw = nw;
|
|
|
|
c->sfh = nh;
|
2019-10-24 06:47:00 +00:00
|
|
|
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
|
2019-09-07 20:35:37 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
resize(c, c->x, c->y, nw, nh, 1);
|
2019-10-24 06:47:00 +00:00
|
|
|
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
|
2019-09-07 21:08:53 +00:00
|
|
|
c->sfx = c->x;
|
|
|
|
c->sfy = c->y;
|
|
|
|
c->sfw = nw;
|
|
|
|
c->sfh = nh;
|
2019-10-24 06:47:00 +00:00
|
|
|
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
|
2019-09-07 20:35:37 +00:00
|
|
|
#endif // RESIZECORNERS_PATCH
|
2020-03-31 06:21:00 +00:00
|
|
|
#if ROUNDED_CORNERS_PATCH
|
|
|
|
drawroundedcorners(c);
|
|
|
|
#endif // ROUNDED_CORNERS_PATCH
|
2019-09-07 20:35:37 +00:00
|
|
|
}
|
2019-09-04 22:16:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} while (ev.type != ButtonRelease);
|
2020-06-24 12:49:30 +00:00
|
|
|
#if !RESIZEPOINT_PATCH
|
2019-09-07 20:35:37 +00:00
|
|
|
#if RESIZECORNERS_PATCH
|
|
|
|
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
|
2019-10-24 04:52:00 +00:00
|
|
|
horizcorner ? (-c->bw) : (c->w + c->bw - 1),
|
|
|
|
vertcorner ? (-c->bw) : (c->h + c->bw - 1));
|
2019-09-07 20:35:37 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1);
|
2019-09-07 20:35:37 +00:00
|
|
|
#endif // RESIZECORNERS_PATCH
|
2020-06-24 12:49:30 +00:00
|
|
|
#endif // RESIZEPOINT_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
XUngrabPointer(dpy, CurrentTime);
|
|
|
|
while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
|
|
|
|
if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
|
|
|
|
sendmon(c, m);
|
|
|
|
selmon = m;
|
|
|
|
focus(NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
restack(Monitor *m)
|
|
|
|
{
|
|
|
|
Client *c;
|
|
|
|
XEvent ev;
|
|
|
|
XWindowChanges wc;
|
|
|
|
|
|
|
|
drawbar(m);
|
|
|
|
if (!m->sel)
|
|
|
|
return;
|
|
|
|
if (m->sel->isfloating || !m->lt[m->sellt]->arrange)
|
|
|
|
XRaiseWindow(dpy, m->sel->win);
|
|
|
|
if (m->lt[m->sellt]->arrange) {
|
|
|
|
wc.stack_mode = Below;
|
2020-07-15 06:57:30 +00:00
|
|
|
wc.sibling = m->bars[0]->win;
|
2019-09-04 22:16:39 +00:00
|
|
|
for (c = m->stack; c; c = c->snext)
|
|
|
|
if (!c->isfloating && ISVISIBLE(c)) {
|
|
|
|
XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
|
|
|
|
wc.sibling = c->win;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
XSync(dpy, False);
|
|
|
|
while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
|
2019-09-14 22:43:35 +00:00
|
|
|
#if WARP_PATCH
|
2019-10-03 20:58:58 +00:00
|
|
|
if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[MONOCLE_LAYOUT_POS])
|
2019-09-14 22:43:35 +00:00
|
|
|
warp(m->sel);
|
|
|
|
#endif // WARP_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
run(void)
|
|
|
|
{
|
|
|
|
XEvent ev;
|
|
|
|
/* main event loop */
|
|
|
|
XSync(dpy, False);
|
|
|
|
while (running && !XNextEvent(dpy, &ev))
|
|
|
|
if (handler[ev.type])
|
|
|
|
handler[ev.type](&ev); /* call handler */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
scan(void)
|
|
|
|
{
|
|
|
|
unsigned int i, num;
|
|
|
|
Window d1, d2, *wins = NULL;
|
|
|
|
XWindowAttributes wa;
|
|
|
|
|
|
|
|
if (XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
|
|
|
|
for (i = 0; i < num; i++) {
|
|
|
|
if (!XGetWindowAttributes(dpy, wins[i], &wa)
|
|
|
|
|| wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
|
|
|
|
continue;
|
|
|
|
if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState)
|
|
|
|
manage(wins[i], &wa);
|
|
|
|
}
|
|
|
|
for (i = 0; i < num; i++) { /* now the transients */
|
|
|
|
if (!XGetWindowAttributes(dpy, wins[i], &wa))
|
|
|
|
continue;
|
|
|
|
if (XGetTransientForHint(dpy, wins[i], &d1)
|
|
|
|
&& (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
|
|
|
|
manage(wins[i], &wa);
|
|
|
|
}
|
2020-01-27 08:13:13 +00:00
|
|
|
XFree(wins);
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sendmon(Client *c, Monitor *m)
|
|
|
|
{
|
2019-10-24 06:47:00 +00:00
|
|
|
#if EXRESIZE_PATCH
|
|
|
|
Monitor *oldm = selmon;
|
|
|
|
#endif // EXRESIZE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (c->mon == m)
|
|
|
|
return;
|
2020-06-25 08:28:31 +00:00
|
|
|
#if SENDMON_KEEPFOCUS_PATCH && !EXRESIZE_PATCH
|
|
|
|
int hadfocus = (c == selmon->sel);
|
|
|
|
#endif // SENDMON_KEEPFOCUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
unfocus(c, 1);
|
|
|
|
detach(c);
|
|
|
|
detachstack(c);
|
2020-06-24 15:12:54 +00:00
|
|
|
#if SENDMON_KEEPFOCUS_PATCH && !EXRESIZE_PATCH
|
|
|
|
arrange(c->mon);
|
|
|
|
#endif // SENDMON_KEEPFOCUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
c->mon = m;
|
2019-10-02 21:22:04 +00:00
|
|
|
#if EMPTYVIEW_PATCH
|
|
|
|
c->tags = (m->tagset[m->seltags] ? m->tagset[m->seltags] : 1);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
|
2019-10-02 21:22:04 +00:00
|
|
|
#endif // EMPTYVIEW_PATCH
|
2019-09-06 21:25:32 +00:00
|
|
|
#if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH
|
|
|
|
attachx(c);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
attach(c);
|
2019-09-06 21:25:32 +00:00
|
|
|
#endif
|
2019-09-04 22:16:39 +00:00
|
|
|
attachstack(c);
|
2019-10-24 06:47:00 +00:00
|
|
|
#if EXRESIZE_PATCH
|
|
|
|
if (oldm != m)
|
|
|
|
arrange(oldm);
|
|
|
|
arrange(m);
|
|
|
|
focus(c);
|
|
|
|
restack(m);
|
2020-06-24 15:12:54 +00:00
|
|
|
#elif SENDMON_KEEPFOCUS_PATCH
|
|
|
|
arrange(m);
|
2020-06-25 08:28:31 +00:00
|
|
|
if (hadfocus) {
|
|
|
|
focus(c);
|
|
|
|
restack(m);
|
|
|
|
} else
|
|
|
|
focus(NULL);
|
2019-10-24 06:47:00 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
focus(NULL);
|
|
|
|
arrange(NULL);
|
2020-06-24 15:12:54 +00:00
|
|
|
#endif // EXRESIZE_PATCH / SENDMON_KEEPFOCUS_PATCH
|
2020-01-25 17:37:35 +00:00
|
|
|
#if SWITCHTAG_PATCH
|
|
|
|
if (c->switchtag)
|
|
|
|
c->switchtag = 0;
|
|
|
|
#endif // SWITCHTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setclientstate(Client *c, long state)
|
|
|
|
{
|
|
|
|
long data[] = { state, None };
|
|
|
|
|
|
|
|
XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
|
|
|
|
PropModeReplace, (unsigned char *)data, 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
sendevent(Window w, Atom proto, int mask, long d0, long d1, long d2, long d3, long d4)
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
sendevent(Client *c, Atom proto)
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
{
|
|
|
|
int n;
|
|
|
|
Atom *protocols;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
Atom mt;
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
int exists = 0;
|
|
|
|
XEvent ev;
|
|
|
|
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
if (proto == wmatom[WMTakeFocus] || proto == wmatom[WMDelete]) {
|
|
|
|
mt = wmatom[WMProtocols];
|
|
|
|
if (XGetWMProtocols(dpy, w, &protocols, &n)) {
|
|
|
|
while (!exists && n--)
|
|
|
|
exists = protocols[n] == proto;
|
|
|
|
XFree(protocols);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
exists = True;
|
|
|
|
mt = proto;
|
|
|
|
}
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (XGetWMProtocols(dpy, c->win, &protocols, &n)) {
|
|
|
|
while (!exists && n--)
|
|
|
|
exists = protocols[n] == proto;
|
|
|
|
XFree(protocols);
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
if (exists) {
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
ev.type = ClientMessage;
|
|
|
|
ev.xclient.window = w;
|
|
|
|
ev.xclient.message_type = mt;
|
|
|
|
ev.xclient.format = 32;
|
|
|
|
ev.xclient.data.l[0] = d0;
|
|
|
|
ev.xclient.data.l[1] = d1;
|
|
|
|
ev.xclient.data.l[2] = d2;
|
|
|
|
ev.xclient.data.l[3] = d3;
|
|
|
|
ev.xclient.data.l[4] = d4;
|
|
|
|
XSendEvent(dpy, w, False, mask, &ev);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
ev.type = ClientMessage;
|
|
|
|
ev.xclient.window = c->win;
|
|
|
|
ev.xclient.message_type = wmatom[WMProtocols];
|
|
|
|
ev.xclient.format = 32;
|
|
|
|
ev.xclient.data.l[0] = proto;
|
|
|
|
ev.xclient.data.l[1] = CurrentTime;
|
|
|
|
XSendEvent(dpy, c->win, False, NoEventMask, &ev);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
return exists;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setfocus(Client *c)
|
|
|
|
{
|
|
|
|
if (!c->neverfocus) {
|
|
|
|
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
|
|
|
|
XChangeProperty(dpy, root, netatom[NetActiveWindow],
|
|
|
|
XA_WINDOW, 32, PropModeReplace,
|
|
|
|
(unsigned char *) &(c->win), 1);
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
sendevent(c->win, wmatom[WMTakeFocus], NoEventMask, wmatom[WMTakeFocus], CurrentTime, 0, 0, 0);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
sendevent(c, wmatom[WMTakeFocus]);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setfullscreen(Client *c, int fullscreen)
|
|
|
|
{
|
|
|
|
if (fullscreen && !c->isfullscreen) {
|
|
|
|
XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
|
|
|
|
PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
|
|
|
|
c->isfullscreen = 1;
|
2019-10-08 21:15:11 +00:00
|
|
|
#if !FAKEFULLSCREEN_PATCH
|
2019-11-21 11:15:16 +00:00
|
|
|
#if FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
if (!c->fakefullscreen) {
|
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
c->oldstate = c->isfloating;
|
|
|
|
c->oldbw = c->bw;
|
|
|
|
c->bw = 0;
|
|
|
|
c->isfloating = 1;
|
|
|
|
resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
|
|
|
|
XRaiseWindow(dpy, c->win);
|
2019-11-21 11:15:16 +00:00
|
|
|
#if FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
}
|
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
2019-10-08 21:15:11 +00:00
|
|
|
#endif // !FAKEFULLSCREEN_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
} else if (!fullscreen && c->isfullscreen){
|
|
|
|
XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
|
|
|
|
PropModeReplace, (unsigned char*)0, 0);
|
|
|
|
c->isfullscreen = 0;
|
2019-10-08 21:15:11 +00:00
|
|
|
#if !FAKEFULLSCREEN_PATCH
|
2019-11-21 11:15:16 +00:00
|
|
|
#if FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
if (!c->fakefullscreen) {
|
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
c->isfloating = c->oldstate;
|
|
|
|
c->bw = c->oldbw;
|
|
|
|
c->x = c->oldx;
|
|
|
|
c->y = c->oldy;
|
|
|
|
c->w = c->oldw;
|
|
|
|
c->h = c->oldh;
|
|
|
|
resizeclient(c, c->x, c->y, c->w, c->h);
|
|
|
|
arrange(c->mon);
|
2019-11-21 11:15:16 +00:00
|
|
|
#if FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
}
|
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
2019-10-08 21:15:11 +00:00
|
|
|
#endif // !FAKEFULLSCREEN_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setlayout(const Arg *arg)
|
|
|
|
{
|
2019-09-05 20:58:16 +00:00
|
|
|
if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) {
|
|
|
|
#if PERTAG_PATCH
|
|
|
|
selmon->pertag->sellts[selmon->pertag->curtag] ^= 1;
|
|
|
|
selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
selmon->sellt ^= 1;
|
2019-09-05 20:58:16 +00:00
|
|
|
#endif // PERTAG_PATCH
|
2019-10-24 06:47:00 +00:00
|
|
|
#if EXRESIZE_PATCH
|
|
|
|
if (!selmon->lt[selmon->sellt]->arrange) {
|
|
|
|
for (Client *c = selmon->clients ; c ; c = c->next) {
|
|
|
|
if (!c->isfloating) {
|
|
|
|
/*restore last known float dimensions*/
|
|
|
|
resize(c, selmon->mx + c->sfx, selmon->my + c->sfy,
|
|
|
|
c->sfw, c->sfh, False);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif // EXRESIZE_PATCH
|
2019-09-05 20:58:16 +00:00
|
|
|
}
|
2019-09-04 22:16:39 +00:00
|
|
|
if (arg && arg->v)
|
2019-09-05 20:58:16 +00:00
|
|
|
#if PERTAG_PATCH
|
|
|
|
selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt] = (Layout *)arg->v;
|
|
|
|
selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
selmon->lt[selmon->sellt] = (Layout *)arg->v;
|
2019-09-05 20:58:16 +00:00
|
|
|
#endif // PERTAG_PATCH
|
2019-09-30 21:52:51 +00:00
|
|
|
|
|
|
|
#if FLEXTILE_DELUXE_LAYOUT
|
2020-03-27 19:46:54 +00:00
|
|
|
if (selmon->lt[selmon->sellt]->preset.nmaster && selmon->lt[selmon->sellt]->preset.nmaster != -1)
|
2019-09-30 21:52:51 +00:00
|
|
|
selmon->nmaster = selmon->lt[selmon->sellt]->preset.nmaster;
|
2020-03-27 19:46:54 +00:00
|
|
|
if (selmon->lt[selmon->sellt]->preset.nstack && selmon->lt[selmon->sellt]->preset.nstack != -1)
|
2019-09-30 21:52:51 +00:00
|
|
|
selmon->nstack = selmon->lt[selmon->sellt]->preset.nstack;
|
|
|
|
|
|
|
|
selmon->ltaxis[LAYOUT] = selmon->lt[selmon->sellt]->preset.layout;
|
|
|
|
selmon->ltaxis[MASTER] = selmon->lt[selmon->sellt]->preset.masteraxis;
|
|
|
|
selmon->ltaxis[STACK] = selmon->lt[selmon->sellt]->preset.stack1axis;
|
|
|
|
selmon->ltaxis[STACK2] = selmon->lt[selmon->sellt]->preset.stack2axis;
|
|
|
|
|
|
|
|
#if PERTAG_PATCH
|
|
|
|
selmon->pertag->ltaxis[selmon->pertag->curtag][LAYOUT] = selmon->ltaxis[LAYOUT];
|
|
|
|
selmon->pertag->ltaxis[selmon->pertag->curtag][MASTER] = selmon->ltaxis[MASTER];
|
|
|
|
selmon->pertag->ltaxis[selmon->pertag->curtag][STACK] = selmon->ltaxis[STACK];
|
|
|
|
selmon->pertag->ltaxis[selmon->pertag->curtag][STACK2] = selmon->ltaxis[STACK2];
|
|
|
|
#endif // PERTAG_PATCH
|
|
|
|
#endif // FLEXTILE_DELUXE_LAYOUT
|
2019-09-04 22:16:39 +00:00
|
|
|
strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
|
|
|
|
if (selmon->sel)
|
|
|
|
arrange(selmon);
|
|
|
|
else
|
|
|
|
drawbar(selmon);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* arg > 1.0 will set mfact absolutely */
|
|
|
|
void
|
|
|
|
setmfact(const Arg *arg)
|
|
|
|
{
|
|
|
|
float f;
|
|
|
|
|
|
|
|
if (!arg || !selmon->lt[selmon->sellt]->arrange)
|
|
|
|
return;
|
|
|
|
f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
|
2020-04-20 16:40:25 +00:00
|
|
|
if (f < 0.05 || f > 0.95)
|
2019-09-04 22:16:39 +00:00
|
|
|
return;
|
2019-09-05 20:58:16 +00:00
|
|
|
#if PERTAG_PATCH
|
|
|
|
selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag] = f;
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
selmon->mfact = f;
|
2019-09-05 20:58:16 +00:00
|
|
|
#endif // PERTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
arrange(selmon);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setup(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
XSetWindowAttributes wa;
|
|
|
|
Atom utf8string;
|
|
|
|
|
|
|
|
/* clean up any zombies immediately */
|
|
|
|
sigchld(0);
|
|
|
|
|
2019-10-02 21:22:04 +00:00
|
|
|
#if RESTARTSIG_PATCH
|
|
|
|
signal(SIGHUP, sighup);
|
|
|
|
signal(SIGTERM, sigterm);
|
|
|
|
#endif // RESTARTSIG_PATCH
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
/* init screen */
|
|
|
|
screen = DefaultScreen(dpy);
|
|
|
|
sw = DisplayWidth(dpy, screen);
|
|
|
|
sh = DisplayHeight(dpy, screen);
|
|
|
|
root = RootWindow(dpy, screen);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_ALPHA_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
xinitvisual();
|
|
|
|
drw = drw_create(dpy, screen, root, sw, sh, visual, depth, cmap);
|
|
|
|
#else
|
|
|
|
drw = drw_create(dpy, screen, root, sw, sh);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_ALPHA_PATCH
|
|
|
|
#if BAR_PANGO_PATCH
|
2020-06-11 17:42:00 +00:00
|
|
|
if (!drw_font_create(drw, font))
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_PANGO_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
die("no fonts could be loaded.");
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUSPADDING_PATCH && BAR_PANGO_PATCH
|
2020-06-11 17:42:00 +00:00
|
|
|
lrpad = drw->font->h + horizpadbar;
|
|
|
|
bh = drw->font->h + vertpadbar;
|
2020-07-15 06:57:30 +00:00
|
|
|
#elif BAR_STATUSPADDING_PATCH
|
2019-09-07 21:29:37 +00:00
|
|
|
lrpad = drw->fonts->h + horizpadbar;
|
|
|
|
bh = drw->fonts->h + vertpadbar;
|
2020-07-15 06:57:30 +00:00
|
|
|
#elif BAR_PANGO_PATCH
|
2020-06-11 17:42:00 +00:00
|
|
|
lrpad = drw->font->h;
|
|
|
|
bh = drw->font->h + 2;
|
2019-09-07 21:29:37 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
lrpad = drw->fonts->h;
|
2020-06-21 18:04:56 +00:00
|
|
|
#if BAR_HEIGHT_PATCH
|
|
|
|
bh = bar_height ? bar_height : drw->fonts->h + 2;
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
bh = drw->fonts->h + 2;
|
2020-06-21 18:04:56 +00:00
|
|
|
#endif // BAR_HEIGHT_PATCH
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSPADDING_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
updategeom();
|
|
|
|
/* init atoms */
|
|
|
|
utf8string = XInternAtom(dpy, "UTF8_STRING", False);
|
|
|
|
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
|
|
|
|
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
|
|
|
|
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
|
|
|
|
wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
|
2019-09-07 21:46:08 +00:00
|
|
|
#if WINDOWROLERULE_PATCH
|
|
|
|
wmatom[WMWindowRole] = XInternAtom(dpy, "WM_WINDOW_ROLE", False);
|
|
|
|
#endif // WINDOWROLERULE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
|
|
|
|
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
netatom[NetSystemTray] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_S0", False);
|
|
|
|
netatom[NetSystemTrayOP] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE", False);
|
|
|
|
netatom[NetSystemTrayOrientation] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION", False);
|
|
|
|
netatom[NetSystemTrayOrientationHorz] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_ORIENTATION_HORZ", False);
|
|
|
|
netatom[NetSystemTrayVisual] = XInternAtom(dpy, "_NET_SYSTEM_TRAY_VISUAL", False);
|
|
|
|
netatom[NetWMWindowTypeDock] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
|
|
|
|
xatom[Manager] = XInternAtom(dpy, "MANAGER", False);
|
|
|
|
xatom[Xembed] = XInternAtom(dpy, "_XEMBED", False);
|
|
|
|
xatom[XembedInfo] = XInternAtom(dpy, "_XEMBED_INFO", False);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
|
|
|
#if BAR_EWMHTAGS_PATCH
|
2019-09-11 22:48:29 +00:00
|
|
|
netatom[NetDesktopViewport] = XInternAtom(dpy, "_NET_DESKTOP_VIEWPORT", False);
|
|
|
|
netatom[NetNumberOfDesktops] = XInternAtom(dpy, "_NET_NUMBER_OF_DESKTOPS", False);
|
|
|
|
netatom[NetCurrentDesktop] = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
|
|
|
|
netatom[NetDesktopNames] = XInternAtom(dpy, "_NET_DESKTOP_NAMES", False);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EWMHTAGS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
|
|
|
|
netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
|
|
|
|
netatom[NetWMCheck] = XInternAtom(dpy, "_NET_SUPPORTING_WM_CHECK", False);
|
|
|
|
netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
|
|
|
|
netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
|
|
|
|
netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
|
|
|
|
/* init cursors */
|
|
|
|
cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr);
|
|
|
|
cursor[CurResize] = drw_cur_create(drw, XC_sizing);
|
2020-06-25 09:56:41 +00:00
|
|
|
#if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH
|
|
|
|
cursor[CurResizeBR] = drw_cur_create(drw, XC_bottom_right_corner);
|
|
|
|
cursor[CurResizeBL] = drw_cur_create(drw, XC_bottom_left_corner);
|
|
|
|
cursor[CurResizeTR] = drw_cur_create(drw, XC_top_right_corner);
|
|
|
|
cursor[CurResizeTL] = drw_cur_create(drw, XC_top_left_corner);
|
|
|
|
#endif // RESIZEPOINT_PATCH | RESIZECORNERS_PATCH
|
|
|
|
#if DRAGMFACT_PATCH
|
|
|
|
cursor[CurResizeHorzArrow] = drw_cur_create(drw, XC_sb_h_double_arrow);
|
|
|
|
cursor[CurResizeVertArrow] = drw_cur_create(drw, XC_sb_v_double_arrow);
|
|
|
|
#endif // DRAGMFACT_PATCH
|
|
|
|
#if DRAGCFACT_PATCH
|
|
|
|
cursor[CurIronCross] = drw_cur_create(drw, XC_iron_cross);
|
|
|
|
#endif // DRAGCFACT_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
cursor[CurMove] = drw_cur_create(drw, XC_fleur);
|
|
|
|
/* init appearance */
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_VTCOLORS_PATCH
|
2020-02-11 17:31:11 +00:00
|
|
|
get_vt_colors();
|
|
|
|
if (get_luminance(colors[SchemeTagsNorm][ColBg]) > 50) {
|
|
|
|
strcpy(colors[SchemeTitleNorm][ColBg], title_bg_light);
|
|
|
|
strcpy(colors[SchemeTitleSel][ColBg], title_bg_light);
|
|
|
|
} else {
|
|
|
|
strcpy(colors[SchemeTitleNorm][ColBg], title_bg_dark);
|
|
|
|
strcpy(colors[SchemeTitleSel][ColBg], title_bg_dark);
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_VTCOLORS_PATCH
|
|
|
|
#if BAR_STATUS2D_PATCH && !BAR_STATUSCOLORS_PATCH
|
2020-05-26 18:53:53 +00:00
|
|
|
scheme = ecalloc(LENGTH(colors) + 1, sizeof(Clr *));
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_ALPHA_PATCH
|
2020-05-26 18:53:53 +00:00
|
|
|
scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], alphas[0], ColCount);
|
|
|
|
#else
|
|
|
|
scheme[LENGTH(colors)] = drw_scm_create(drw, colors[0], ColCount);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_ALPHA_PATCH | FLOAT_BORDER_COLOR_PATCH
|
2020-05-26 18:53:53 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUS2D_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
for (i = 0; i < LENGTH(colors); i++)
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_ALPHA_PATCH
|
2020-05-26 18:53:53 +00:00
|
|
|
scheme[i] = drw_scm_create(drw, colors[i], alphas[i], ColCount);
|
2019-09-10 22:51:37 +00:00
|
|
|
#else
|
2020-05-26 18:53:53 +00:00
|
|
|
scheme[i] = drw_scm_create(drw, colors[i], ColCount);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_ALPHA_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
updatebars();
|
|
|
|
updatestatus();
|
2020-07-15 06:57:30 +00:00
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
/* supporting window for NetWMCheck */
|
|
|
|
wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0);
|
|
|
|
XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32,
|
|
|
|
PropModeReplace, (unsigned char *) &wmcheckwin, 1);
|
|
|
|
XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8,
|
|
|
|
PropModeReplace, (unsigned char *) "dwm", 3);
|
|
|
|
XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
|
|
|
|
PropModeReplace, (unsigned char *) &wmcheckwin, 1);
|
|
|
|
/* EWMH support per view */
|
|
|
|
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
|
|
|
|
PropModeReplace, (unsigned char *) netatom, NetLast);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EWMHTAGS_PATCH
|
2019-09-11 22:48:29 +00:00
|
|
|
setnumdesktops();
|
|
|
|
setcurrentdesktop();
|
|
|
|
setdesktopnames();
|
|
|
|
setviewport();
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EWMHTAGS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
XDeleteProperty(dpy, root, netatom[NetClientList]);
|
|
|
|
/* select events */
|
|
|
|
wa.cursor = cursor[CurNormal]->cursor;
|
|
|
|
wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
|
|
|
|
|ButtonPressMask|PointerMotionMask|EnterWindowMask
|
|
|
|
|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
|
|
|
|
XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
|
|
|
|
XSelectInput(dpy, root, wa.event_mask);
|
|
|
|
grabkeys();
|
|
|
|
focus(NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
seturgent(Client *c, int urg)
|
|
|
|
{
|
|
|
|
XWMHints *wmh;
|
|
|
|
|
|
|
|
c->isurgent = urg;
|
|
|
|
if (!(wmh = XGetWMHints(dpy, c->win)))
|
|
|
|
return;
|
|
|
|
wmh->flags = urg ? (wmh->flags | XUrgencyHint) : (wmh->flags & ~XUrgencyHint);
|
|
|
|
XSetWMHints(dpy, c->win, wmh);
|
|
|
|
XFree(wmh);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
showhide(Client *c)
|
|
|
|
{
|
|
|
|
if (!c)
|
|
|
|
return;
|
|
|
|
if (ISVISIBLE(c)) {
|
2020-06-05 09:23:22 +00:00
|
|
|
#if SCRATCHPADS_PATCH && !SCRATCHPAD_KEEP_POSITION_AND_SIZE_PATCH
|
[dwm][PATCH] Multiple scratchpads
This patch enables multiple scratchpads, each with one assigned window.
This enables the same scratchpad workflow that you have in i3.
Scratchpads are implemented as special tags, whose mask does not
apply to new spawned windows. To assign a window to a scratchpad you
have to set up a rule, as you do with regular tags.
Windows tagged with scratchpad tags can be set floating or not in the
rules array. Most users would probably want them floating (i3 style),
but having them tiled does also perfectly work and might fit better the
DWM approach. In case they are set floating, the patch moves them to the
center of the screen whenever the are shown. The patch can easily be
modified to make this last feature configurable in the rules array (see
the center patch).
The togglescratch function, borrowed from the previous scratchpad patch
and slightly modified, can be used to spawn a registered scratchpad
process or toggle its view. This function looks for a window tagged on
the selected scratchpad. If it is found its view is toggled. If it is
not found the corresponding registered command is spawned. The
config.def.h shows three examples of its use to spawn a terminal in the
first scratchpad tag, a second terminal running ranger on the second
scratchpad tag and the keepassxc application to manage passwords on a
third scratchpad tag.
If you prefer to spawn your scratchpad applications from the startup
script, you might opt for binding keys to toggleview instead, as
scratchpads are just special tags (you may even extend the TAGKEYS macro
to generalize the key bindings).
2020-04-16 14:39:22 +00:00
|
|
|
if ((c->tags & SPTAGMASK) && c->isfloating) {
|
|
|
|
c->x = c->mon->wx + (c->mon->ww / 2 - WIDTH(c) / 2);
|
|
|
|
c->y = c->mon->wy + (c->mon->wh / 2 - HEIGHT(c) / 2);
|
|
|
|
}
|
2020-06-05 09:23:22 +00:00
|
|
|
#endif // SCRATCHPADS_PATCH | SCRATCHPAD_KEEP_POSITION_AND_SIZE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
/* show clients top down */
|
2019-10-24 06:47:00 +00:00
|
|
|
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
|
2019-09-07 21:08:53 +00:00
|
|
|
if (!c->mon->lt[c->mon->sellt]->arrange && c->sfx != -9999 && !c->isfullscreen) {
|
|
|
|
XMoveWindow(dpy, c->win, c->sfx, c->sfy);
|
|
|
|
resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0);
|
|
|
|
showhide(c->snext);
|
|
|
|
return;
|
|
|
|
}
|
2019-10-24 06:47:00 +00:00
|
|
|
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
|
2019-09-12 22:06:54 +00:00
|
|
|
#if AUTORESIZE_PATCH
|
|
|
|
if (c->needresize) {
|
|
|
|
c->needresize = 0;
|
|
|
|
XMoveResizeWindow(dpy, c->win, c->x, c->y, c->w, c->h);
|
|
|
|
} else {
|
|
|
|
XMoveWindow(dpy, c->win, c->x, c->y);
|
|
|
|
}
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
XMoveWindow(dpy, c->win, c->x, c->y);
|
2019-09-12 22:06:54 +00:00
|
|
|
#endif // AUTORESIZE_PATCH
|
2019-10-08 21:15:11 +00:00
|
|
|
if ((!c->mon->lt[c->mon->sellt]->arrange || c->isfloating)
|
|
|
|
#if !FAKEFULLSCREEN_PATCH
|
|
|
|
&& !c->isfullscreen
|
|
|
|
#endif // !FAKEFULLSCREEN_PATCH
|
|
|
|
)
|
2019-09-04 22:16:39 +00:00
|
|
|
resize(c, c->x, c->y, c->w, c->h, 0);
|
|
|
|
showhide(c->snext);
|
|
|
|
} else {
|
|
|
|
/* hide clients bottom up */
|
|
|
|
showhide(c->snext);
|
|
|
|
XMoveWindow(dpy, c->win, WIDTH(c) * -2, c->y);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
sigchld(int unused)
|
|
|
|
{
|
|
|
|
if (signal(SIGCHLD, sigchld) == SIG_ERR)
|
|
|
|
die("can't install SIGCHLD handler:");
|
|
|
|
while (0 < waitpid(-1, NULL, WNOHANG));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
spawn(const Arg *arg)
|
|
|
|
{
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUSCMD_PATCH && !BAR_DWMBLOCKS_PATCH
|
2020-04-13 12:59:58 +00:00
|
|
|
char *cmd = NULL;
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSCMD_PATCH | BAR_DWMBLOCKS_PATCH
|
2019-10-24 06:03:00 +00:00
|
|
|
#if !NODMENU_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (arg->v == dmenucmd)
|
|
|
|
dmenumon[0] = '0' + selmon->num;
|
2019-10-24 06:03:00 +00:00
|
|
|
#endif // NODMENU_PATCH
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUSCMD_PATCH && !BAR_DWMBLOCKS_PATCH
|
2020-04-13 12:59:58 +00:00
|
|
|
#if !NODMENU_PATCH
|
|
|
|
else if (arg->v == statuscmd)
|
|
|
|
#else
|
|
|
|
if (arg->v == statuscmd)
|
|
|
|
#endif // NODMENU_PATCH
|
|
|
|
{
|
|
|
|
int len = strlen(statuscmds[statuscmdn]) + 1;
|
|
|
|
if (!(cmd = malloc(sizeof(char)*len + sizeof(statusexport))))
|
|
|
|
die("malloc:");
|
|
|
|
strcpy(cmd, statusexport);
|
|
|
|
strcat(cmd, statuscmds[statuscmdn]);
|
|
|
|
cmd[LENGTH(statusexport)-3] = '0' + lastbutton;
|
|
|
|
statuscmd[2] = cmd;
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSCMD_PATCH | BAR_DWMBLOCKS_PATCH
|
2020-04-13 12:59:58 +00:00
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
if (fork() == 0) {
|
|
|
|
if (dpy)
|
|
|
|
close(ConnectionNumber(dpy));
|
2019-10-10 21:50:30 +00:00
|
|
|
#if SPAWNCMD_PATCH
|
|
|
|
if (selmon->sel) {
|
|
|
|
const char* const home = getenv("HOME");
|
|
|
|
assert(home && strchr(home, '/'));
|
|
|
|
const size_t homelen = strlen(home);
|
|
|
|
char *cwd, *pathbuf = NULL;
|
|
|
|
struct stat statbuf;
|
|
|
|
|
|
|
|
cwd = strtok(selmon->sel->name, SPAWN_CWD_DELIM);
|
|
|
|
/* NOTE: strtok() alters selmon->sel->name in-place,
|
|
|
|
* but that does not matter because we are going to
|
|
|
|
* exec() below anyway; nothing else will use it */
|
|
|
|
while (cwd) {
|
|
|
|
if (*cwd == '~') { /* replace ~ with $HOME */
|
|
|
|
if (!(pathbuf = malloc(homelen + strlen(cwd)))) /* ~ counts for NULL term */
|
|
|
|
die("fatal: could not malloc() %u bytes\n", homelen + strlen(cwd));
|
|
|
|
strcpy(strcpy(pathbuf, home) + homelen, cwd + 1);
|
|
|
|
cwd = pathbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strchr(cwd, '/') && !stat(cwd, &statbuf)) {
|
|
|
|
if (!S_ISDIR(statbuf.st_mode))
|
|
|
|
cwd = dirname(cwd);
|
|
|
|
|
|
|
|
if (!chdir(cwd))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cwd = strtok(NULL, SPAWN_CWD_DELIM);
|
|
|
|
}
|
|
|
|
|
|
|
|
free(pathbuf);
|
|
|
|
}
|
|
|
|
#endif // SPAWNCMD_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
setsid();
|
|
|
|
execvp(((char **)arg->v)[0], (char **)arg->v);
|
|
|
|
fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
|
|
|
|
perror(" failed");
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUSCMD_PATCH && !BAR_DWMBLOCKS_PATCH
|
2020-04-13 12:59:58 +00:00
|
|
|
free(cmd);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSCMD_PATCH | BAR_DWMBLOCKS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tag(const Arg *arg)
|
|
|
|
{
|
2020-01-30 07:43:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
unsigned int tagmask, tagindex;
|
|
|
|
#endif // SWAPFOCUS_PATCH
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
if (selmon->sel && arg->ui & TAGMASK) {
|
|
|
|
selmon->sel->tags = arg->ui & TAGMASK;
|
2020-05-20 13:25:56 +00:00
|
|
|
#if SWITCHTAG_PATCH
|
|
|
|
if (selmon->sel->switchtag)
|
|
|
|
selmon->sel->switchtag = 0;
|
|
|
|
#endif // SWITCHTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
focus(NULL);
|
2020-01-29 07:31:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
selmon->pertag->prevclient[selmon->pertag->curtag] = NULL;
|
2020-01-30 07:43:00 +00:00
|
|
|
for (tagmask = arg->ui & TAGMASK, tagindex = 1; tagmask!=0; tagmask >>= 1, tagindex++)
|
|
|
|
if (tagmask & 1)
|
|
|
|
selmon->pertag->prevclient[tagindex] = NULL;
|
2020-01-29 07:31:00 +00:00
|
|
|
#endif // SWAPFOCUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
arrange(selmon);
|
2019-09-15 21:42:47 +00:00
|
|
|
#if VIEWONTAG_PATCH
|
|
|
|
view(arg);
|
|
|
|
#endif // VIEWONTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
tagmon(const Arg *arg)
|
|
|
|
{
|
2019-09-05 21:39:25 +00:00
|
|
|
#if TAGMONFIXFS_PATCH
|
|
|
|
Client *c = selmon->sel;
|
|
|
|
if (!c || !mons->next)
|
|
|
|
return;
|
|
|
|
if (c->isfullscreen) {
|
2020-04-27 18:41:38 +00:00
|
|
|
c->isfullscreen = 0;
|
|
|
|
sendmon(c, dirtomon(arg->i));
|
|
|
|
c->isfullscreen = 1;
|
|
|
|
#if FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
if (!c->fakefullscreen) {
|
|
|
|
resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
|
|
|
|
XRaiseWindow(dpy, c->win);
|
|
|
|
}
|
|
|
|
#elif !FAKEFULLSCREEN_PATCH
|
|
|
|
resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
|
|
|
|
XRaiseWindow(dpy, c->win);
|
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
} else
|
|
|
|
sendmon(c, dirtomon(arg->i));
|
2019-09-05 21:39:25 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!selmon->sel || !mons->next)
|
|
|
|
return;
|
|
|
|
sendmon(selmon->sel, dirtomon(arg->i));
|
2019-09-05 21:39:25 +00:00
|
|
|
#endif // TAGMONFIXFS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
togglebar(const Arg *arg)
|
|
|
|
{
|
2020-07-15 06:57:30 +00:00
|
|
|
int b;
|
|
|
|
#if BAR_HOLDBAR_PATCH && PERTAG_PATCH && PERTAGBAR_PATCH
|
2020-06-30 08:15:36 +00:00
|
|
|
selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = (selmon->showbar == 2 ? 1 : !selmon->showbar);
|
2020-07-15 06:57:30 +00:00
|
|
|
#elif BAR_HOLDBAR_PATCH
|
2020-06-30 08:15:36 +00:00
|
|
|
selmon->showbar = (selmon->showbar == 2 ? 1 : !selmon->showbar);
|
|
|
|
#elif PERTAG_PATCH && PERTAGBAR_PATCH
|
2019-09-05 20:58:16 +00:00
|
|
|
selmon->showbar = selmon->pertag->showbars[selmon->pertag->curtag] = !selmon->showbar;
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
selmon->showbar = !selmon->showbar;
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_HOLDBAR_PATCH | PERTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
updatebarpos(selmon);
|
2020-07-15 06:57:30 +00:00
|
|
|
for (b = 0; b < LENGTH(selmon->bars); b++)
|
|
|
|
if (selmon->bars[b]->win)
|
|
|
|
XMoveResizeWindow(dpy, selmon->bars[b]->win, selmon->bars[b]->bx, selmon->bars[b]->by, selmon->bars[b]->bw, selmon->bars[b]->bh);
|
2019-09-04 22:16:39 +00:00
|
|
|
arrange(selmon);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
togglefloating(const Arg *arg)
|
|
|
|
{
|
|
|
|
if (!selmon->sel)
|
|
|
|
return;
|
2019-10-08 21:15:11 +00:00
|
|
|
#if !FAKEFULLSCREEN_PATCH
|
2019-11-21 11:15:16 +00:00
|
|
|
#if FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
if (selmon->sel->isfullscreen && !selmon->sel->fakefullscreen) /* no support for fullscreen windows */
|
|
|
|
return;
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (selmon->sel->isfullscreen) /* no support for fullscreen windows */
|
|
|
|
return;
|
2019-11-21 11:15:16 +00:00
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
2019-10-08 21:15:11 +00:00
|
|
|
#endif // !FAKEFULLSCREEN_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed;
|
2019-09-10 22:51:37 +00:00
|
|
|
#if FLOAT_BORDER_COLOR_PATCH
|
|
|
|
if (selmon->sel->isfloating)
|
|
|
|
XSetWindowBorder(dpy, selmon->sel->win, scheme[SchemeSel][ColFloat].pixel);
|
|
|
|
else
|
|
|
|
XSetWindowBorder(dpy, selmon->sel->win, scheme[SchemeSel][ColBorder].pixel);
|
|
|
|
#endif // FLOAT_BORDER_COLOR_PATCH
|
2019-09-07 21:08:53 +00:00
|
|
|
if (selmon->sel->isfloating) {
|
2019-10-24 06:47:00 +00:00
|
|
|
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
|
2019-09-07 21:08:53 +00:00
|
|
|
if (selmon->sel->sfx != -9999) {
|
|
|
|
/* restore last known float dimensions */
|
|
|
|
resize(selmon->sel, selmon->sel->sfx, selmon->sel->sfy,
|
|
|
|
selmon->sel->sfw, selmon->sel->sfh, 0);
|
|
|
|
arrange(selmon);
|
|
|
|
return;
|
|
|
|
}
|
2019-10-24 06:47:00 +00:00
|
|
|
#endif // SAVEFLOATS_PATCH // EXRESIZE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
resize(selmon->sel, selmon->sel->x, selmon->sel->y,
|
|
|
|
selmon->sel->w, selmon->sel->h, 0);
|
2019-10-24 06:47:00 +00:00
|
|
|
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
|
2019-09-07 21:08:53 +00:00
|
|
|
} else {
|
|
|
|
/* save last known float dimensions */
|
|
|
|
selmon->sel->sfx = selmon->sel->x;
|
|
|
|
selmon->sel->sfy = selmon->sel->y;
|
|
|
|
selmon->sel->sfw = selmon->sel->w;
|
|
|
|
selmon->sel->sfh = selmon->sel->h;
|
2019-10-24 06:47:00 +00:00
|
|
|
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
|
2019-09-07 21:08:53 +00:00
|
|
|
}
|
2019-09-04 22:16:39 +00:00
|
|
|
arrange(selmon);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
toggletag(const Arg *arg)
|
|
|
|
{
|
|
|
|
unsigned int newtags;
|
2020-01-30 07:43:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
unsigned int tagmask, tagindex;
|
|
|
|
#endif // SWAPFOCUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
|
|
|
if (!selmon->sel)
|
|
|
|
return;
|
|
|
|
newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
|
|
|
|
if (newtags) {
|
|
|
|
selmon->sel->tags = newtags;
|
|
|
|
focus(NULL);
|
2020-01-30 07:43:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
for (tagmask = arg->ui & TAGMASK, tagindex = 1; tagmask!=0; tagmask >>= 1, tagindex++)
|
|
|
|
if (tagmask & 1)
|
|
|
|
selmon->pertag->prevclient[tagindex] = NULL;
|
|
|
|
#endif // SWAPFOCUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
arrange(selmon);
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EWMHTAGS_PATCH
|
2019-09-11 22:48:29 +00:00
|
|
|
updatecurrentdesktop();
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EWMHTAGS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
toggleview(const Arg *arg)
|
|
|
|
{
|
|
|
|
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
|
2019-09-05 20:58:16 +00:00
|
|
|
#if PERTAG_PATCH
|
|
|
|
int i;
|
|
|
|
#endif // PERTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
2019-10-04 22:12:52 +00:00
|
|
|
#if TAGINTOSTACK_ALLMASTER_PATCH
|
|
|
|
Client *const selected = selmon->sel;
|
|
|
|
|
|
|
|
// clients in the master area should be the same after we add a new tag
|
|
|
|
Client **const masters = calloc(selmon->nmaster, sizeof(Client *));
|
|
|
|
if (!masters) {
|
|
|
|
die("fatal: could not calloc() %u bytes \n", selmon->nmaster * sizeof(Client *));
|
|
|
|
}
|
|
|
|
// collect (from last to first) references to all clients in the master area
|
|
|
|
Client *c;
|
2019-10-06 21:43:51 +00:00
|
|
|
size_t j;
|
|
|
|
for (c = nexttiled(selmon->clients), j = 0; c && j < selmon->nmaster; c = nexttiled(c->next), ++j)
|
|
|
|
masters[selmon->nmaster - (j + 1)] = c;
|
2019-10-04 22:12:52 +00:00
|
|
|
// put the master clients at the front of the list
|
|
|
|
// > go from the 'last' master to the 'first'
|
2019-10-06 21:43:51 +00:00
|
|
|
for (j = 0; j < selmon->nmaster; ++j)
|
|
|
|
if (masters[j])
|
|
|
|
pop(masters[j]);
|
2019-10-04 22:12:52 +00:00
|
|
|
free(masters);
|
|
|
|
|
|
|
|
// we also want to be sure not to mutate the focus
|
|
|
|
focus(selected);
|
|
|
|
#elif TAGINTOSTACK_ONEMASTER_PATCH
|
|
|
|
// the first visible client should be the same after we add a new tag
|
|
|
|
// we also want to be sure not to mutate the focus
|
|
|
|
Client *const c = nexttiled(selmon->clients);
|
|
|
|
if (c) {
|
|
|
|
Client * const selected = selmon->sel;
|
|
|
|
pop(c);
|
|
|
|
focus(selected);
|
|
|
|
}
|
|
|
|
#endif // TAGINTOSTACK_ALLMASTER_PATCH / TAGINTOSTACK_ONEMASTER_PATCH
|
|
|
|
|
2019-10-02 21:22:04 +00:00
|
|
|
#if !EMPTYVIEW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (newtagset) {
|
2019-10-02 21:22:04 +00:00
|
|
|
#endif // EMPTYVIEW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
selmon->tagset[selmon->seltags] = newtagset;
|
2019-09-05 20:58:16 +00:00
|
|
|
|
|
|
|
#if PERTAG_PATCH
|
|
|
|
if (newtagset == ~0) {
|
|
|
|
selmon->pertag->prevtag = selmon->pertag->curtag;
|
|
|
|
selmon->pertag->curtag = 0;
|
|
|
|
}
|
|
|
|
/* test if the user did not select the same tag */
|
|
|
|
if (!(newtagset & 1 << (selmon->pertag->curtag - 1))) {
|
|
|
|
selmon->pertag->prevtag = selmon->pertag->curtag;
|
|
|
|
for (i=0; !(newtagset & 1 << i); i++) ;
|
|
|
|
selmon->pertag->curtag = i + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* apply settings for this view */
|
|
|
|
selmon->nmaster = selmon->pertag->nmasters[selmon->pertag->curtag];
|
|
|
|
selmon->mfact = selmon->pertag->mfacts[selmon->pertag->curtag];
|
|
|
|
selmon->sellt = selmon->pertag->sellts[selmon->pertag->curtag];
|
|
|
|
selmon->lt[selmon->sellt] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt];
|
|
|
|
selmon->lt[selmon->sellt^1] = selmon->pertag->ltidxs[selmon->pertag->curtag][selmon->sellt^1];
|
|
|
|
#if PERTAGBAR_PATCH
|
|
|
|
if (selmon->showbar != selmon->pertag->showbars[selmon->pertag->curtag])
|
|
|
|
togglebar(NULL);
|
|
|
|
#endif // PERTAGBAR_PATCH
|
|
|
|
#endif // PERTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
focus(NULL);
|
|
|
|
arrange(selmon);
|
2019-10-02 21:22:04 +00:00
|
|
|
#if !EMPTYVIEW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
2019-10-02 21:22:04 +00:00
|
|
|
#endif // EMPTYVIEW_PATCH
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EWMHTAGS_PATCH
|
2019-09-11 22:48:29 +00:00
|
|
|
updatecurrentdesktop();
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EWMHTAGS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
unfocus(Client *c, int setfocus)
|
|
|
|
{
|
|
|
|
if (!c)
|
|
|
|
return;
|
2020-01-29 07:31:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
selmon->pertag->prevclient[selmon->pertag->curtag] = c;
|
|
|
|
#endif // SWAPFOCUS_PATCH
|
2020-04-05 07:10:00 +00:00
|
|
|
#if LOSEFULLSCREEN_PATCH
|
|
|
|
#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
if (c->isfullscreen && !c->fakefullscreen && ISVISIBLE(c))
|
|
|
|
setfullscreen(c, 0);
|
|
|
|
#else
|
|
|
|
if (c->isfullscreen && ISVISIBLE(c))
|
|
|
|
setfullscreen(c, 0);
|
|
|
|
#endif // FAKEFULLSCREEN_CLIENT_PATCH
|
|
|
|
#endif // LOSEFULLSCREEN_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
grabbuttons(c, 0);
|
2019-09-10 22:51:37 +00:00
|
|
|
#if FLOAT_BORDER_COLOR_PATCH
|
|
|
|
if (c->isfloating)
|
|
|
|
XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColFloat].pixel);
|
|
|
|
else
|
|
|
|
XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel);
|
2019-09-10 22:51:37 +00:00
|
|
|
#endif // FLOAT_BORDER_COLOR_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (setfocus) {
|
|
|
|
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
|
|
|
|
XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
unmanage(Client *c, int destroyed)
|
|
|
|
{
|
|
|
|
Monitor *m = c->mon;
|
2020-07-03 11:30:21 +00:00
|
|
|
#if SWITCHTAG_PATCH
|
|
|
|
unsigned int switchtag = c->switchtag;
|
|
|
|
#endif // SWITCHTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
XWindowChanges wc;
|
|
|
|
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
if (c->swallowing) {
|
|
|
|
unswallow(c);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Client *s = swallowingclient(c->win);
|
|
|
|
if (s) {
|
|
|
|
free(s->swallowing);
|
|
|
|
s->swallowing = NULL;
|
|
|
|
arrange(m);
|
|
|
|
focus(NULL);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif // SWALLOW_PATCH
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
detach(c);
|
|
|
|
detachstack(c);
|
|
|
|
if (!destroyed) {
|
|
|
|
wc.border_width = c->oldbw;
|
|
|
|
XGrabServer(dpy); /* avoid race conditions */
|
|
|
|
XSetErrorHandler(xerrordummy);
|
|
|
|
XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */
|
|
|
|
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
|
|
|
|
setclientstate(c, WithdrawnState);
|
|
|
|
XSync(dpy, False);
|
|
|
|
XSetErrorHandler(xerror);
|
|
|
|
XUngrabServer(dpy);
|
|
|
|
}
|
|
|
|
free(c);
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
if (s)
|
|
|
|
return;
|
|
|
|
#endif // SWALLOW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
focus(NULL);
|
|
|
|
updateclientlist();
|
|
|
|
arrange(m);
|
2019-11-26 19:23:58 +00:00
|
|
|
#if SWITCHTAG_PATCH
|
2020-07-03 11:30:21 +00:00
|
|
|
if (switchtag)
|
|
|
|
view(&((Arg) { .ui = switchtag }));
|
2019-11-26 19:23:58 +00:00
|
|
|
#endif // SWITCHTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
unmapnotify(XEvent *e)
|
|
|
|
{
|
|
|
|
Client *c;
|
|
|
|
XUnmapEvent *ev = &e->xunmap;
|
|
|
|
|
|
|
|
if ((c = wintoclient(ev->window))) {
|
|
|
|
if (ev->send_event)
|
|
|
|
setclientstate(c, WithdrawnState);
|
|
|
|
else
|
|
|
|
unmanage(c, 0);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_SYSTRAY_PATCH
|
2019-09-05 20:10:00 +00:00
|
|
|
} else if (showsystray && (c = wintosystrayicon(ev->window))) {
|
|
|
|
/* KLUDGE! sometimes icons occasionally unmap their windows, but do
|
|
|
|
* _not_ destroy them. We map those windows back */
|
|
|
|
XMapRaised(dpy, c->win);
|
|
|
|
removesystrayicon(c);
|
|
|
|
updatesystray();
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_SYSTRAY_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
updatebars(void)
|
|
|
|
{
|
2020-07-15 06:57:30 +00:00
|
|
|
int b;
|
2019-09-04 22:16:39 +00:00
|
|
|
Monitor *m;
|
|
|
|
XSetWindowAttributes wa = {
|
|
|
|
.override_redirect = True,
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_ALPHA_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
.background_pixel = 0,
|
|
|
|
.border_pixel = 0,
|
|
|
|
.colormap = cmap,
|
|
|
|
#else
|
|
|
|
.background_pixmap = ParentRelative,
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_ALPHA_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
.event_mask = ButtonPressMask|ExposureMask
|
|
|
|
};
|
|
|
|
XClassHint ch = {"dwm", "dwm"};
|
|
|
|
for (m = mons; m; m = m->next) {
|
2020-07-15 06:57:30 +00:00
|
|
|
for (b = 0; b < LENGTH(m->bars); b++) {
|
|
|
|
if (!m->bars[b]->win) { // TODO add static status controls to not create / show extra bar?
|
|
|
|
#if BAR_ALPHA_PATCH
|
|
|
|
m->bars[b]->win = XCreateWindow(dpy, root, m->bars[b]->bx, m->bars[b]->by, m->bars[b]->bw, m->bars[b]->bh, 0, depth,
|
|
|
|
InputOutput, visual,
|
|
|
|
CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa);
|
|
|
|
#else
|
|
|
|
m->bars[b]->win = XCreateWindow(dpy, root, m->bars[b]->bx, m->bars[b]->by, m->bars[b]->bw, m->bars[b]->bh, 0, DefaultDepth(dpy, screen),
|
|
|
|
CopyFromParent, DefaultVisual(dpy, screen),
|
|
|
|
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
|
|
|
|
#endif // BAR_ALPHA_PATCH
|
|
|
|
XDefineCursor(dpy, m->bars[b]->win, cursor[CurNormal]->cursor);
|
|
|
|
XMapRaised(dpy, m->bars[b]->win);
|
|
|
|
XSetClassHint(dpy, m->bars[b]->win, &ch);
|
|
|
|
}
|
2019-10-24 05:35:00 +00:00
|
|
|
}
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
updatebarpos(Monitor *m)
|
|
|
|
{
|
|
|
|
m->wy = m->my;
|
|
|
|
m->wh = m->mh;
|
2020-07-15 06:57:30 +00:00
|
|
|
int num_bars, b;
|
|
|
|
#if BAR_PADDING_PATCH
|
|
|
|
int y_pad = vertpad;
|
|
|
|
int x_pad = sidepad;
|
2020-01-24 09:47:13 +00:00
|
|
|
#else
|
2020-07-15 06:57:30 +00:00
|
|
|
int y_pad = 0;
|
|
|
|
int x_pad = 0;
|
|
|
|
#endif // BAR_PADDING_PATCH
|
|
|
|
|
|
|
|
num_bars = LENGTH(m->bars);
|
2019-10-24 05:35:00 +00:00
|
|
|
if (m->showbar) {
|
2020-07-15 06:57:30 +00:00
|
|
|
m->wh = m->wh - y_pad * num_bars - bh * num_bars;
|
|
|
|
m->wy = m->wy + bh + y_pad;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (b = 0; b < num_bars; b++) {
|
|
|
|
m->bars[b]->bx = m->mx + x_pad;
|
|
|
|
m->bars[b]->bw = m->ww - 2 * x_pad;
|
|
|
|
m->bars[b]->bh = bh;
|
|
|
|
if (m->showbar) {
|
|
|
|
m->bars[b]->by = m->topbar == b ? m->wy + m->wh : m->wy - bh;
|
|
|
|
} else {
|
|
|
|
m->bars[b]->by = -bh - y_pad;
|
|
|
|
}
|
2019-10-24 05:35:00 +00:00
|
|
|
}
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
updateclientlist()
|
|
|
|
{
|
|
|
|
Client *c;
|
|
|
|
Monitor *m;
|
|
|
|
|
|
|
|
XDeleteProperty(dpy, root, netatom[NetClientList]);
|
|
|
|
for (m = mons; m; m = m->next)
|
|
|
|
for (c = m->clients; c; c = c->next)
|
|
|
|
XChangeProperty(dpy, root, netatom[NetClientList],
|
|
|
|
XA_WINDOW, 32, PropModeAppend,
|
|
|
|
(unsigned char *) &(c->win), 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
updategeom(void)
|
|
|
|
{
|
|
|
|
int dirty = 0;
|
|
|
|
|
|
|
|
#ifdef XINERAMA
|
|
|
|
if (XineramaIsActive(dpy)) {
|
|
|
|
int i, j, n, nn;
|
|
|
|
Client *c;
|
|
|
|
Monitor *m;
|
|
|
|
XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
|
|
|
|
XineramaScreenInfo *unique = NULL;
|
|
|
|
|
|
|
|
for (n = 0, m = mons; m; m = m->next, n++);
|
|
|
|
/* only consider unique geometries as separate screens */
|
|
|
|
unique = ecalloc(nn, sizeof(XineramaScreenInfo));
|
|
|
|
for (i = 0, j = 0; i < nn; i++)
|
|
|
|
if (isuniquegeom(unique, j, &info[i]))
|
|
|
|
memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo));
|
|
|
|
XFree(info);
|
|
|
|
nn = j;
|
2019-10-07 20:56:53 +00:00
|
|
|
#if SORTSCREENS_PATCH
|
|
|
|
sortscreens(unique, nn);
|
|
|
|
#endif // SORTSCREENS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (n <= nn) { /* new monitors available */
|
|
|
|
for (i = 0; i < (nn - n); i++) {
|
|
|
|
for (m = mons; m && m->next; m = m->next);
|
|
|
|
if (m)
|
|
|
|
m->next = createmon();
|
|
|
|
else
|
|
|
|
mons = createmon();
|
|
|
|
}
|
2020-06-10 09:52:35 +00:00
|
|
|
for (i = 0, m = mons; i < nn && m; m = m->next, i++) {
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATICSTATUS_PATCH && !BAR_STATUSALLMONS_PATCH
|
2020-07-07 16:25:00 +00:00
|
|
|
if (i == statmonval)
|
|
|
|
statmon = m;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EXTRABAR_PATCH
|
2020-07-08 12:13:29 +00:00
|
|
|
if (i == statebmonval)
|
|
|
|
statebmon = m;
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EXTRABAR_PATCH
|
|
|
|
#endif // BAR_STATICSTATUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (i >= n
|
|
|
|
|| unique[i].x_org != m->mx || unique[i].y_org != m->my
|
|
|
|
|| unique[i].width != m->mw || unique[i].height != m->mh)
|
|
|
|
{
|
|
|
|
dirty = 1;
|
|
|
|
m->num = i;
|
|
|
|
m->mx = m->wx = unique[i].x_org;
|
|
|
|
m->my = m->wy = unique[i].y_org;
|
|
|
|
m->mw = m->ww = unique[i].width;
|
|
|
|
m->mh = m->wh = unique[i].height;
|
|
|
|
updatebarpos(m);
|
|
|
|
}
|
2020-06-10 09:52:35 +00:00
|
|
|
}
|
2019-09-04 22:16:39 +00:00
|
|
|
} else { /* less monitors available nn < n */
|
|
|
|
for (i = nn; i < n; i++) {
|
|
|
|
for (m = mons; m && m->next; m = m->next);
|
|
|
|
while ((c = m->clients)) {
|
|
|
|
dirty = 1;
|
|
|
|
m->clients = c->next;
|
|
|
|
detachstack(c);
|
|
|
|
c->mon = mons;
|
|
|
|
attach(c);
|
|
|
|
attachstack(c);
|
|
|
|
}
|
|
|
|
if (m == selmon)
|
|
|
|
selmon = mons;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATICSTATUS_PATCH && !BAR_STATUSALLMONS_PATCH
|
2020-06-10 09:52:35 +00:00
|
|
|
if (m == statmon)
|
|
|
|
statmon = mons;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EXTRABAR_PATCH
|
2020-07-08 12:13:29 +00:00
|
|
|
if (m == statebmon)
|
|
|
|
statebmon = mons;
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EXTRABAR_PATCH
|
|
|
|
#endif // BAR_STATICSTATUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
cleanupmon(m);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(unique);
|
|
|
|
} else
|
|
|
|
#endif /* XINERAMA */
|
|
|
|
{ /* default monitor setup */
|
|
|
|
if (!mons)
|
|
|
|
mons = createmon();
|
|
|
|
if (mons->mw != sw || mons->mh != sh) {
|
|
|
|
dirty = 1;
|
|
|
|
mons->mw = mons->ww = sw;
|
|
|
|
mons->mh = mons->wh = sh;
|
|
|
|
updatebarpos(mons);
|
|
|
|
}
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATICSTATUS_PATCH && !BAR_STATUSALLMONS_PATCH
|
2020-06-10 09:52:35 +00:00
|
|
|
if (!statmon)
|
|
|
|
statmon = mons;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EXTRABAR_PATCH
|
2020-07-08 12:13:29 +00:00
|
|
|
if (!statebmon)
|
|
|
|
statebmon = mons;
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EXTRABAR_PATCH
|
|
|
|
#endif // BAR_STATICSTATUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (dirty) {
|
|
|
|
selmon = mons;
|
|
|
|
selmon = wintomon(root);
|
|
|
|
}
|
|
|
|
return dirty;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
updatenumlockmask(void)
|
|
|
|
{
|
|
|
|
unsigned int i, j;
|
|
|
|
XModifierKeymap *modmap;
|
|
|
|
|
|
|
|
numlockmask = 0;
|
|
|
|
modmap = XGetModifierMapping(dpy);
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
for (j = 0; j < modmap->max_keypermod; j++)
|
|
|
|
if (modmap->modifiermap[i * modmap->max_keypermod + j]
|
|
|
|
== XKeysymToKeycode(dpy, XK_Num_Lock))
|
|
|
|
numlockmask = (1 << i);
|
|
|
|
XFreeModifiermap(modmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
updatesizehints(Client *c)
|
|
|
|
{
|
|
|
|
long msize;
|
|
|
|
XSizeHints size;
|
|
|
|
|
|
|
|
if (!XGetWMNormalHints(dpy, c->win, &size, &msize))
|
|
|
|
/* size is uninitialized, ensure that size.flags aren't used */
|
2020-06-15 19:01:05 +00:00
|
|
|
#if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH
|
|
|
|
size.flags = 0;
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
size.flags = PSize;
|
2020-06-15 19:01:05 +00:00
|
|
|
#endif // SIZEHINTS_PATCH | SIZEHINTS_RULED_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (size.flags & PBaseSize) {
|
|
|
|
c->basew = size.base_width;
|
|
|
|
c->baseh = size.base_height;
|
|
|
|
} else if (size.flags & PMinSize) {
|
|
|
|
c->basew = size.min_width;
|
|
|
|
c->baseh = size.min_height;
|
|
|
|
} else
|
|
|
|
c->basew = c->baseh = 0;
|
|
|
|
if (size.flags & PResizeInc) {
|
|
|
|
c->incw = size.width_inc;
|
|
|
|
c->inch = size.height_inc;
|
|
|
|
} else
|
|
|
|
c->incw = c->inch = 0;
|
|
|
|
if (size.flags & PMaxSize) {
|
|
|
|
c->maxw = size.max_width;
|
|
|
|
c->maxh = size.max_height;
|
|
|
|
} else
|
|
|
|
c->maxw = c->maxh = 0;
|
|
|
|
if (size.flags & PMinSize) {
|
|
|
|
c->minw = size.min_width;
|
|
|
|
c->minh = size.min_height;
|
|
|
|
} else if (size.flags & PBaseSize) {
|
|
|
|
c->minw = size.base_width;
|
|
|
|
c->minh = size.base_height;
|
|
|
|
} else
|
|
|
|
c->minw = c->minh = 0;
|
|
|
|
if (size.flags & PAspect) {
|
|
|
|
c->mina = (float)size.min_aspect.y / size.min_aspect.x;
|
|
|
|
c->maxa = (float)size.max_aspect.x / size.max_aspect.y;
|
|
|
|
} else
|
|
|
|
c->maxa = c->mina = 0.0;
|
2020-06-15 19:01:05 +00:00
|
|
|
#if SIZEHINTS_PATCH || SIZEHINTS_RULED_PATCH
|
|
|
|
if (size.flags & PSize) {
|
|
|
|
c->basew = size.base_width;
|
|
|
|
c->baseh = size.base_height;
|
|
|
|
c->isfloating = 1;
|
|
|
|
}
|
|
|
|
#if SIZEHINTS_RULED_PATCH
|
|
|
|
checkfloatingrules(c);
|
|
|
|
#endif // SIZEHINTS_RULED_PATCH
|
|
|
|
#endif // SIZEHINTS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
updatestatus(void)
|
|
|
|
{
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUSALLMONS_PATCH
|
2019-10-06 21:43:51 +00:00
|
|
|
Monitor* m;
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSALLMONS_PATCH
|
|
|
|
#if BAR_EXTRABAR_PATCH
|
2020-07-05 19:53:36 +00:00
|
|
|
if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext))) {
|
2019-10-24 05:35:00 +00:00
|
|
|
strcpy(stext, "dwm-"VERSION);
|
|
|
|
estext[0] = '\0';
|
|
|
|
} else {
|
2020-07-05 19:53:36 +00:00
|
|
|
char *e = strchr(rawstext, statussep);
|
2019-10-24 05:35:00 +00:00
|
|
|
if (e) {
|
|
|
|
*e = '\0'; e++;
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUSCMD_PATCH
|
2020-07-05 19:53:36 +00:00
|
|
|
strncpy(rawestext, e, sizeof(estext) - 1);
|
|
|
|
copyvalidchars(estext, rawestext);
|
|
|
|
#else
|
2019-10-24 05:35:00 +00:00
|
|
|
strncpy(estext, e, sizeof(estext) - 1);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSCMD_PATCH
|
2019-10-24 05:35:00 +00:00
|
|
|
} else {
|
|
|
|
estext[0] = '\0';
|
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_STATUSCMD_PATCH
|
2020-07-05 19:53:36 +00:00
|
|
|
copyvalidchars(stext, rawstext);
|
2020-04-13 12:59:58 +00:00
|
|
|
#else
|
2020-07-05 19:53:36 +00:00
|
|
|
strncpy(stext, rawstext, sizeof(stext) - 1);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSCMD_PATCH
|
2019-10-24 05:35:00 +00:00
|
|
|
}
|
2020-07-15 06:57:30 +00:00
|
|
|
#elif BAR_STATUSCMD_PATCH
|
2020-04-13 12:59:58 +00:00
|
|
|
if (!gettextprop(root, XA_WM_NAME, rawstext, sizeof(rawstext)))
|
|
|
|
strcpy(stext, "dwm-"VERSION);
|
|
|
|
else
|
|
|
|
copyvalidchars(stext, rawstext);
|
2019-10-24 05:35:00 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
|
|
|
|
strcpy(stext, "dwm-"VERSION);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EXTRABAR_PATCH
|
|
|
|
#if BAR_STATUSALLMONS_PATCH
|
2019-10-06 21:43:51 +00:00
|
|
|
for (m = mons; m; m = m->next)
|
|
|
|
drawbar(m);
|
2020-07-15 06:57:30 +00:00
|
|
|
#elif BAR_STATICSTATUS_PATCH
|
2020-06-10 09:52:35 +00:00
|
|
|
drawbar(statmon);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EXTRABAR_PATCH
|
2020-07-08 12:13:29 +00:00
|
|
|
if (statmon != statebmon)
|
|
|
|
drawbar(statebmon);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EXTRABAR_PATCH
|
2019-10-06 21:43:51 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
drawbar(selmon);
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_STATUSALLMONS_PATCH | BAR_STATICSTATUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
updatetitle(Client *c)
|
|
|
|
{
|
|
|
|
if (!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
|
|
|
|
gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
|
|
|
|
if (c->name[0] == '\0') /* hack to mark broken clients */
|
|
|
|
strcpy(c->name, broken);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
updatewmhints(Client *c)
|
|
|
|
{
|
|
|
|
XWMHints *wmh;
|
|
|
|
|
|
|
|
if ((wmh = XGetWMHints(dpy, c->win))) {
|
|
|
|
if (c == selmon->sel && wmh->flags & XUrgencyHint) {
|
|
|
|
wmh->flags &= ~XUrgencyHint;
|
|
|
|
XSetWMHints(dpy, c->win, wmh);
|
2019-09-15 22:13:03 +00:00
|
|
|
} else {
|
2019-09-04 22:16:39 +00:00
|
|
|
c->isurgent = (wmh->flags & XUrgencyHint) ? 1 : 0;
|
2019-09-15 22:13:03 +00:00
|
|
|
#if URGENTBORDER_PATCH
|
|
|
|
if (c->isurgent) {
|
|
|
|
#if FLOAT_BORDER_COLOR_PATCH
|
|
|
|
if (c->isfloating)
|
|
|
|
XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColFloat].pixel);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
XSetWindowBorder(dpy, c->win, scheme[SchemeUrg][ColBorder].pixel);
|
|
|
|
}
|
|
|
|
#endif // URGENTBORDER_PATCH
|
|
|
|
}
|
2019-09-04 22:16:39 +00:00
|
|
|
if (wmh->flags & InputHint)
|
|
|
|
c->neverfocus = !wmh->input;
|
|
|
|
else
|
|
|
|
c->neverfocus = 0;
|
|
|
|
XFree(wmh);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
view(const Arg *arg)
|
|
|
|
{
|
2019-10-02 21:22:04 +00:00
|
|
|
#if EMPTYVIEW_PATCH
|
|
|
|
if (arg->ui && (arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
|
2019-10-02 21:22:04 +00:00
|
|
|
#endif // EMPTYVIEW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
return;
|
|
|
|
selmon->seltags ^= 1; /* toggle sel tagset */
|
2019-09-05 20:58:16 +00:00
|
|
|
#if PERTAG_PATCH
|
2019-09-30 21:52:51 +00:00
|
|
|
pertagview(arg);
|
2020-01-29 07:31:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH
|
|
|
|
Client *unmodified = selmon->pertag->prevclient[selmon->pertag->curtag];
|
|
|
|
#endif // SWAPFOCUS_PATCH
|
2019-09-05 20:58:16 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (arg->ui & TAGMASK)
|
|
|
|
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
|
2019-09-05 20:58:16 +00:00
|
|
|
#endif // PERTAG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
focus(NULL);
|
2020-01-29 07:31:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
selmon->pertag->prevclient[selmon->pertag->curtag] = unmodified;
|
|
|
|
#endif // SWAPFOCUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
arrange(selmon);
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_EWMHTAGS_PATCH
|
2019-09-11 22:48:29 +00:00
|
|
|
updatecurrentdesktop();
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_EWMHTAGS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Client *
|
|
|
|
wintoclient(Window w)
|
|
|
|
{
|
|
|
|
Client *c;
|
|
|
|
Monitor *m;
|
|
|
|
|
|
|
|
for (m = mons; m; m = m->next)
|
|
|
|
for (c = m->clients; c; c = c->next)
|
|
|
|
if (c->win == w)
|
|
|
|
return c;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Monitor *
|
|
|
|
wintomon(Window w)
|
|
|
|
{
|
2020-07-15 06:57:30 +00:00
|
|
|
int x, y, b;
|
2019-09-04 22:16:39 +00:00
|
|
|
Client *c;
|
|
|
|
Monitor *m;
|
|
|
|
|
|
|
|
if (w == root && getrootptr(&x, &y))
|
|
|
|
return recttomon(x, y, 1, 1);
|
|
|
|
for (m = mons; m; m = m->next)
|
2020-07-15 06:57:30 +00:00
|
|
|
for (b = 0; b < LENGTH(m->bars); b++)
|
|
|
|
if (w == m->bars[b]->win)
|
|
|
|
return m;
|
2019-09-04 22:16:39 +00:00
|
|
|
if ((c = wintoclient(w)))
|
|
|
|
return c->mon;
|
|
|
|
return selmon;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* There's no way to check accesses to destroyed windows, thus those cases are
|
|
|
|
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
|
|
|
|
* default error handler, which may call exit. */
|
|
|
|
int
|
|
|
|
xerror(Display *dpy, XErrorEvent *ee)
|
|
|
|
{
|
|
|
|
if (ee->error_code == BadWindow
|
|
|
|
|| (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
|
|
|
|
|| (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
|
|
|
|
|| (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
|
|
|
|
|| (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
|
|
|
|
|| (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
|
|
|
|
|| (ee->request_code == X_GrabButton && ee->error_code == BadAccess)
|
|
|
|
|| (ee->request_code == X_GrabKey && ee->error_code == BadAccess)
|
|
|
|
|| (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
|
|
|
|
return 0;
|
|
|
|
fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
|
|
|
|
ee->request_code, ee->error_code);
|
|
|
|
return xerrorxlib(dpy, ee); /* may call exit */
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
xerrordummy(Display *dpy, XErrorEvent *ee)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Startup Error handler to check if another window manager
|
|
|
|
* is already running. */
|
|
|
|
int
|
|
|
|
xerrorstart(Display *dpy, XErrorEvent *ee)
|
|
|
|
{
|
|
|
|
die("dwm: another window manager is already running");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
zoom(const Arg *arg)
|
|
|
|
{
|
|
|
|
Client *c = selmon->sel;
|
2019-09-05 21:19:23 +00:00
|
|
|
#if ZOOMSWAP_PATCH
|
|
|
|
Client *at = NULL, *cold, *cprevious = NULL, *p;
|
|
|
|
#endif // ZOOMSWAP_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
|
2020-01-29 07:31:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
selmon->pertag->prevclient[selmon->pertag->curtag] = nexttiled(selmon->clients);
|
|
|
|
#endif // SWAPFOCUS_PATCH
|
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!selmon->lt[selmon->sellt]->arrange
|
2019-09-05 21:19:23 +00:00
|
|
|
|| (selmon->sel && selmon->sel->isfloating)
|
|
|
|
#if ZOOMSWAP_PATCH
|
|
|
|
|| !c
|
|
|
|
#endif // ZOOMSWAP_PATCH
|
|
|
|
)
|
2019-09-04 22:16:39 +00:00
|
|
|
return;
|
2019-09-05 21:19:23 +00:00
|
|
|
|
|
|
|
#if ZOOMSWAP_PATCH
|
2020-01-15 12:21:56 +00:00
|
|
|
if (c == nexttiled(selmon->clients)) {
|
|
|
|
#if PERTAG_PATCH
|
|
|
|
p = selmon->pertag->prevzooms[selmon->pertag->curtag];
|
|
|
|
#else
|
|
|
|
p = prevzoom;
|
|
|
|
#endif // PERTAG_PATCH
|
|
|
|
at = prevtiled(p);
|
|
|
|
if (at)
|
|
|
|
cprevious = nexttiled(at->next);
|
|
|
|
if (!cprevious || cprevious != p) {
|
2019-09-05 21:19:23 +00:00
|
|
|
#if PERTAG_PATCH
|
2020-01-15 12:21:56 +00:00
|
|
|
selmon->pertag->prevzooms[selmon->pertag->curtag] = NULL;
|
2019-09-05 21:19:23 +00:00
|
|
|
#else
|
2020-01-15 12:21:56 +00:00
|
|
|
prevzoom = NULL;
|
2019-09-05 21:19:23 +00:00
|
|
|
#endif // PERTAG_PATCH
|
2020-01-29 07:31:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
if (!c || !(c = selmon->pertag->prevclient[selmon->pertag->curtag] = nexttiled(c->next)))
|
|
|
|
#else
|
2020-01-15 12:21:56 +00:00
|
|
|
if (!c || !(c = nexttiled(c->next)))
|
2020-01-29 07:31:00 +00:00
|
|
|
#endif // SWAPFOCUS_PATCH
|
2020-01-15 12:21:56 +00:00
|
|
|
return;
|
|
|
|
} else
|
2020-01-29 07:31:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
c = selmon->pertag->prevclient[selmon->pertag->curtag] = cprevious;
|
|
|
|
#else
|
2020-01-15 12:21:56 +00:00
|
|
|
c = cprevious;
|
2020-01-29 07:31:00 +00:00
|
|
|
#endif // SWAPFOCUS_PATCH
|
2020-01-15 12:21:56 +00:00
|
|
|
}
|
2019-09-05 21:19:23 +00:00
|
|
|
|
2020-01-15 12:21:56 +00:00
|
|
|
cold = nexttiled(selmon->clients);
|
|
|
|
if (c != cold && !at)
|
|
|
|
at = prevtiled(c);
|
|
|
|
detach(c);
|
|
|
|
attach(c);
|
|
|
|
/* swap windows instead of pushing the previous one down */
|
|
|
|
if (c != cold && at) {
|
|
|
|
#if PERTAG_PATCH
|
|
|
|
selmon->pertag->prevzooms[selmon->pertag->curtag] = cold;
|
|
|
|
#else
|
|
|
|
prevzoom = cold;
|
|
|
|
#endif // PERTAG_PATCH
|
|
|
|
if (cold && at != cold) {
|
|
|
|
detach(cold);
|
|
|
|
cold->next = at->next;
|
|
|
|
at->next = cold;
|
2019-09-05 21:19:23 +00:00
|
|
|
}
|
2020-01-15 12:21:56 +00:00
|
|
|
}
|
|
|
|
focus(c);
|
|
|
|
arrange(c->mon);
|
2019-09-05 21:19:23 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (c == nexttiled(selmon->clients))
|
2020-01-29 07:31:00 +00:00
|
|
|
#if SWAPFOCUS_PATCH && PERTAG_PATCH
|
|
|
|
if (!c || !(c = selmon->pertag->prevclient[selmon->pertag->curtag] = nexttiled(c->next)))
|
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!c || !(c = nexttiled(c->next)))
|
2020-01-29 07:31:00 +00:00
|
|
|
#endif // SWAPFOCUS_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
return;
|
|
|
|
pop(c);
|
2019-09-05 21:19:23 +00:00
|
|
|
#endif // ZOOMSWAP_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
main(int argc, char *argv[])
|
|
|
|
{
|
2019-11-04 07:17:00 +00:00
|
|
|
#if CMDCUSTOMIZE_PATCH
|
2019-10-05 21:56:43 +00:00
|
|
|
for (int i=1;i<argc;i+=1)
|
|
|
|
if (!strcmp("-v", argv[i]))
|
|
|
|
die("dwm-"VERSION);
|
|
|
|
else if (!strcmp("-h", argv[i]) || !strcmp("--help", argv[i]))
|
|
|
|
die(help());
|
|
|
|
else if (!strcmp("-fn", argv[i])) /* font set */
|
2020-07-15 06:57:30 +00:00
|
|
|
#if BAR_PANGO_PATCH
|
2020-06-14 13:52:47 +00:00
|
|
|
strcpy(font, argv[++i]);
|
|
|
|
#else
|
2019-10-05 21:56:43 +00:00
|
|
|
fonts[0] = argv[++i];
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // BAR_PANGO_PATCH
|
|
|
|
#if !BAR_VTCOLORS_PATCH
|
2019-10-05 21:56:43 +00:00
|
|
|
else if (!strcmp("-nb", argv[i])) /* normal background color */
|
|
|
|
colors[SchemeNorm][1] = argv[++i];
|
|
|
|
else if (!strcmp("-nf", argv[i])) /* normal foreground color */
|
|
|
|
colors[SchemeNorm][0] = argv[++i];
|
|
|
|
else if (!strcmp("-sb", argv[i])) /* selected background color */
|
|
|
|
colors[SchemeSel][1] = argv[++i];
|
|
|
|
else if (!strcmp("-sf", argv[i])) /* selected foreground color */
|
|
|
|
colors[SchemeSel][0] = argv[++i];
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // !BAR_VTCOLORS_PATCH
|
2019-11-04 07:17:00 +00:00
|
|
|
#if NODMENU_PATCH
|
|
|
|
else if (!strcmp("-df", argv[i])) /* dmenu font */
|
|
|
|
dmenucmd[2] = argv[++i];
|
|
|
|
else if (!strcmp("-dnb", argv[i])) /* dmenu normal background color */
|
|
|
|
dmenucmd[4] = argv[++i];
|
|
|
|
else if (!strcmp("-dnf", argv[i])) /* dmenu normal foreground color */
|
|
|
|
dmenucmd[6] = argv[++i];
|
|
|
|
else if (!strcmp("-dsb", argv[i])) /* dmenu selected background color */
|
|
|
|
dmenucmd[8] = argv[++i];
|
|
|
|
else if (!strcmp("-dsf", argv[i])) /* dmenu selected foreground color */
|
|
|
|
dmenucmd[10] = argv[++i];
|
|
|
|
#else
|
2019-10-05 21:56:43 +00:00
|
|
|
else if (!strcmp("-df", argv[i])) /* dmenu font */
|
|
|
|
dmenucmd[4] = argv[++i];
|
|
|
|
else if (!strcmp("-dnb", argv[i])) /* dmenu normal background color */
|
|
|
|
dmenucmd[6] = argv[++i];
|
|
|
|
else if (!strcmp("-dnf", argv[i])) /* dmenu normal foreground color */
|
|
|
|
dmenucmd[8] = argv[++i];
|
|
|
|
else if (!strcmp("-dsb", argv[i])) /* dmenu selected background color */
|
|
|
|
dmenucmd[10] = argv[++i];
|
|
|
|
else if (!strcmp("-dsf", argv[i])) /* dmenu selected foreground color */
|
|
|
|
dmenucmd[12] = argv[++i];
|
2019-11-04 07:17:00 +00:00
|
|
|
#endif // NODMENU_PATCH
|
2020-02-11 17:31:11 +00:00
|
|
|
else die(help());
|
2019-10-05 21:56:43 +00:00
|
|
|
#else
|
2019-09-04 22:16:39 +00:00
|
|
|
if (argc == 2 && !strcmp("-v", argv[1]))
|
|
|
|
die("dwm-"VERSION);
|
|
|
|
else if (argc != 1)
|
|
|
|
die("usage: dwm [-v]");
|
2019-11-04 07:17:00 +00:00
|
|
|
#endif // CMDCUSTOMIZE_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
|
|
|
|
fputs("warning: no locale support\n", stderr);
|
|
|
|
if (!(dpy = XOpenDisplay(NULL)))
|
|
|
|
die("dwm: cannot open display");
|
2019-10-22 17:08:00 +00:00
|
|
|
#if SWALLOW_PATCH
|
|
|
|
if (!(xcon = XGetXCBConnection(dpy)))
|
|
|
|
die("dwm: cannot get xcb connection\n");
|
|
|
|
#endif // SWALLOW_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
checkotherwm();
|
2020-07-15 06:57:30 +00:00
|
|
|
#if XRDB_PATCH && !BAR_VTCOLORS_PATCH
|
2019-09-15 20:45:22 +00:00
|
|
|
XrmInitialize();
|
|
|
|
loadxrdb();
|
2020-07-15 06:57:30 +00:00
|
|
|
#endif // XRDB_PATCH && !BAR_VTCOLORS_PATCH
|
2019-09-15 20:45:22 +00:00
|
|
|
|
2019-09-04 22:16:39 +00:00
|
|
|
setup();
|
|
|
|
#ifdef __OpenBSD__
|
|
|
|
if (pledge("stdio rpath proc exec", NULL) == -1)
|
|
|
|
die("pledge");
|
|
|
|
#endif /* __OpenBSD__ */
|
|
|
|
scan();
|
2019-09-06 21:37:30 +00:00
|
|
|
#if AUTOSTART_PATCH
|
2020-06-14 17:56:52 +00:00
|
|
|
runautostart();
|
2019-09-06 21:37:30 +00:00
|
|
|
#endif
|
2019-09-04 22:16:39 +00:00
|
|
|
run();
|
2019-10-02 21:22:04 +00:00
|
|
|
#if RESTARTSIG_PATCH
|
|
|
|
if (restart)
|
|
|
|
execvp(argv[0], argv);
|
|
|
|
#endif // RESTARTSIG_PATCH
|
2019-09-04 22:16:39 +00:00
|
|
|
cleanup();
|
|
|
|
XCloseDisplay(dpy);
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|