2007-09-15 22:33:46 +02: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
2017-01-07 17:21:28 +01:00
* events about window ( dis - ) appearance . Only one X connection at a time is
2007-09-15 22:33:46 +02:00
* allowed to select for this event mask .
*
2008-12-12 19:49:06 +00:00
* 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 .
2007-09-15 22:33:46 +02:00
*
* Each child of the root window is called a client , except windows which have
2017-01-07 17:21:28 +01:00
* set the override_redirect flag . Clients are organized in a linked client
2009-07-02 20:37:26 +01:00
* 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
2008-05-26 11:43:51 +01:00
* client .
2007-09-15 22:33:46 +02:00
*
2007-09-17 16:42:37 +02:00
* Keys and tagging rules are organized as arrays and defined in config . h .
2007-09-15 22:33:46 +02:00
*
* To understand everything else , start reading main ( ) .
*/
2007-09-15 22:25:27 +02:00
# include <errno.h>
2008-08-25 09:37:39 +01:00
# include <locale.h>
2008-12-13 17:44:29 +00:00
# include <signal.h>
2015-11-08 20:38:00 +01:00
# include <stdarg.h>
2007-09-15 22:25:27 +02:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <unistd.h>
2007-09-27 09:14:32 +02:00
# include <sys/types.h>
2007-09-15 22:25:27 +02:00
# include <sys/wait.h>
# include <X11/cursorfont.h>
# include <X11/keysym.h>
# include <X11/Xatom.h>
2007-10-17 11:19:14 +02:00
# include <X11/Xlib.h>
2007-09-15 22:25:27 +02:00
# include <X11/Xproto.h>
# include <X11/Xutil.h>
2008-05-19 15:05:46 +01:00
# ifdef XINERAMA
# include <X11/extensions/Xinerama.h>
2009-06-20 15:10:04 +01:00
# endif /* XINERAMA */
2015-03-05 20:26:11 -08:00
# include <X11/Xft/Xft.h>
2007-09-15 22:25:27 +02:00
2013-04-17 21:21:47 +02:00
# include "drw.h"
2012-12-08 10:13:01 +01:00
# include "util.h"
2012-11-17 19:01:22 +01:00
2007-09-15 22:25:27 +02:00
/* macros */
2008-07-16 18:33:51 +01:00
# define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
2011-06-27 20:12:42 +01:00
# define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
2011-11-06 20:31:29 +01:00
# 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 ) ) )
2009-06-23 17:20:33 +01:00
# define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
2009-06-20 15:51:34 +01:00
# define LENGTH(X) (sizeof X / sizeof X[0])
2008-07-16 18:33:51 +01:00
# define MOUSEMASK (BUTTONMASK|PointerMotionMask)
2009-06-20 17:02:55 +01:00
# define WIDTH(X) ((X)->w + 2 * (X)->bw)
# define HEIGHT(X) ((X)->h + 2 * (X)->bw)
2009-07-14 16:04:07 +01:00
# define TAGMASK ((1 << LENGTH(tags)) - 1)
2016-05-22 22:33:56 +02:00
# define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
2007-11-07 09:49:53 +01:00
2007-10-18 10:28:41 +02:00
/* enums */
2013-06-19 19:35:33 +02:00
enum { CurNormal , CurResize , CurMove , CurLast } ; /* cursor */
2023-10-08 00:02:49 -04:00
enum { SchemeNorm , SchemeSel , SchemeStatus , SchemeTagsSel , SchemeTagsNorm , SchemeInfoSel , SchemeInfoNorm , SchemeWarn , SchemeUrgent , SchemeWorking } ; /* color schemes */
2016-12-05 10:09:49 +01:00
enum { NetSupported , NetWMName , NetWMState , NetWMCheck ,
2011-11-02 12:01:28 +00:00
NetWMFullscreen , NetActiveWindow , NetWMWindowType ,
2013-06-19 19:35:33 +02:00
NetWMWindowTypeDialog , NetClientList , NetLast } ; /* EWMH atoms */
2011-04-12 20:19:32 +00:00
enum { WMProtocols , WMDelete , WMState , WMTakeFocus , WMLast } ; /* default atoms */
2008-06-20 16:52:07 +01:00
enum { ClkTagBar , ClkLtSymbol , ClkStatusText , ClkWinTitle ,
2013-06-19 19:35:33 +02:00
ClkClientWin , ClkRootWin , ClkLast } ; /* clicks */
2007-10-18 10:28:41 +02:00
2008-06-11 20:41:28 +01:00
typedef union {
int i ;
2008-07-16 18:17:42 +01:00
unsigned int ui ;
2008-06-11 20:41:28 +01:00
float f ;
2009-07-08 18:59:20 +01:00
const void * v ;
2008-06-11 20:41:28 +01:00
} Arg ;
typedef struct {
2008-07-16 18:17:42 +01:00
unsigned int click ;
unsigned int mask ;
unsigned int button ;
2008-06-11 20:41:28 +01:00
void ( * func ) ( const Arg * arg ) ;
const Arg arg ;
} Button ;
2009-06-22 14:58:08 +01:00
typedef struct Monitor Monitor ;
2007-10-18 10:28:41 +02:00
typedef struct Client Client ;
struct Client {
char name [ 256 ] ;
2008-06-15 10:52:57 +01:00
float mina , maxa ;
2007-10-18 10:28:41 +02:00
int x , y , w , h ;
2010-05-30 10:02:56 +01:00
int oldx , oldy , oldw , oldh ;
2007-10-18 10:28:41 +02:00
int basew , baseh , incw , inch , maxw , maxh , minw , minh ;
2008-05-22 11:50:18 +01:00
int bw , oldbw ;
2008-07-16 18:17:42 +01:00
unsigned int tags ;
2015-11-08 22:48:43 +01:00
int isfixed , isfloating , isurgent , neverfocus , oldstate , isfullscreen ;
2007-10-18 10:28:41 +02:00
Client * next ;
Client * snext ;
2009-06-23 17:17:25 +01:00
Monitor * mon ;
2007-10-18 10:28:41 +02:00
Window win ;
} ;
typedef struct {
2008-07-16 18:17:42 +01:00
unsigned int mod ;
2007-10-18 10:28:41 +02:00
KeySym keysym ;
2008-06-11 09:12:06 +01:00
void ( * func ) ( const Arg * ) ;
const Arg arg ;
2007-10-18 10:28:41 +02:00
} Key ;
typedef struct {
2009-06-22 14:58:08 +01:00
const char * symbol ;
void ( * arrange ) ( Monitor * ) ;
} Layout ;
2021-04-08 23:16:19 -04:00
typedef struct Pertag Pertag ;
2009-06-22 14:58:08 +01:00
struct Monitor {
2009-09-22 09:53:11 +01:00
char ltsymbol [ 16 ] ;
2009-06-20 16:18:02 +01:00
float mfact ;
2011-10-25 20:40:46 +01:00
int nmaster ;
2009-07-09 21:52:17 +01:00
int num ;
2009-07-09 11:29:01 +01:00
int by ; /* bar geometry */
2009-06-30 20:15:31 +01:00
int mx , my , mw , mh ; /* screen size */
2009-06-20 15:10:04 +01:00
int wx , wy , ww , wh ; /* window area */
2021-04-09 10:50:41 -04:00
int gappih ; /* horizontal gap between windows */
int gappiv ; /* vertical gap between windows */
int gappoh ; /* horizontal outer gaps */
int gappov ; /* vertical outer gaps */
2009-06-19 20:15:15 +01:00
unsigned int seltags ;
unsigned int sellt ;
2009-06-20 17:02:55 +01:00
unsigned int tagset [ 2 ] ;
2015-11-08 22:48:43 +01:00
int showbar ;
int topbar ;
2009-06-23 17:17:25 +01:00
Client * clients ;
Client * sel ;
Client * stack ;
2009-06-22 14:58:08 +01:00
Monitor * next ;
2009-06-23 17:17:25 +01:00
Window barwin ;
2009-07-08 18:59:20 +01:00
const Layout * lt [ 2 ] ;
2021-04-08 23:16:19 -04:00
Pertag * pertag ;
2009-06-22 14:58:08 +01:00
} ;
2009-06-20 15:10:04 +01:00
2007-10-18 10:28:41 +02:00
typedef struct {
2008-03-14 14:35:45 +00:00
const char * class ;
const char * instance ;
const char * title ;
2008-07-16 18:17:42 +01:00
unsigned int tags ;
2015-11-08 22:48:43 +01:00
int isfloating ;
2009-07-09 21:52:17 +01:00
int monitor ;
2007-10-18 10:28:41 +02:00
} Rule ;
2007-10-18 17:02:19 +02:00
/* function declarations */
2008-06-11 09:12:06 +01:00
static void applyrules ( Client * c ) ;
2021-04-09 11:20:47 -04:00
static int applysizehints ( Client * c , int * x , int * y , int * w , int * h , int * bw , int interact ) ;
2009-09-27 10:31:14 +01:00
static void arrange ( Monitor * m ) ;
static void arrangemon ( Monitor * m ) ;
2008-06-11 09:12:06 +01:00
static void attach ( Client * c ) ;
static void attachstack ( Client * c ) ;
static void buttonpress ( XEvent * e ) ;
static void checkotherwm ( void ) ;
static void cleanup ( void ) ;
2009-09-22 20:33:42 +01:00
static void cleanupmon ( Monitor * mon ) ;
2010-05-30 10:02:56 +01:00
static void clientmessage ( XEvent * e ) ;
2008-06-11 09:12:06 +01:00
static void configure ( Client * c ) ;
static void configurenotify ( XEvent * e ) ;
static void configurerequest ( XEvent * e ) ;
2009-09-21 19:51:17 +01:00
static Monitor * createmon ( void ) ;
2008-06-11 09:12:06 +01:00
static void destroynotify ( XEvent * e ) ;
static void detach ( Client * c ) ;
static void detachstack ( Client * c ) ;
2009-07-02 20:37:26 +01:00
static Monitor * dirtomon ( int dir ) ;
2009-06-20 15:10:04 +01:00
static void drawbar ( Monitor * m ) ;
2009-06-27 18:39:03 +01:00
static void drawbars ( void ) ;
2008-06-11 09:12:06 +01:00
static void enternotify ( XEvent * e ) ;
static void expose ( XEvent * e ) ;
static void focus ( Client * c ) ;
static void focusin ( XEvent * e ) ;
2009-07-01 19:15:20 +01:00
static void focusmon ( const Arg * arg ) ;
2008-06-11 09:12:06 +01:00
static void focusstack ( const Arg * arg ) ;
2020-04-22 15:48:08 +01:00
static Atom getatomprop ( Client * c , Atom prop ) ;
2015-11-08 22:48:43 +01:00
static int getrootptr ( int * x , int * y ) ;
2008-06-11 09:12:06 +01:00
static long getstate ( Window w ) ;
2015-11-08 22:48:43 +01:00
static int gettextprop ( Window w , Atom atom , char * text , unsigned int size ) ;
static void grabbuttons ( Client * c , int focused ) ;
2008-06-11 09:12:06 +01:00
static void grabkeys ( void ) ;
2011-10-25 20:40:46 +01:00
static void incnmaster ( const Arg * arg ) ;
2008-06-11 09:12:06 +01:00
static void keypress ( XEvent * e ) ;
static void killclient ( const Arg * arg ) ;
static void manage ( Window w , XWindowAttributes * wa ) ;
static void mappingnotify ( XEvent * e ) ;
static void maprequest ( XEvent * e ) ;
2009-06-20 15:10:04 +01:00
static void monocle ( Monitor * m ) ;
2011-11-15 20:16:58 +01:00
static void motionnotify ( XEvent * e ) ;
2020-12-03 09:53:29 -05:00
static void moveresize ( const Arg * arg ) ;
2008-06-11 20:41:28 +01:00
static void movemouse ( const Arg * arg ) ;
2009-06-23 17:20:33 +01:00
static Client * nexttiled ( Client * c ) ;
2011-04-15 08:13:06 +00:00
static void pop ( Client * ) ;
2008-06-11 09:12:06 +01:00
static void propertynotify ( XEvent * e ) ;
static void quit ( const Arg * arg ) ;
2011-11-06 20:31:29 +01:00
static Monitor * recttomon ( int x , int y , int w , int h ) ;
2021-04-09 11:20:47 -04:00
static void resize ( Client * c , int x , int y , int w , int h , int bw , int interact ) ;
static void resizeclient ( Client * c , int x , int y , int w , int h , int bw ) ;
2008-06-11 20:41:28 +01:00
static void resizemouse ( const Arg * arg ) ;
2009-06-20 15:10:04 +01:00
static void restack ( Monitor * m ) ;
2008-06-11 09:12:06 +01:00
static void run ( void ) ;
static void scan ( void ) ;
2015-11-08 22:48:43 +01:00
static int sendevent ( Client * c , Atom proto ) ;
2009-06-27 18:39:03 +01:00
static void sendmon ( Client * c , Monitor * m ) ;
2008-06-11 09:12:06 +01:00
static void setclientstate ( Client * c , long state ) ;
2011-04-12 20:19:32 +00:00
static void setfocus ( Client * c ) ;
2015-11-08 22:48:43 +01:00
static void setfullscreen ( Client * c , int fullscreen ) ;
2008-06-19 11:38:53 +01:00
static void setlayout ( const Arg * arg ) ;
2008-06-11 09:12:06 +01:00
static void setmfact ( const Arg * arg ) ;
static void setup ( void ) ;
2016-12-05 10:16:46 +01:00
static void seturgent ( Client * c , int urg ) ;
2009-03-19 13:06:15 +00:00
static void showhide ( Client * c ) ;
2009-08-13 10:45:59 +01:00
static void sigchld ( int unused ) ;
2021-04-09 01:24:48 -04:00
static void sighup ( int unused ) ;
static void sigterm ( int unused ) ;
2008-06-11 09:12:06 +01:00
static void spawn ( const Arg * arg ) ;
static void tag ( const Arg * arg ) ;
2009-07-01 19:15:20 +01:00
static void tagmon ( const Arg * arg ) ;
2008-06-11 09:12:06 +01:00
static void togglebar ( const Arg * arg ) ;
static void togglefloating ( const Arg * arg ) ;
static void toggletag ( const Arg * arg ) ;
static void toggleview ( const Arg * arg ) ;
2015-11-08 22:48:43 +01:00
static void unfocus ( Client * c , int setfocus ) ;
static void unmanage ( Client * c , int destroyed ) ;
2008-06-11 09:12:06 +01:00
static void unmapnotify ( XEvent * e ) ;
2009-06-22 20:29:59 +01:00
static void updatebarpos ( Monitor * m ) ;
2009-06-22 14:58:08 +01:00
static void updatebars ( void ) ;
2012-03-25 17:49:35 +02:00
static void updateclientlist ( void ) ;
2018-05-02 18:09:50 -04:00
static int updategeom ( void ) ;
2008-08-25 09:44:23 +01:00
static void updatenumlockmask ( void ) ;
2008-06-11 09:12:06 +01:00
static void updatesizehints ( Client * c ) ;
2008-12-12 19:49:06 +00:00
static void updatestatus ( void ) ;
2008-06-11 09:12:06 +01:00
static void updatetitle ( Client * c ) ;
2018-03-14 13:58:06 -04:00
static void updatewindowtype ( Client * c ) ;
2008-06-11 09:12:06 +01:00
static void updatewmhints ( Client * c ) ;
static void view ( const Arg * arg ) ;
2020-12-01 09:34:31 -05:00
static void warp ( const Client * c ) ;
2009-06-30 19:39:59 +01:00
static Client * wintoclient ( Window w ) ;
static Monitor * wintomon ( Window w ) ;
2008-06-11 09:12:06 +01:00
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 ) ;
2007-10-18 10:28:41 +02:00
/* variables */
2009-07-12 22:49:06 +01:00
static const char broken [ ] = " broken " ;
2009-09-16 15:59:54 +01:00
static char stext [ 256 ] ;
added some comments regarding FAQ about s{x,y,w,h}, w{x,y,w,h}, b{y,h,lw}
2008-08-18 09:10:21 +01:00
static int screen ;
2009-07-09 21:52:17 +01:00
static int sw , sh ; /* X display screen geometry width, height */
2009-06-20 15:10:04 +01:00
static int bh , blw = 0 ; /* bar geometry */
2016-05-22 22:33:56 +02:00
static int lrpad ; /* sum of left and right padding for text */
2008-06-11 09:12:06 +01:00
static int ( * xerrorxlib ) ( Display * , XErrorEvent * ) ;
2008-07-16 18:17:42 +01:00
static unsigned int numlockmask = 0 ;
2008-06-11 09:12:06 +01:00
static void ( * handler [ LASTEvent ] ) ( XEvent * ) = {
2007-10-18 10:28:41 +02:00
[ ButtonPress ] = buttonpress ,
2010-05-30 10:02:56 +01:00
[ ClientMessage ] = clientmessage ,
2007-10-18 10:28:41 +02:00
[ ConfigureRequest ] = configurerequest ,
[ ConfigureNotify ] = configurenotify ,
[ DestroyNotify ] = destroynotify ,
[ EnterNotify ] = enternotify ,
[ Expose ] = expose ,
2007-11-17 19:59:13 +01:00
[ FocusIn ] = focusin ,
2007-10-18 10:28:41 +02:00
[ KeyPress ] = keypress ,
[ MappingNotify ] = mappingnotify ,
[ MapRequest ] = maprequest ,
2011-11-15 20:16:58 +01:00
[ MotionNotify ] = motionnotify ,
2007-10-18 10:28:41 +02:00
[ PropertyNotify ] = propertynotify ,
[ UnmapNotify ] = unmapnotify
} ;
2008-06-11 09:12:06 +01:00
static Atom wmatom [ WMLast ] , netatom [ NetLast ] ;
2021-04-09 01:24:48 -04:00
static int restart = 0 ;
2015-11-08 22:48:43 +01:00
static int running = 1 ;
2013-06-16 15:20:29 +02:00
static Cur * cursor [ CurLast ] ;
2017-11-03 21:20:48 +01:00
static Clr * * scheme ;
2008-06-11 09:12:06 +01:00
static Display * dpy ;
2013-06-16 15:20:29 +02:00
static Drw * drw ;
static Monitor * mons , * selmon ;
2016-12-05 10:09:49 +01:00
static Window root , wmcheckwin ;
2009-07-02 20:56:23 +01:00
2007-10-18 10:28:41 +02:00
/* configuration, allows nested code to access above variables */
# include "config.h"
2008-05-22 11:04:19 +01:00
2021-04-08 23:16:19 -04:00
struct Pertag {
unsigned int curtag , prevtag ; /* current and previous tag */
int nmasters [ LENGTH ( tags ) + 1 ] ; /* number of windows in master area */
float mfacts [ LENGTH ( tags ) + 1 ] ; /* mfacts per tag */
unsigned int sellts [ LENGTH ( tags ) + 1 ] ; /* selected layouts */
const Layout * ltidxs [ LENGTH ( tags ) + 1 ] [ 2 ] ; /* matrix of tags and layouts indexes */
int showbars [ LENGTH ( tags ) + 1 ] ; /* display bar for the current tag */
} ;
2008-07-16 18:17:42 +01:00
/* compile-time check if all tags fit into an unsigned int bit array. */
2009-07-14 16:01:14 +01:00
struct NumTags { char limitexceeded [ LENGTH ( tags ) > 31 ? - 1 : 1 ] ; } ;
2007-10-18 10:28:41 +02:00
2007-10-18 17:02:19 +02:00
/* function implementations */
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
applyrules ( Client * c )
{
2009-07-12 22:49:06 +01:00
const char * class , * instance ;
2008-07-16 18:17:42 +01:00
unsigned int i ;
2009-07-08 18:59:20 +01:00
const Rule * r ;
2009-07-09 21:52:17 +01:00
Monitor * m ;
2011-08-15 18:44:12 +02:00
XClassHint ch = { NULL , NULL } ;
2007-09-15 22:25:27 +02:00
2007-09-16 11:53:14 +02:00
/* rule matching */
2015-11-08 22:48:43 +01:00
c - > isfloating = 0 ;
2015-11-07 14:04:49 +01:00
c - > tags = 0 ;
2011-08-15 18:44:12 +02:00
XGetClassHint ( dpy , c - > win , & ch ) ;
class = ch . res_class ? ch . res_class : broken ;
instance = ch . res_name ? ch . res_name : broken ;
2015-11-08 23:11:48 +01:00
for ( i = 0 ; i < LENGTH ( rules ) ; i + + ) {
2011-08-15 18:44:12 +02:00
r = & rules [ i ] ;
2015-11-08 23:11:48 +01:00
if ( ( ! r - > title | | strstr ( c - > name , r - > title ) )
2011-08-15 18:44:12 +02:00
& & ( ! r - > class | | strstr ( class , r - > class ) )
& & ( ! r - > instance | | strstr ( instance , r - > instance ) ) )
{
c - > isfloating = r - > isfloating ;
c - > tags | = r - > tags ;
2015-11-08 23:11:48 +01:00
for ( m = mons ; m & & m - > num ! = r - > monitor ; m = m - > next ) ;
if ( m )
2011-08-15 18:44:12 +02:00
c - > mon = m ;
2007-09-16 11:53:14 +02:00
}
2008-02-26 22:51:23 +00:00
}
2015-11-08 23:11:48 +01:00
if ( ch . res_class )
2011-08-15 18:44:12 +02:00
XFree ( ch . res_class ) ;
2015-11-08 23:11:48 +01:00
if ( ch . res_name )
2011-08-15 18:44:12 +02:00
XFree ( ch . res_name ) ;
2009-06-23 17:17:25 +01:00
c - > tags = c - > tags & TAGMASK ? c - > tags & TAGMASK : c - > mon - > tagset [ c - > mon - > seltags ] ;
2007-09-15 22:25:27 +02:00
}
2015-11-08 22:48:43 +01:00
int
2021-04-09 11:20:47 -04:00
applysizehints ( Client * c , int * x , int * y , int * w , int * h , int * bw , int interact )
2015-11-08 23:11:48 +01:00
{
2015-11-08 22:48:43 +01:00
int baseismin ;
2009-06-30 20:15:31 +01:00
Monitor * m = c - > mon ;
2009-03-02 10:43:48 +00:00
/* set minimum possible */
* w = MAX ( 1 , * w ) ;
* h = MAX ( 1 , * h ) ;
2015-11-08 23:11:48 +01:00
if ( interact ) {
if ( * x > sw )
2009-07-02 18:30:01 +01:00
* x = sw - WIDTH ( c ) ;
2015-11-08 23:11:48 +01:00
if ( * y > sh )
2009-07-02 18:30:01 +01:00
* y = sh - HEIGHT ( c ) ;
2021-04-09 11:20:47 -04:00
if ( * x + * w + 2 * * bw < 0 )
2009-07-02 18:30:01 +01:00
* x = 0 ;
2021-04-09 11:20:47 -04:00
if ( * y + * h + 2 * * bw < 0 )
2009-07-02 18:30:01 +01:00
* y = 0 ;
2015-11-08 23:11:48 +01:00
} else {
if ( * x > = m - > wx + m - > ww )
2011-11-04 20:02:35 +01:00
* x = m - > wx + m - > ww - WIDTH ( c ) ;
2015-11-08 23:11:48 +01:00
if ( * y > = m - > wy + m - > wh )
2011-11-04 20:02:35 +01:00
* y = m - > wy + m - > wh - HEIGHT ( c ) ;
2021-04-09 11:20:47 -04:00
if ( * x + * w + 2 * * bw < = m - > wx )
2011-11-04 20:02:35 +01:00
* x = m - > wx ;
2021-04-09 11:20:47 -04:00
if ( * y + * h + 2 * * bw < = m - > wy )
2011-11-04 20:02:35 +01:00
* y = m - > wy ;
2009-07-02 18:30:01 +01:00
}
2015-11-08 23:11:48 +01:00
if ( * h < bh )
2009-03-17 19:53:00 +00:00
* h = bh ;
2015-11-08 23:11:48 +01:00
if ( * w < bh )
2009-03-17 19:53:00 +00:00
* w = bh ;
2015-11-08 23:11:48 +01:00
if ( resizehints | | c - > isfloating | | ! c - > mon - > lt [ c - > mon - > sellt ] - > arrange ) {
2009-03-17 19:53:00 +00:00
/* see last two sentences in ICCCM 4.1.2.3 */
baseismin = c - > basew = = c - > minw & & c - > baseh = = c - > minh ;
2015-11-08 23:11:48 +01:00
if ( ! baseismin ) { /* temporarily remove base dimensions */
2009-03-17 19:53:00 +00:00
* w - = c - > basew ;
* h - = c - > baseh ;
}
/* adjust for aspect limits */
2015-11-08 23:11:48 +01:00
if ( c - > mina > 0 & & c - > maxa > 0 ) {
if ( c - > maxa < ( float ) * w / * h )
2009-07-17 15:28:07 +01:00
* w = * h * c - > maxa + 0.5 ;
2015-11-08 23:11:48 +01:00
else if ( c - > mina < ( float ) * h / * w )
2009-07-17 15:28:07 +01:00
* h = * w * c - > mina + 0.5 ;
2009-03-17 19:53:00 +00:00
}
2015-11-08 23:11:48 +01:00
if ( baseismin ) { /* increment calculation requires this */
2009-03-17 19:53:00 +00:00
* w - = c - > basew ;
* h - = c - > baseh ;
}
/* adjust for increment value */
2015-11-08 23:11:48 +01:00
if ( c - > incw )
2009-03-17 19:53:00 +00:00
* w - = * w % c - > incw ;
2015-11-08 23:11:48 +01:00
if ( c - > inch )
2009-03-17 19:53:00 +00:00
* h - = * h % c - > inch ;
/* restore base dimensions */
2010-09-25 13:39:08 +00:00
* w = MAX ( * w + c - > basew , c - > minw ) ;
* h = MAX ( * h + c - > baseh , c - > minh ) ;
2015-11-08 23:11:48 +01:00
if ( c - > maxw )
2009-03-17 19:53:00 +00:00
* w = MIN ( * w , c - > maxw ) ;
2015-11-08 23:11:48 +01:00
if ( c - > maxh )
2009-03-17 19:53:00 +00:00
* h = MIN ( * h , c - > maxh ) ;
}
2021-04-09 11:20:47 -04:00
return * x ! = c - > x | | * y ! = c - > y | | * w ! = c - > w | | * h ! = c - > h | | * bw ! = c - > bw ;
2009-03-02 10:43:48 +00:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
arrange ( Monitor * m )
{
if ( m )
2009-09-27 10:31:14 +01:00
showhide ( m - > stack ) ;
2015-11-08 23:11:48 +01:00
else for ( m = mons ; m ; m = m - > next )
2009-06-23 17:17:25 +01:00
showhide ( m - > stack ) ;
2015-11-08 23:11:48 +01:00
if ( m ) {
2009-09-27 10:31:14 +01:00
arrangemon ( m ) ;
2012-02-08 19:54:05 +01:00
restack ( m ) ;
2015-11-08 23:11:48 +01:00
} else for ( m = mons ; m ; m = m - > next )
2009-09-27 10:31:14 +01:00
arrangemon ( m ) ;
}
void
2015-11-08 23:11:48 +01:00
arrangemon ( Monitor * m )
{
2021-04-09 11:20:47 -04:00
Client * c ;
2009-09-27 10:31:14 +01:00
strncpy ( m - > ltsymbol , m - > lt [ m - > sellt ] - > symbol , sizeof m - > ltsymbol ) ;
2015-11-08 23:11:48 +01:00
if ( m - > lt [ m - > sellt ] - > arrange )
2009-09-27 10:31:14 +01:00
m - > lt [ m - > sellt ] - > arrange ( m ) ;
2021-04-09 11:20:47 -04:00
else
/* <>< case; rather than providing an arrange function and upsetting other logic that tests for its presence, simply add borders here */
for ( c = selmon - > clients ; c ; c = c - > next )
if ( ISVISIBLE ( c ) & & c - > bw = = 0 )
resize ( c , c - > x , c - > y , c - > w - 2 * borderpx , c - > h - 2 * borderpx , borderpx , 0 ) ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
attach ( Client * c )
{
2009-06-23 17:34:20 +01:00
c - > next = c - > mon - > clients ;
c - > mon - > clients = c ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
attachstack ( Client * c )
{
2009-06-23 17:34:20 +01:00
c - > snext = c - > mon - > stack ;
c - > mon - > stack = c ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
buttonpress ( XEvent * e )
{
2008-07-16 18:17:42 +01:00
unsigned int i , x , click ;
2008-06-20 16:52:07 +01:00
Arg arg = { 0 } ;
2007-09-16 11:53:14 +02:00
Client * c ;
2009-06-24 19:45:47 +01:00
Monitor * m ;
2007-09-16 11:53:14 +02:00
XButtonPressedEvent * ev = & e - > xbutton ;
2007-09-15 22:25:27 +02:00
2008-06-15 10:52:57 +01:00
click = ClkRootWin ;
2009-06-24 19:45:47 +01:00
/* focus monitor if necessary */
2015-11-08 23:11:48 +01:00
if ( ( m = wintomon ( ev - > window ) ) & & m ! = selmon ) {
2015-11-08 22:48:43 +01:00
unfocus ( selmon - > sel , 1 ) ;
2009-06-27 18:39:03 +01:00
selmon = m ;
focus ( NULL ) ;
}
2015-11-08 23:11:48 +01:00
if ( ev - > window = = selmon - > barwin ) {
2009-07-09 11:29:01 +01:00
i = x = 0 ;
2011-07-27 19:59:10 +02:00
do
2009-06-20 15:10:04 +01:00
x + = TEXTW ( tags [ i ] ) ;
2015-11-08 23:11:48 +01:00
while ( ev - > x > = x & & + + i < LENGTH ( tags ) ) ;
if ( i < LENGTH ( tags ) ) {
2008-06-20 16:52:07 +01:00
click = ClkTagBar ;
arg . ui = 1 < < i ;
2015-11-08 23:11:48 +01:00
} else if ( ev - > x < x + blw )
2008-06-12 13:10:14 +01:00
click = ClkLtSymbol ;
2020-03-03 16:23:53 -06:00
else if ( ev - > x > selmon - > ww - ( int ) TEXTW ( stext ) )
2008-06-12 13:10:14 +01:00
click = ClkStatusText ;
else
click = ClkWinTitle ;
2015-11-08 23:11:48 +01:00
} else if ( ( c = wintoclient ( ev - > window ) ) ) {
2008-06-15 10:52:57 +01:00
focus ( c ) ;
2017-01-07 17:21:29 +01:00
restack ( selmon ) ;
XAllowEvents ( dpy , ReplayPointer , CurrentTime ) ;
2008-06-11 20:41:28 +01:00
click = ClkClientWin ;
2008-06-15 10:52:57 +01:00
}
2015-11-08 23:11:48 +01:00
for ( i = 0 ; i < LENGTH ( buttons ) ; i + + )
if ( click = = buttons [ i ] . click & & buttons [ i ] . func & & buttons [ i ] . button = = ev - > button
2009-07-14 16:26:04 +01:00
& & CLEANMASK ( buttons [ i ] . mask ) = = CLEANMASK ( ev - > state ) )
2008-09-01 22:18:50 +01:00
buttons [ i ] . func ( click = = ClkTagBar & & buttons [ i ] . arg . i = = 0 ? & arg : & buttons [ i ] . arg ) ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
checkotherwm ( void )
{
2008-09-06 08:59:51 +01:00
xerrorxlib = XSetErrorHandler ( xerrorstart ) ;
2007-09-16 12:34:08 +02:00
/* this causes an error if some other window manager is running */
2007-12-22 14:30:47 +00:00
XSelectInput ( dpy , DefaultRootWindow ( dpy ) , SubstructureRedirectMask ) ;
2007-09-16 12:34:08 +02:00
XSync ( dpy , False ) ;
2008-09-06 08:59:51 +01:00
XSetErrorHandler ( xerror ) ;
2007-09-16 12:34:08 +02:00
XSync ( dpy , False ) ;
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
cleanup ( void )
{
2008-08-12 21:24:40 +02:00
Arg a = { . ui = ~ 0 } ;
2008-06-11 10:26:57 +01:00
Layout foo = { " " , NULL } ;
2009-06-23 17:17:25 +01:00
Monitor * m ;
2015-10-20 23:27:31 +02:00
size_t i ;
2008-06-11 10:25:02 +01:00
2008-06-11 09:12:06 +01:00
view ( & a ) ;
2009-07-06 20:12:47 +01:00
selmon - > lt [ selmon - > sellt ] = & foo ;
2015-11-08 23:11:48 +01:00
for ( m = mons ; m ; m = m - > next )
while ( m - > stack )
2015-11-08 22:48:43 +01:00
unmanage ( m - > stack , 0 ) ;
2008-02-18 17:08:22 +00:00
XUngrabKey ( dpy , AnyKey , AnyModifier , root ) ;
2015-11-08 23:11:48 +01:00
while ( mons )
2009-09-22 20:33:42 +01:00
cleanupmon ( mons ) ;
2015-11-08 23:11:48 +01:00
for ( i = 0 ; i < CurLast ; i + + )
2015-10-20 23:27:31 +02:00
drw_cur_free ( drw , cursor [ i ] ) ;
2016-12-05 10:01:33 +01:00
for ( i = 0 ; i < LENGTH ( colors ) ; i + + )
2016-05-22 22:33:56 +02:00
free ( scheme [ i ] ) ;
2016-12-05 10:09:49 +01:00
XDestroyWindow ( dpy , wmcheckwin ) ;
2013-06-16 15:20:29 +02:00
drw_free ( drw ) ;
2008-02-18 17:08:22 +00:00
XSync ( dpy , False ) ;
XSetInputFocus ( dpy , PointerRoot , RevertToPointerRoot , CurrentTime ) ;
2012-03-25 17:46:03 +02:00
XDeleteProperty ( dpy , root , netatom [ NetActiveWindow ] ) ;
2007-09-15 22:25:27 +02:00
}
2009-06-22 14:58:08 +01:00
void
2015-11-08 23:11:48 +01:00
cleanupmon ( Monitor * mon )
{
2009-06-22 14:58:08 +01:00
Monitor * m ;
2015-11-08 23:11:48 +01:00
if ( mon = = mons )
2009-09-22 20:33:42 +01:00
mons = mons - > next ;
else {
2015-11-08 23:11:48 +01:00
for ( m = mons ; m & & m - > next ! = mon ; m = m - > next ) ;
2009-09-22 20:33:42 +01:00
m - > next = mon - > next ;
2009-06-22 14:58:08 +01:00
}
2009-09-22 20:33:42 +01:00
XUnmapWindow ( dpy , mon - > barwin ) ;
XDestroyWindow ( dpy , mon - > barwin ) ;
free ( mon ) ;
2009-06-22 14:58:08 +01:00
}
2011-04-15 08:12:20 +00:00
void
2015-11-08 23:11:48 +01:00
clientmessage ( XEvent * e )
{
2011-04-15 08:12:20 +00:00
XClientMessageEvent * cme = & e - > xclient ;
Client * c = wintoclient ( cme - > window ) ;
2015-11-08 23:11:48 +01:00
if ( ! c )
2011-04-15 08:12:20 +00:00
return ;
2015-11-08 23:11:48 +01:00
if ( cme - > message_type = = netatom [ NetWMState ] ) {
2017-01-07 17:21:28 +01:00
if ( cme - > data . l [ 1 ] = = netatom [ NetWMFullscreen ]
| | cme - > data . l [ 2 ] = = netatom [ NetWMFullscreen ] )
2011-11-06 20:30:06 +01:00
setfullscreen ( c , ( cme - > data . l [ 0 ] = = 1 /* _NET_WM_STATE_ADD */
2017-05-08 21:08:27 +02:00
| | ( cme - > data . l [ 0 ] = = 2 /* _NET_WM_STATE_TOGGLE */ & & ! c - > isfullscreen ) ) ) ;
2015-11-08 23:11:48 +01:00
} else if ( cme - > message_type = = netatom [ NetActiveWindow ] ) {
2016-12-05 10:16:46 +01:00
if ( c ! = selmon - > sel & & ! c - > isurgent )
seturgent ( c , 1 ) ;
2011-04-15 08:12:20 +00:00
}
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
configure ( Client * c )
{
2007-09-16 11:53:14 +02:00
XConfigureEvent ce ;
2007-09-15 22:25:27 +02:00
2007-09-16 11:53:14 +02:00
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 ;
2008-03-17 16:29:50 +00:00
ce . border_width = c - > bw ;
2007-09-16 11:53:14 +02:00
ce . above = None ;
ce . override_redirect = False ;
XSendEvent ( dpy , c - > win , False , StructureNotifyMask , ( XEvent * ) & ce ) ;
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
configurenotify ( XEvent * e )
{
2009-06-22 14:58:08 +01:00
Monitor * m ;
2015-12-19 20:25:26 +01:00
Client * c ;
2007-09-16 11:53:14 +02:00
XConfigureEvent * ev = & e - > xconfigure ;
2015-11-08 22:48:43 +01:00
int dirty ;
2007-09-16 11:53:14 +02:00
2015-10-20 23:28:30 +02:00
/* TODO: updategeom handling sucks, needs to be simplified */
2015-11-08 23:11:48 +01:00
if ( ev - > window = = root ) {
2012-07-08 09:43:11 +02:00
dirty = ( sw ! = ev - > width | | sh ! = ev - > height ) ;
2008-03-19 09:27:17 +00:00
sw = ev - > width ;
sh = ev - > height ;
2015-11-08 23:11:48 +01:00
if ( updategeom ( ) | | dirty ) {
2013-06-16 15:20:29 +02:00
drw_resize ( drw , sw , bh ) ;
2012-07-08 09:43:11 +02:00
updatebars ( ) ;
2015-12-19 20:25:26 +01:00
for ( m = mons ; m ; m = m - > next ) {
for ( c = m - > clients ; c ; c = c - > next )
if ( c - > isfullscreen )
2021-04-09 11:20:47 -04:00
resizeclient ( c , m - > mx , m - > my , m - > mw , m - > mh , 0 ) ;
2012-07-08 09:43:11 +02:00
XMoveResizeWindow ( dpy , m - > barwin , m - > wx , m - > by , m - > ww , bh ) ;
2015-12-19 20:25:26 +01:00
}
2012-07-08 09:43:11 +02:00
focus ( NULL ) ;
arrange ( NULL ) ;
}
2008-03-19 09:27:17 +00:00
}
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
configurerequest ( XEvent * e )
{
2007-09-15 22:25:27 +02:00
Client * c ;
2009-06-30 15:51:09 +01:00
Monitor * m ;
2007-09-15 22:25:27 +02:00
XConfigureRequestEvent * ev = & e - > xconfigurerequest ;
XWindowChanges wc ;
2015-11-08 23:11:48 +01:00
if ( ( c = wintoclient ( ev - > window ) ) ) {
if ( ev - > value_mask & CWBorderWidth )
2008-03-17 16:29:50 +00:00
c - > bw = ev - > border_width ;
2015-11-08 23:11:48 +01:00
else if ( c - > isfloating | | ! selmon - > lt [ selmon - > sellt ] - > arrange ) {
2009-06-30 15:51:09 +01:00
m = c - > mon ;
2015-11-08 23:11:48 +01:00
if ( ev - > value_mask & CWX ) {
2011-07-20 18:30:51 +00:00
c - > oldx = c - > x ;
2009-06-30 15:51:09 +01:00
c - > x = m - > mx + ev - > x ;
2011-07-20 18:30:51 +00:00
}
2015-11-08 23:11:48 +01:00
if ( ev - > value_mask & CWY ) {
2011-07-20 18:30:51 +00:00
c - > oldy = c - > y ;
2009-06-30 15:51:09 +01:00
c - > y = m - > my + ev - > y ;
2011-07-20 18:30:51 +00:00
}
2015-11-08 23:11:48 +01:00
if ( ev - > value_mask & CWWidth ) {
2011-07-20 18:30:51 +00:00
c - > oldw = c - > w ;
2007-09-15 22:25:27 +02:00
c - > w = ev - > width ;
2011-07-20 18:30:51 +00:00
}
2015-11-08 23:11:48 +01:00
if ( ev - > value_mask & CWHeight ) {
2011-07-20 18:30:51 +00:00
c - > oldh = c - > h ;
2007-09-15 22:25:27 +02:00
c - > h = ev - > height ;
2011-07-20 18:30:51 +00:00
}
2015-11-08 23:11:48 +01:00
if ( ( c - > x + c - > w ) > m - > mx + m - > mw & & c - > isfloating )
2011-07-20 18:33:19 +00:00
c - > x = m - > mx + ( m - > mw / 2 - WIDTH ( c ) / 2 ) ; /* center in x direction */
2015-11-08 23:11:48 +01:00
if ( ( c - > y + c - > h ) > m - > my + m - > mh & & c - > isfloating )
2011-07-20 18:33:19 +00:00
c - > y = m - > my + ( m - > mh / 2 - HEIGHT ( c ) / 2 ) ; /* center in y direction */
2015-11-08 23:11:48 +01:00
if ( ( ev - > value_mask & ( CWX | CWY ) ) & & ! ( ev - > value_mask & ( CWWidth | CWHeight ) ) )
2007-09-15 22:25:27 +02:00
configure ( c ) ;
2015-11-08 23:11:48 +01:00
if ( ISVISIBLE ( c ) )
2007-09-15 22:25:27 +02:00
XMoveResizeWindow ( dpy , c - > win , c - > x , c - > y , c - > w , c - > h ) ;
2015-11-08 23:11:48 +01:00
} else
2007-09-15 22:25:27 +02:00
configure ( c ) ;
2015-11-08 23:11:48 +01:00
} else {
2007-09-15 22:25:27 +02:00
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 ) ;
}
2009-09-21 19:51:17 +01:00
Monitor *
2015-11-08 23:11:48 +01:00
createmon ( void )
{
2009-09-21 19:51:17 +01:00
Monitor * m ;
2021-04-08 23:16:19 -04:00
unsigned int i ;
2009-09-21 19:51:17 +01:00
2015-10-20 23:30:31 +02:00
m = ecalloc ( 1 , sizeof ( Monitor ) ) ;
2009-09-21 19:51:17 +01:00
m - > tagset [ 0 ] = m - > tagset [ 1 ] = 1 ;
m - > mfact = mfact ;
2011-10-25 20:40:46 +01:00
m - > nmaster = nmaster ;
2009-09-21 19:51:17 +01:00
m - > showbar = showbar ;
m - > topbar = topbar ;
2021-04-09 10:50:41 -04:00
m - > gappih = gappih ;
m - > gappiv = gappiv ;
m - > gappoh = gappoh ;
m - > gappov = gappov ;
2009-09-21 19:51:17 +01:00
m - > lt [ 0 ] = & layouts [ 0 ] ;
m - > lt [ 1 ] = & layouts [ 1 % LENGTH ( layouts ) ] ;
2009-09-22 09:53:11 +01:00
strncpy ( m - > ltsymbol , layouts [ 0 ] . symbol , sizeof m - > ltsymbol ) ;
2021-04-08 23:16:19 -04:00
m - > pertag = ecalloc ( 1 , sizeof ( Pertag ) ) ;
m - > pertag - > curtag = m - > pertag - > prevtag = 1 ;
for ( i = 0 ; i < = LENGTH ( tags ) ; i + + ) {
m - > pertag - > nmasters [ i ] = m - > nmaster ;
m - > pertag - > mfacts [ i ] = m - > mfact ;
m - > pertag - > ltidxs [ i ] [ 0 ] = m - > lt [ 0 ] ;
m - > pertag - > ltidxs [ i ] [ 1 ] = m - > lt [ 1 ] ;
m - > pertag - > sellts [ i ] = m - > sellt ;
m - > pertag - > showbars [ i ] = m - > showbar ;
}
2009-09-21 19:51:17 +01:00
return m ;
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
destroynotify ( XEvent * e )
{
2007-09-15 22:25:27 +02:00
Client * c ;
XDestroyWindowEvent * ev = & e - > xdestroywindow ;
2015-11-08 23:11:48 +01:00
if ( ( c = wintoclient ( ev - > window ) ) )
2015-11-08 22:48:43 +01:00
unmanage ( c , 1 ) ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
detach ( Client * c )
{
2008-07-03 10:58:35 +01:00
Client * * tc ;
2008-06-11 09:12:06 +01:00
2015-11-08 23:11:48 +01:00
for ( tc = & c - > mon - > clients ; * tc & & * tc ! = c ; tc = & ( * tc ) - > next ) ;
2008-07-03 10:58:35 +01:00
* tc = c - > next ;
2007-09-16 11:53:14 +02:00
}
2007-09-15 22:25:27 +02:00
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
detachstack ( Client * c )
{
2009-06-30 19:45:25 +01:00
Client * * tc , * t ;
2007-09-16 11:53:14 +02:00
2015-11-08 23:11:48 +01:00
for ( tc = & c - > mon - > stack ; * tc & & * tc ! = c ; tc = & ( * tc ) - > snext ) ;
2007-09-16 11:53:14 +02:00
* tc = c - > snext ;
2009-06-30 19:39:59 +01:00
2015-11-08 23:11:48 +01:00
if ( c = = c - > mon - > sel ) {
for ( t = c - > mon - > stack ; t & & ! ISVISIBLE ( t ) ; t = t - > snext ) ;
2009-06-30 19:45:25 +01:00
c - > mon - > sel = t ;
2009-06-30 19:39:59 +01:00
}
2007-09-16 11:53:14 +02:00
}
2009-07-02 20:37:26 +01:00
Monitor *
2015-11-08 23:11:48 +01:00
dirtomon ( int dir )
{
2009-07-02 20:37:26 +01:00
Monitor * m = NULL ;
2015-11-08 23:11:48 +01:00
if ( dir > 0 ) {
if ( ! ( m = selmon - > next ) )
2009-07-02 20:37:26 +01:00
m = mons ;
2015-11-08 23:11:48 +01:00
} else if ( selmon = = mons )
for ( m = mons ; m - > next ; m = m - > next ) ;
2011-07-27 19:59:10 +02:00
else
2015-11-08 23:11:48 +01:00
for ( m = mons ; m - > next ! = selmon ; m = m - > next ) ;
2009-07-02 20:37:26 +01:00
return m ;
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
drawbar ( Monitor * m )
{
2020-04-22 15:48:27 +01:00
int x , w , tw = 0 ;
2016-05-22 22:33:56 +02:00
int boxs = drw - > fonts - > h / 9 ;
int boxw = drw - > fonts - > h / 6 + 2 ;
2009-09-16 15:59:54 +01:00
unsigned int i , occ = 0 , urg = 0 ;
2023-10-07 22:09:04 -04:00
char * ts = stext ;
char * tp = stext ;
int tx = 0 ;
char ctmp ;
2008-08-04 17:39:36 +01:00
Client * c ;
2016-05-22 22:33:56 +02:00
/* draw status first so it can be overdrawn by tags later */
if ( m = = selmon ) { /* status is only drawn on selected monitor */
2021-04-09 01:23:16 -04:00
drw_setscheme ( drw , scheme [ SchemeStatus ] ) ;
2020-04-22 15:48:27 +01:00
tw = TEXTW ( stext ) - lrpad + 2 ; /* 2px right padding */
2023-10-07 22:09:04 -04:00
while ( 1 ) {
if ( ( unsigned int ) * ts > LENGTH ( colors ) ) { ts + + ; continue ; }
ctmp = * ts ;
* ts = ' \0 ' ;
drw_text ( drw , m - > ww - tw + tx , 0 , tw - tx , bh , 0 , tp , 0 ) ;
tx + = TEXTW ( tp ) - lrpad ;
if ( ctmp = = ' \0 ' ) { break ; }
drw_setscheme ( drw , scheme [ ( unsigned int ) ( ctmp - 1 ) ] ) ;
* ts = ctmp ;
tp = + + ts ;
}
2016-05-22 22:33:56 +02:00
}
2015-10-20 23:34:49 +02:00
2015-11-08 23:11:48 +01:00
for ( c = m - > clients ; c ; c = c - > next ) {
2009-06-23 17:17:25 +01:00
occ | = c - > tags ;
2015-11-08 23:11:48 +01:00
if ( c - > isurgent )
2009-06-23 17:17:25 +01:00
urg | = c - > tags ;
2008-08-04 17:39:36 +01:00
}
2013-06-16 15:20:29 +02:00
x = 0 ;
2015-11-08 23:11:48 +01:00
for ( i = 0 ; i < LENGTH ( tags ) ; i + + ) {
2013-06-16 15:20:29 +02:00
w = TEXTW ( tags [ i ] ) ;
2021-04-09 01:23:16 -04:00
drw_setscheme ( drw , scheme [ m - > tagset [ m - > seltags ] & 1 < < i ? SchemeTagsSel : SchemeTagsNorm ] ) ;
2016-05-22 22:33:56 +02:00
drw_text ( drw , x , 0 , w , bh , lrpad / 2 , tags [ i ] , urg & 1 < < i ) ;
if ( occ & 1 < < i )
drw_rect ( drw , x + boxs , boxs , boxw , boxw ,
2017-05-08 21:08:27 +02:00
m = = selmon & & selmon - > sel & & selmon - > sel - > tags & 1 < < i ,
urg & 1 < < i ) ;
2013-06-16 15:20:29 +02:00
x + = w ;
2008-02-21 10:31:06 +00:00
}
2013-06-16 15:20:29 +02:00
w = blw = TEXTW ( m - > ltsymbol ) ;
2021-04-09 01:23:16 -04:00
drw_setscheme ( drw , scheme [ SchemeTagsNorm ] ) ;
2016-05-22 22:33:56 +02:00
x = drw_text ( drw , x , 0 , w , bh , lrpad / 2 , m - > ltsymbol , 0 ) ;
2020-04-22 15:48:27 +01:00
if ( ( w = m - > ww - tw - x ) > bh ) {
2015-11-08 23:11:48 +01:00
if ( m - > sel ) {
2021-04-09 11:06:06 -04:00
// drw_setscheme(drw, scheme[m == selmon ? SchemeInfoSel : SchemeInfoNorm]);
2021-04-14 22:49:17 -04:00
drw_text ( drw , x , 0 , w , bh , lrpad / 2 , " " , 0 ) ;
2016-05-22 22:33:56 +02:00
if ( m - > sel - > isfloating )
drw_rect ( drw , x + boxs , boxs , boxw , boxw , m - > sel - > isfixed , 0 ) ;
2015-11-08 23:11:48 +01:00
} else {
2021-04-09 01:23:16 -04:00
drw_setscheme ( drw , scheme [ SchemeInfoNorm ] ) ;
2016-05-22 22:33:56 +02:00
drw_rect ( drw , x , 0 , w , bh , 1 , 1 ) ;
2009-06-24 13:51:45 +01:00
}
2009-06-20 15:10:04 +01:00
}
2013-06-16 15:20:29 +02:00
drw_map ( drw , m - > barwin , 0 , 0 , m - > ww , bh ) ;
2007-09-15 22:25:27 +02:00
}
2009-06-20 15:10:04 +01:00
void
2015-11-08 23:11:48 +01:00
drawbars ( void )
{
2009-06-22 14:58:08 +01:00
Monitor * m ;
2009-06-20 15:10:04 +01:00
2015-11-08 23:11:48 +01:00
for ( m = mons ; m ; m = m - > next )
2009-06-22 14:58:08 +01:00
drawbar ( m ) ;
2009-06-20 15:10:04 +01:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
enternotify ( XEvent * e )
{
2011-06-25 09:07:28 +01:00
Client * c ;
2009-06-27 18:39:03 +01:00
Monitor * m ;
2007-09-16 11:53:14 +02:00
XCrossingEvent * ev = & e - > xcrossing ;
2015-11-08 23:11:48 +01:00
if ( ( ev - > mode ! = NotifyNormal | | ev - > detail = = NotifyInferior ) & & ev - > window ! = root )
2008-02-28 20:02:57 +00:00
return ;
2011-06-25 09:07:28 +01:00
c = wintoclient ( ev - > window ) ;
2011-07-10 21:22:22 +01:00
m = c ? c - > mon : wintomon ( ev - > window ) ;
2015-11-08 23:11:48 +01:00
if ( m ! = selmon ) {
2015-11-08 22:48:43 +01:00
unfocus ( selmon - > sel , 1 ) ;
2009-06-27 18:39:03 +01:00
selmon = m ;
2015-11-08 23:11:48 +01:00
} else if ( ! c | | c = = selmon - > sel )
2011-06-25 09:07:28 +01:00
return ;
2011-07-10 21:22:22 +01:00
focus ( c ) ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
expose ( XEvent * e )
{
2009-06-22 14:58:08 +01:00
Monitor * m ;
2007-09-16 11:53:14 +02:00
XExposeEvent * ev = & e - > xexpose ;
2007-09-15 22:25:27 +02:00
2015-11-08 23:11:48 +01:00
if ( ev - > count = = 0 & & ( m = wintomon ( ev - > window ) ) )
2009-06-27 18:39:03 +01:00
drawbar ( m ) ;
2008-02-28 21:38:53 +00:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
focus ( Client * c )
{
if ( ! c | | ! ISVISIBLE ( c ) )
for ( c = selmon - > stack ; c & & ! ISVISIBLE ( c ) ; c = c - > snext ) ;
if ( selmon - > sel & & selmon - > sel ! = c )
2015-11-08 22:48:43 +01:00
unfocus ( selmon - > sel , 0 ) ;
2015-11-08 23:11:48 +01:00
if ( c ) {
if ( c - > mon ! = selmon )
2009-06-24 15:37:32 +01:00
selmon = c - > mon ;
2015-11-08 23:11:48 +01:00
if ( c - > isurgent )
2016-12-05 10:16:46 +01:00
seturgent ( c , 0 ) ;
2007-09-16 11:53:14 +02:00
detachstack ( c ) ;
attachstack ( c ) ;
2015-11-08 22:48:43 +01:00
grabbuttons ( c , 1 ) ;
2016-05-22 22:33:56 +02:00
XSetWindowBorder ( dpy , c - > win , scheme [ SchemeSel ] [ ColBorder ] . pixel ) ;
2011-04-12 20:19:32 +00:00
setfocus ( c ) ;
2015-11-08 23:11:48 +01:00
} else {
2008-02-18 16:47:16 +00:00
XSetInputFocus ( dpy , root , RevertToPointerRoot , CurrentTime ) ;
2012-03-25 17:46:03 +02:00
XDeleteProperty ( dpy , root , netatom [ NetActiveWindow ] ) ;
}
2009-06-23 17:17:25 +01:00
selmon - > sel = c ;
2009-06-20 15:10:04 +01:00
drawbars ( ) ;
2007-09-15 22:25:27 +02:00
}
2017-01-07 17:21:28 +01:00
/* there are some broken focus acquiring clients needing extra handling */
2007-11-17 19:59:13 +01:00
void
2015-11-08 23:11:48 +01:00
focusin ( XEvent * e )
{
2007-11-17 19:59:13 +01:00
XFocusChangeEvent * ev = & e - > xfocus ;
2015-11-08 23:11:48 +01:00
if ( selmon - > sel & & ev - > window ! = selmon - > sel - > win )
2011-04-12 20:19:32 +00:00
setfocus ( selmon - > sel ) ;
2007-11-17 19:59:13 +01:00
}
2009-06-20 15:10:04 +01:00
void
2015-11-08 23:11:48 +01:00
focusmon ( const Arg * arg )
{
2010-09-25 13:39:08 +00:00
Monitor * m ;
2009-06-27 18:50:50 +01:00
2015-11-08 23:11:48 +01:00
if ( ! mons - > next )
2009-06-27 18:50:50 +01:00
return ;
2015-11-08 23:11:48 +01:00
if ( ( m = dirtomon ( arg - > i ) ) = = selmon )
2010-04-01 00:14:15 +01:00
return ;
2017-01-07 17:21:28 +01:00
unfocus ( selmon - > sel , 0 ) ;
2009-06-27 18:50:50 +01:00
selmon = m ;
focus ( NULL ) ;
2020-12-01 09:34:31 -05:00
warp ( selmon - > sel ) ;
2009-06-20 15:10:04 +01:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
focusstack ( const Arg * arg )
{
2008-06-11 09:12:06 +01:00
Client * c = NULL , * i ;
2007-09-15 22:25:27 +02:00
2015-11-08 23:11:48 +01:00
if ( ! selmon - > sel )
2007-09-16 11:53:14 +02:00
return ;
2015-11-08 23:11:48 +01: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 ) )
2008-06-11 09:12:06 +01:00
c = i ;
2015-11-08 23:11:48 +01:00
if ( ! c )
for ( ; i ; i = i - > next )
if ( ISVISIBLE ( i ) )
2008-06-11 09:12:06 +01:00
c = i ;
2007-09-16 11:53:14 +02:00
}
2015-11-08 23:11:48 +01:00
if ( c ) {
2007-09-16 11:53:14 +02:00
focus ( c ) ;
2009-06-20 15:10:04 +01:00
restack ( selmon ) ;
2007-09-16 11:53:14 +02:00
}
2007-09-15 22:25:27 +02:00
}
2011-11-06 20:30:06 +01:00
Atom
2015-11-08 23:11:48 +01:00
getatomprop ( Client * c , Atom prop )
{
2011-11-06 20:30:06 +01:00
int di ;
unsigned long dl ;
unsigned char * p = NULL ;
Atom da , atom = None ;
2015-11-08 23:11:48 +01:00
if ( XGetWindowProperty ( dpy , c - > win , prop , 0L , sizeof atom , False , XA_ATOM ,
2017-05-08 21:08:27 +02:00
& da , & di , & dl , & dl , & p ) = = Success & & p ) {
2011-11-06 20:30:06 +01:00
atom = * ( Atom * ) p ;
XFree ( p ) ;
}
return atom ;
}
2015-11-08 22:48:43 +01:00
int
2015-11-08 23:11:48 +01:00
getrootptr ( int * x , int * y )
{
2009-06-27 18:39:03 +01:00
int di ;
unsigned int dui ;
Window dummy ;
2009-07-02 18:40:04 +01:00
2015-11-08 22:48:43 +01:00
return XQueryPointer ( dpy , root , & dummy , & dummy , x , y , & di , & di , & dui ) ;
2009-06-27 18:39:03 +01:00
}
2007-09-17 16:42:37 +02:00
long
2015-11-08 23:11:48 +01:00
getstate ( Window w )
{
2010-05-30 10:02:56 +01:00
int format ;
2007-09-16 11:53:14 +02:00
long result = - 1 ;
unsigned char * p = NULL ;
2008-07-16 18:17:42 +01:00
unsigned long n , extra ;
2007-09-16 11:53:14 +02:00
Atom real ;
2007-09-15 22:25:27 +02:00
2015-11-08 23:11:48 +01:00
if ( XGetWindowProperty ( dpy , w , wmatom [ WMState ] , 0L , 2L , False , wmatom [ WMState ] ,
2017-05-08 21:08:27 +02:00
& real , & format , & n , & extra , ( unsigned char * * ) & p ) ! = Success )
2007-09-16 11:53:14 +02:00
return - 1 ;
2015-11-08 23:11:48 +01:00
if ( n ! = 0 )
2007-09-16 11:53:14 +02:00
result = * p ;
XFree ( p ) ;
return result ;
2007-09-15 22:25:27 +02:00
}
2015-11-08 22:48:43 +01:00
int
2015-11-08 23:11:48 +01:00
gettextprop ( Window w , Atom atom , char * text , unsigned int size )
{
2007-09-16 11:53:14 +02:00
char * * list = NULL ;
int n ;
XTextProperty name ;
2007-09-15 22:25:27 +02:00
2015-11-08 23:11:48 +01:00
if ( ! text | | size = = 0 )
2015-11-08 22:48:43 +01:00
return 0 ;
2007-09-16 11:53:14 +02:00
text [ 0 ] = ' \0 ' ;
2017-11-03 16:36:32 +01:00
if ( ! XGetTextProperty ( dpy , w , & name , atom ) | | ! name . nitems )
2015-11-08 22:48:43 +01:00
return 0 ;
2015-11-08 23:11:48 +01:00
if ( name . encoding = = XA_STRING )
2007-09-16 11:53:14 +02:00
strncpy ( text , ( char * ) name . value , size - 1 ) ;
else {
2015-11-08 23:11:48 +01:00
if ( XmbTextPropertyToTextList ( dpy , & name , & list , & n ) > = Success & & n > 0 & & * list ) {
2007-09-16 11:53:14 +02:00
strncpy ( text , * list , size - 1 ) ;
XFreeStringList ( list ) ;
2007-09-15 22:25:27 +02:00
}
2007-09-16 11:53:14 +02:00
}
text [ size - 1 ] = ' \0 ' ;
XFree ( name . value ) ;
2015-11-08 22:48:43 +01:00
return 1 ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
grabbuttons ( Client * c , int focused )
{
2008-08-25 09:44:23 +01:00
updatenumlockmask ( ) ;
{
unsigned int i , j ;
unsigned int modifiers [ ] = { 0 , LockMask , numlockmask , numlockmask | LockMask } ;
XUngrabButton ( dpy , AnyButton , AnyModifier , c - > win ) ;
2017-01-07 17:21:29 +01:00
if ( ! focused )
2008-08-25 09:44:23 +01:00
XGrabButton ( dpy , AnyButton , AnyModifier , c - > win , False ,
2017-05-08 21:08:27 +02:00
BUTTONMASK , GrabModeSync , GrabModeSync , None , None ) ;
2017-01-07 17:21:29 +01:00
for ( i = 0 ; i < LENGTH ( buttons ) ; i + + )
if ( buttons [ i ] . click = = ClkClientWin )
for ( j = 0 ; j < LENGTH ( modifiers ) ; j + + )
XGrabButton ( dpy , buttons [ i ] . button ,
2017-05-08 21:08:27 +02:00
buttons [ i ] . mask | modifiers [ j ] ,
c - > win , False , BUTTONMASK ,
GrabModeAsync , GrabModeSync , None , None ) ;
2008-08-25 09:44:23 +01:00
}
2007-09-16 11:53:14 +02:00
}
2007-11-10 19:16:11 +01:00
void
2015-11-08 23:11:48 +01:00
grabkeys ( void )
{
2008-08-25 09:44:23 +01:00
updatenumlockmask ( ) ;
2009-07-02 18:40:04 +01:00
{
2008-08-25 09:44:23 +01:00
unsigned int i , j ;
2008-08-23 09:31:28 +01:00
unsigned int modifiers [ ] = { 0 , LockMask , numlockmask , numlockmask | LockMask } ;
KeyCode code ;
XUngrabKey ( dpy , AnyKey , AnyModifier , root ) ;
2015-11-08 23:11:48 +01:00
for ( i = 0 ; i < LENGTH ( keys ) ; i + + )
if ( ( code = XKeysymToKeycode ( dpy , keys [ i ] . keysym ) ) )
for ( j = 0 ; j < LENGTH ( modifiers ) ; j + + )
2008-09-02 18:47:01 +01:00
XGrabKey ( dpy , code , keys [ i ] . mod | modifiers [ j ] , root ,
2017-05-08 21:08:27 +02:00
True , GrabModeAsync , GrabModeAsync ) ;
2007-11-10 19:16:11 +01:00
}
}
2011-10-25 20:40:46 +01:00
void
2015-11-08 23:11:48 +01:00
incnmaster ( const Arg * arg )
{
2021-04-08 23:16:19 -04:00
unsigned int i ;
2011-10-31 20:09:27 +01:00
selmon - > nmaster = MAX ( selmon - > nmaster + arg - > i , 0 ) ;
2021-04-08 23:16:19 -04:00
for ( i = 0 ; i < LENGTH ( tags ) ; + + i )
if ( selmon - > tagset [ selmon - > seltags ] & 1 < < i )
selmon - > pertag - > nmasters [ i + 1 ] = selmon - > nmaster ;
if ( selmon - > pertag - > curtag = = 0 )
{
selmon - > pertag - > nmasters [ 0 ] = selmon - > nmaster ;
}
2011-10-25 20:40:46 +01:00
arrange ( selmon ) ;
}
2009-09-21 19:51:17 +01:00
# ifdef XINERAMA
2015-11-08 22:48:43 +01:00
static int
2015-11-08 23:11:48 +01:00
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
2012-07-08 09:43:11 +02:00
& & unique [ n ] . width = = info - > width & & unique [ n ] . height = = info - > height )
2015-11-08 22:48:43 +01:00
return 0 ;
return 1 ;
2009-09-21 19:51:17 +01:00
}
# endif /* XINERAMA */
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
keypress ( XEvent * e )
{
2008-07-16 18:17:42 +01:00
unsigned int i ;
2007-09-16 11:53:14 +02:00
KeySym keysym ;
XKeyEvent * ev ;
ev = & e - > xkey ;
2012-11-18 16:39:56 +01:00
keysym = XKeycodeToKeysym ( dpy , ( KeyCode ) ev - > keycode , 0 ) ;
2015-11-08 23:11:48 +01:00
for ( i = 0 ; i < LENGTH ( keys ) ; i + + )
if ( keysym = = keys [ i ] . keysym
2009-07-14 16:26:04 +01:00
& & CLEANMASK ( keys [ i ] . mod ) = = CLEANMASK ( ev - > state )
& & keys [ i ] . func )
2008-06-11 09:12:06 +01:00
keys [ i ] . func ( & ( keys [ i ] . arg ) ) ;
2007-09-16 11:53:14 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
killclient ( const Arg * arg )
{
if ( ! selmon - > sel )
2007-09-15 22:25:27 +02:00
return ;
2015-11-08 23:11:48 +01:00
if ( ! sendevent ( selmon - > sel , wmatom [ WMDelete ] ) ) {
2009-09-08 13:30:18 +01:00
XGrabServer ( dpy ) ;
XSetErrorHandler ( xerrordummy ) ;
XSetCloseDownMode ( dpy , DestroyAll ) ;
2009-06-23 17:17:25 +01:00
XKillClient ( dpy , selmon - > sel - > win ) ;
2009-09-08 13:30:18 +01:00
XSync ( dpy , False ) ;
XSetErrorHandler ( xerror ) ;
XUngrabServer ( dpy ) ;
}
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
manage ( Window w , XWindowAttributes * wa )
{
2007-09-16 11:53:14 +02:00
Client * c , * t = NULL ;
2008-08-18 10:22:46 +01:00
Window trans = None ;
2007-09-16 11:53:14 +02:00
XWindowChanges wc ;
2007-09-15 22:25:27 +02:00
2015-10-20 23:30:31 +02:00
c = ecalloc ( 1 , sizeof ( Client ) ) ;
2007-09-16 11:53:14 +02:00
c - > win = w ;
2016-05-25 16:33:11 -07: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 ;
2009-07-12 22:34:29 +01:00
updatetitle ( c ) ;
2015-11-08 23:11:48 +01:00
if ( XGetTransientForHint ( dpy , w , & trans ) & & ( t = wintoclient ( trans ) ) ) {
2009-06-30 19:56:19 +01:00
c - > mon = t - > mon ;
c - > tags = t - > tags ;
2015-11-08 23:11:48 +01:00
} else {
2009-06-30 19:56:19 +01:00
c - > mon = selmon ;
applyrules ( c ) ;
}
2011-11-06 20:30:06 +01:00
2015-11-08 23:11:48 +01:00
if ( c - > x + WIDTH ( c ) > c - > mon - > mx + c - > mon - > mw )
2011-11-06 20:30:06 +01:00
c - > x = c - > mon - > mx + c - > mon - > mw - WIDTH ( c ) ;
2015-11-08 23:11:48 +01:00
if ( c - > y + HEIGHT ( c ) > c - > mon - > my + c - > mon - > mh )
2011-11-06 20:30:06 +01:00
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 */
c - > y = MAX ( c - > y , ( ( c - > mon - > by = = c - > mon - > my ) & & ( c - > x + ( c - > w / 2 ) > = c - > mon - > wx )
2017-05-08 21:08:27 +02:00
& & ( c - > x + ( c - > w / 2 ) < c - > mon - > wx + c - > mon - > ww ) ) ? bh : c - > mon - > my ) ;
2011-11-06 20:30:06 +01:00
c - > bw = borderpx ;
2008-03-17 16:29:50 +00:00
wc . border_width = c - > bw ;
2007-09-16 11:53:14 +02:00
XConfigureWindow ( dpy , w , CWBorderWidth , & wc ) ;
2016-05-22 22:33:56 +02:00
XSetWindowBorder ( dpy , w , scheme [ SchemeNorm ] [ ColBorder ] . pixel ) ;
2007-09-16 11:53:14 +02:00
configure ( c ) ; /* propagates border_width, if size doesn't change */
2011-11-02 12:01:28 +00:00
updatewindowtype ( c ) ;
2007-09-16 11:53:14 +02:00
updatesizehints ( c ) ;
2011-04-12 20:19:32 +00:00
updatewmhints ( c ) ;
2008-02-23 23:11:27 +00:00
XSelectInput ( dpy , w , EnterWindowMask | FocusChangeMask | PropertyChangeMask | StructureNotifyMask ) ;
2015-11-08 22:48:43 +01:00
grabbuttons ( c , 0 ) ;
2015-11-08 23:11:48 +01:00
if ( ! c - > isfloating )
2010-05-30 10:02:56 +01:00
c - > isfloating = c - > oldstate = trans ! = None | | c - > isfixed ;
2015-11-08 23:11:48 +01:00
if ( c - > isfloating )
2008-06-01 10:54:02 +01:00
XRaiseWindow ( dpy , c - > win ) ;
2007-09-16 11:53:14 +02:00
attach ( c ) ;
attachstack ( c ) ;
2012-03-25 17:49:35 +02:00
XChangeProperty ( dpy , root , netatom [ NetClientList ] , XA_WINDOW , 32 , PropModeAppend ,
2017-05-08 21:08:27 +02:00
( unsigned char * ) & ( c - > win ) , 1 ) ;
2008-06-22 09:29:06 +01:00
XMoveResizeWindow ( dpy , c - > win , c - > x + 2 * sw , c - > y , c - > w , c - > h ) ; /* some windows require this */
2007-09-16 11:53:14 +02:00
setclientstate ( c , NormalState ) ;
2011-07-29 20:01:22 +02:00
if ( c - > mon = = selmon )
2015-11-08 22:48:43 +01:00
unfocus ( selmon - > sel , 0 ) ;
2011-07-29 20:01:22 +02:00
c - > mon - > sel = c ;
2009-09-27 10:31:14 +01:00
arrange ( c - > mon ) ;
2011-07-29 20:01:22 +02:00
XMapWindow ( dpy , c - > win ) ;
focus ( NULL ) ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
mappingnotify ( XEvent * e )
{
2007-09-16 11:53:14 +02:00
XMappingEvent * ev = & e - > xmapping ;
2007-09-15 22:25:27 +02:00
2007-09-16 11:53:14 +02:00
XRefreshKeyboardMapping ( ev ) ;
2015-11-08 23:11:48 +01:00
if ( ev - > request = = MappingKeyboard )
2007-11-10 19:16:11 +01:00
grabkeys ( ) ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
maprequest ( XEvent * e )
{
2007-09-16 11:53:14 +02:00
static XWindowAttributes wa ;
XMapRequestEvent * ev = & e - > xmaprequest ;
2015-11-08 23:11:48 +01:00
if ( ! XGetWindowAttributes ( dpy , ev - > window , & wa ) )
2007-09-15 22:25:27 +02:00
return ;
2015-11-08 23:11:48 +01:00
if ( wa . override_redirect )
2007-09-16 11:53:14 +02:00
return ;
2015-11-08 23:11:48 +01:00
if ( ! wintoclient ( ev - > window ) )
2007-09-16 11:53:14 +02:00
manage ( ev - > window , & wa ) ;
2007-09-15 22:25:27 +02:00
}
2008-06-19 11:38:53 +01:00
void
2015-11-08 23:11:48 +01:00
monocle ( Monitor * m )
{
2009-09-16 15:59:54 +01:00
unsigned int n = 0 ;
2008-06-19 11:38:53 +01:00
Client * c ;
2015-11-08 23:11:48 +01:00
for ( c = m - > clients ; c ; c = c - > next )
if ( ISVISIBLE ( c ) )
2009-09-16 15:59:54 +01:00
n + + ;
2015-11-08 23:11:48 +01:00
if ( n > 0 ) /* override layout symbol */
2009-09-22 09:53:11 +01:00
snprintf ( m - > ltsymbol , sizeof m - > ltsymbol , " [%d] " , n ) ;
2015-11-08 23:11:48 +01:00
for ( c = nexttiled ( m - > clients ) ; c ; c = nexttiled ( c - > next ) )
2021-04-09 11:20:47 -04:00
resize ( c , m - > wx , m - > wy , m - > ww , m - > wh , 0 , 0 ) ;
2008-06-19 11:38:53 +01:00
}
2011-11-15 20:16:58 +01:00
void
2015-11-08 23:11:48 +01:00
motionnotify ( XEvent * e )
{
2011-11-15 20:16:58 +01:00
static Monitor * mon = NULL ;
Monitor * m ;
XMotionEvent * ev = & e - > xmotion ;
2015-11-08 23:11:48 +01:00
if ( ev - > window ! = root )
2011-11-15 20:16:58 +01:00
return ;
2015-11-08 23:11:48 +01:00
if ( ( m = recttomon ( ev - > x_root , ev - > y_root , 1 , 1 ) ) ! = mon & & mon ) {
2015-11-08 22:48:43 +01:00
unfocus ( selmon - > sel , 1 ) ;
2011-11-15 20:16:58 +01:00
selmon = m ;
focus ( NULL ) ;
}
mon = m ;
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
movemouse ( const Arg * arg )
{
2009-06-27 18:39:03 +01:00
int x , y , ocx , ocy , nx , ny ;
2008-06-11 20:41:28 +01:00
Client * c ;
2009-06-27 18:39:03 +01:00
Monitor * m ;
2007-09-15 22:25:27 +02:00
XEvent ev ;
2014-08-11 07:24:29 +02:00
Time lasttime = 0 ;
2007-09-15 22:25:27 +02:00
2015-11-08 23:11:48 +01:00
if ( ! ( c = selmon - > sel ) )
2008-06-11 20:41:28 +01:00
return ;
2015-11-08 23:11:48 +01:00
if ( c - > isfullscreen ) /* no support moving fullscreen windows by mouse */
2012-06-23 09:06:00 +02:00
return ;
2009-06-20 15:10:04 +01:00
restack ( selmon ) ;
2008-08-18 18:23:39 +01:00
ocx = c - > x ;
ocy = c - > y ;
2015-11-08 23:11:48 +01:00
if ( XGrabPointer ( dpy , root , False , MOUSEMASK , GrabModeAsync , GrabModeAsync ,
2017-05-08 21:08:27 +02:00
None , cursor [ CurMove ] - > cursor , CurrentTime ) ! = GrabSuccess )
2007-09-15 22:25:27 +02:00
return ;
2015-11-08 23:11:48 +01:00
if ( ! getrootptr ( & x , & y ) )
2009-06-27 18:39:03 +01:00
return ;
2008-08-18 18:23:39 +01:00
do {
2008-02-23 23:11:27 +00:00
XMaskEvent ( dpy , MOUSEMASK | ExposureMask | SubstructureRedirectMask , & ev ) ;
2011-05-12 14:16:33 +00:00
switch ( ev . type ) {
2007-09-16 11:53:14 +02:00
case ConfigureRequest :
case Expose :
case MapRequest :
handler [ ev . type ] ( & ev ) ;
break ;
case MotionNotify :
2014-08-11 07:24:29 +02:00
if ( ( ev . xmotion . time - lasttime ) < = ( 1000 / 60 ) )
continue ;
lasttime = ev . xmotion . time ;
2008-07-16 18:33:51 +01:00
nx = ocx + ( ev . xmotion . x - x ) ;
ny = ocy + ( ev . xmotion . y - y ) ;
2017-01-07 17:21:30 +01:00
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 ) ;
2015-11-08 23:11:48 +01:00
if ( ! selmon - > lt [ selmon - > sellt ] - > arrange | | c - > isfloating )
2021-04-09 11:20:47 -04:00
resize ( c , nx , ny , c - > w , c - > h , c - > bw , 1 ) ;
2007-09-16 11:53:14 +02:00
break ;
}
2015-11-08 23:11:48 +01:00
} while ( ev . type ! = ButtonRelease ) ;
2008-08-18 18:23:39 +01:00
XUngrabPointer ( dpy , CurrentTime ) ;
2015-11-08 23:11:48 +01:00
if ( ( m = recttomon ( c - > x , c - > y , c - > w , c - > h ) ) ! = selmon ) {
2009-06-27 18:39:03 +01:00
sendmon ( c , m ) ;
2009-06-30 15:51:09 +01:00
selmon = m ;
focus ( NULL ) ;
}
2007-09-16 11:53:14 +02:00
}
2020-12-03 09:53:29 -05:00
void
moveresize ( const Arg * arg ) {
/* only floating windows can be moved */
Client * c ;
c = selmon - > sel ;
int x , y , w , h , nx , ny , nw , nh , ox , oy , ow , oh ;
char xAbs , yAbs , wAbs , hAbs ;
int msx , msy , dx , dy , nmx , nmy ;
unsigned int dui ;
Window dummy ;
if ( ! c | | ! arg )
return ;
if ( selmon - > lt [ selmon - > sellt ] - > arrange & & ! c - > isfloating )
return ;
if ( sscanf ( ( char * ) arg - > v , " %d%c %d%c %d%c %d%c " , & x , & xAbs , & y , & yAbs , & w , & wAbs , & h , & hAbs ) ! = 8 )
return ;
/* compute new window position; prevent window from be positioned outside the current monitor */
nw = c - > w + w ;
if ( wAbs = = ' W ' )
nw = w < selmon - > mw - 2 * c - > bw ? w : selmon - > mw - 2 * c - > bw ;
nh = c - > h + h ;
if ( hAbs = = ' H ' )
nh = h < selmon - > mh - 2 * c - > bw ? h : selmon - > mh - 2 * c - > bw ;
nx = c - > x + x ;
if ( xAbs = = ' X ' ) {
if ( x < selmon - > mx )
nx = selmon - > mx ;
else if ( x > selmon - > mx + selmon - > mw )
nx = selmon - > mx + selmon - > mw - nw - 2 * c - > bw ;
else
nx = x ;
}
ny = c - > y + y ;
if ( yAbs = = ' Y ' ) {
if ( y < selmon - > my )
ny = selmon - > my ;
else if ( y > selmon - > my + selmon - > mh )
ny = selmon - > my + selmon - > mh - nh - 2 * c - > bw ;
else
ny = y ;
}
ox = c - > x ;
oy = c - > y ;
ow = c - > w ;
oh = c - > h ;
XRaiseWindow ( dpy , c - > win ) ;
Bool xqp = XQueryPointer ( dpy , root , & dummy , & dummy , & msx , & msy , & dx , & dy , & dui ) ;
2021-04-09 11:20:47 -04:00
resize ( c , nx , ny , nw , nh , borderpx , True ) ;
2020-12-03 09:53:29 -05:00
/* move cursor along with the window to avoid problems caused by the sloppy focus */
if ( xqp & & ox < = msx & & ( ox + ow ) > = msx & & oy < = msy & & ( oy + oh ) > = msy )
{
nmx = c - > x - ox + c - > w - ow ;
nmy = c - > y - oy + c - > h - oh ;
XWarpPointer ( dpy , None , None , 0 , 0 , 0 , 0 , nmx , nmy ) ;
}
}
2007-09-17 16:42:37 +02:00
Client *
2015-11-08 23:11:48 +01:00
nexttiled ( Client * c )
{
for ( ; c & & ( c - > isfloating | | ! ISVISIBLE ( c ) ) ; c = c - > next ) ;
2007-09-16 11:53:14 +02:00
return c ;
2007-09-15 22:25:27 +02:00
}
2011-04-15 08:12:20 +00:00
void
2015-11-08 23:11:48 +01:00
pop ( Client * c )
{
2011-04-15 08:12:20 +00:00
detach ( c ) ;
attach ( c ) ;
focus ( c ) ;
arrange ( c - > mon ) ;
2009-06-30 19:39:59 +01:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
propertynotify ( XEvent * e )
{
2007-09-16 11:53:14 +02:00
Client * c ;
Window trans ;
XPropertyEvent * ev = & e - > xproperty ;
2007-09-15 22:25:27 +02:00
2015-11-08 23:11:48 +01:00
if ( ( ev - > window = = root ) & & ( ev - > atom = = XA_WM_NAME ) )
2008-12-12 19:49:06 +00:00
updatestatus ( ) ;
2015-11-08 23:11:48 +01:00
else if ( ev - > state = = PropertyDelete )
2007-09-16 11:53:14 +02:00
return ; /* ignore */
2015-11-08 23:11:48 +01:00
else if ( ( c = wintoclient ( ev - > window ) ) ) {
2011-05-12 14:16:33 +00:00
switch ( ev - > atom ) {
2008-02-21 10:31:06 +00:00
default : break ;
case XA_WM_TRANSIENT_FOR :
2015-11-08 23:11:48 +01:00
if ( ! c - > isfloating & & ( XGetTransientForHint ( dpy , c - > win , & trans ) ) & &
2017-05-08 21:08:27 +02:00
( c - > isfloating = ( wintoclient ( trans ) ) ! = NULL ) )
2009-09-27 10:31:14 +01:00
arrange ( c - > mon ) ;
2008-02-21 10:31:06 +00:00
break ;
case XA_WM_NORMAL_HINTS :
updatesizehints ( c ) ;
break ;
case XA_WM_HINTS :
updatewmhints ( c ) ;
2009-06-20 15:10:04 +01:00
drawbars ( ) ;
2008-02-21 10:31:06 +00:00
break ;
2007-09-16 11:53:14 +02:00
}
2015-11-08 23:11:48 +01:00
if ( ev - > atom = = XA_WM_NAME | | ev - > atom = = netatom [ NetWMName ] ) {
2007-09-16 11:53:14 +02:00
updatetitle ( c ) ;
2015-11-08 23:11:48 +01:00
if ( c = = c - > mon - > sel )
2009-08-18 15:59:38 +01:00
drawbar ( c - > mon ) ;
2007-09-16 11:53:14 +02:00
}
2015-11-08 23:11:48 +01:00
if ( ev - > atom = = netatom [ NetWMWindowType ] )
2011-11-02 12:01:28 +00:00
updatewindowtype ( c ) ;
2007-09-16 11:53:14 +02:00
}
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
quit ( const Arg * arg )
{
2021-04-09 01:24:48 -04:00
if ( arg - > i ) restart = 1 ;
2015-11-08 22:48:43 +01:00
running = 0 ;
2007-09-15 22:25:27 +02:00
}
2011-11-06 20:31:29 +01:00
Monitor *
2015-11-08 23:11:48 +01:00
recttomon ( int x , int y , int w , int h )
{
2011-11-06 20:31:29 +01:00
Monitor * m , * r = selmon ;
int a , area = 0 ;
2015-11-08 23:11:48 +01:00
for ( m = mons ; m ; m = m - > next )
if ( ( a = INTERSECT ( x , y , w , h , m ) ) > area ) {
2011-11-06 20:31:29 +01:00
area = a ;
r = m ;
}
return r ;
}
2007-09-17 16:42:37 +02:00
void
2021-04-09 11:20:47 -04:00
resize ( Client * c , int x , int y , int w , int h , int bw , int interact )
2015-11-08 23:11:48 +01:00
{
2021-04-09 11:20:47 -04:00
if ( applysizehints ( c , & x , & y , & w , & h , & bw , interact ) )
resizeclient ( c , x , y , w , h , bw ) ;
2010-05-30 10:02:56 +01:00
}
void
2021-04-09 11:20:47 -04:00
resizeclient ( Client * c , int x , int y , int w , int h , int bw )
2015-11-08 23:11:48 +01:00
{
2007-10-03 16:25:25 +02:00
XWindowChanges wc ;
2008-02-20 08:13:41 +00:00
2010-05-30 10:02:56 +01:00
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 ;
2021-04-09 11:20:47 -04:00
c - > oldbw = c - > bw ; c - > bw = wc . border_width = bw ;
2010-05-30 10:02:56 +01:00
XConfigureWindow ( dpy , c - > win , CWX | CWY | CWWidth | CWHeight | CWBorderWidth , & wc ) ;
configure ( c ) ;
XSync ( dpy , False ) ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
resizemouse ( const Arg * arg )
{
2014-08-11 07:24:29 +02:00
int ocx , ocy , nw , nh ;
2008-06-11 20:41:28 +01:00
Client * c ;
2009-06-27 18:39:03 +01:00
Monitor * m ;
2007-09-16 11:53:14 +02:00
XEvent ev ;
2014-08-11 07:24:29 +02:00
Time lasttime = 0 ;
2007-09-16 11:53:14 +02:00
2015-11-08 23:11:48 +01:00
if ( ! ( c = selmon - > sel ) )
2008-06-11 20:41:28 +01:00
return ;
2015-11-08 23:11:48 +01:00
if ( c - > isfullscreen ) /* no support resizing fullscreen windows by mouse */
2012-06-23 09:06:00 +02:00
return ;
2009-06-20 15:10:04 +01:00
restack ( selmon ) ;
2007-09-16 11:53:14 +02:00
ocx = c - > x ;
ocy = c - > y ;
2015-11-08 23:11:48 +01:00
if ( XGrabPointer ( dpy , root , False , MOUSEMASK , GrabModeAsync , GrabModeAsync ,
2017-05-08 21:08:27 +02:00
None , cursor [ CurResize ] - > cursor , CurrentTime ) ! = GrabSuccess )
2007-09-16 11:53:14 +02:00
return ;
2008-03-17 16:29:50 +00:00
XWarpPointer ( dpy , None , c - > win , 0 , 0 , 0 , 0 , c - > w + c - > bw - 1 , c - > h + c - > bw - 1 ) ;
2008-08-18 19:19:15 +01:00
do {
2008-08-18 19:28:57 +01:00
XMaskEvent ( dpy , MOUSEMASK | ExposureMask | SubstructureRedirectMask , & ev ) ;
2007-09-16 11:53:14 +02:00
switch ( ev . type ) {
case ConfigureRequest :
case Expose :
case MapRequest :
handler [ ev . type ] ( & ev ) ;
break ;
case MotionNotify :
2014-08-11 07:24:29 +02:00
if ( ( ev . xmotion . time - lasttime ) < = ( 1000 / 60 ) )
continue ;
lasttime = ev . xmotion . time ;
2008-12-20 12:02:14 +00:00
nw = MAX ( ev . xmotion . x - ocx - 2 * c - > bw + 1 , 1 ) ;
nh = MAX ( ev . xmotion . y - ocy - 2 * c - > bw + 1 , 1 ) ;
2015-11-08 23:11:48 +01:00
if ( c - > mon - > wx + nw > = selmon - > wx & & c - > mon - > wx + nw < = selmon - > wx + selmon - > ww
2011-03-23 08:58:57 +00:00
& & c - > mon - > wy + nh > = selmon - > wy & & c - > mon - > wy + nh < = selmon - > wy + selmon - > wh )
2009-07-14 16:26:04 +01:00
{
2015-11-08 23:11:48 +01:00
if ( ! c - > isfloating & & selmon - > lt [ selmon - > sellt ] - > arrange
2009-07-14 16:26:04 +01:00
& & ( abs ( nw - c - > w ) > snap | | abs ( nh - c - > h ) > snap ) )
2008-05-19 13:41:58 +01:00
togglefloating ( NULL ) ;
2008-04-27 18:22:52 +01:00
}
2015-11-08 23:11:48 +01:00
if ( ! selmon - > lt [ selmon - > sellt ] - > arrange | | c - > isfloating )
2021-04-09 11:20:47 -04:00
resize ( c , c - > x , c - > y , nw , nh , c - > bw , 1 ) ;
2007-09-16 11:53:14 +02:00
break ;
}
2015-11-08 23:11:48 +01:00
} while ( ev . type ! = ButtonRelease ) ;
2008-08-18 19:19:15 +01:00
XWarpPointer ( dpy , None , c - > win , 0 , 0 , 0 , 0 , c - > w + c - > bw - 1 , c - > h + c - > bw - 1 ) ;
XUngrabPointer ( dpy , CurrentTime ) ;
2015-11-08 23:11:48 +01:00
while ( XCheckMaskEvent ( dpy , EnterWindowMask , & ev ) ) ;
if ( ( m = recttomon ( c - > x , c - > y , c - > w , c - > h ) ) ! = selmon ) {
2009-06-27 18:39:03 +01:00
sendmon ( c , m ) ;
2009-06-30 15:51:09 +01:00
selmon = m ;
focus ( NULL ) ;
}
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
restack ( Monitor * m )
{
2007-09-16 11:53:14 +02:00
Client * c ;
XEvent ev ;
XWindowChanges wc ;
2007-09-15 22:25:27 +02:00
2009-09-27 10:31:14 +01:00
drawbar ( m ) ;
2015-11-08 23:11:48 +01:00
if ( ! m - > sel )
2007-09-16 11:53:14 +02:00
return ;
2015-11-08 23:11:48 +01:00
if ( m - > sel - > isfloating | | ! m - > lt [ m - > sellt ] - > arrange )
2012-02-08 19:54:05 +01:00
XRaiseWindow ( dpy , m - > sel - > win ) ;
2015-11-08 23:11:48 +01:00
if ( m - > lt [ m - > sellt ] - > arrange ) {
2007-09-16 11:53:14 +02:00
wc . stack_mode = Below ;
2009-06-20 15:10:04 +01:00
wc . sibling = m - > barwin ;
2015-11-08 23:11:48 +01:00
for ( c = m - > stack ; c ; c = c - > snext )
if ( ! c - > isfloating & & ISVISIBLE ( c ) ) {
2008-04-27 18:22:52 +01:00
XConfigureWindow ( dpy , c - > win , CWSibling | CWStackMode , & wc ) ;
wc . sibling = c - > win ;
}
2007-09-16 11:53:14 +02:00
}
XSync ( dpy , False ) ;
2015-11-08 23:11:48 +01:00
while ( XCheckMaskEvent ( dpy , EnterWindowMask , & ev ) ) ;
2020-12-01 09:34:31 -05:00
if ( m = = selmon & & ( m - > tagset [ m - > seltags ] & m - > sel - > tags ) & & selmon - > lt [ selmon - > sellt ] ! = & layouts [ 2 ] )
warp ( m - > sel ) ;
2007-09-15 22:25:27 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
run ( void )
{
2007-09-16 12:34:08 +02:00
XEvent ev ;
2008-12-12 19:49:06 +00:00
/* main event loop */
2007-09-16 12:34:08 +02:00
XSync ( dpy , False ) ;
2015-11-08 23:11:48 +01:00
while ( running & & ! XNextEvent ( dpy , & ev ) )
if ( handler [ ev . type ] )
2009-07-14 16:01:14 +01:00
handler [ ev . type ] ( & ev ) ; /* call handler */
2007-09-16 12:34:08 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
scan ( void )
{
2008-07-16 18:17:42 +01:00
unsigned int i , num ;
2008-08-18 10:14:51 +01:00
Window d1 , d2 , * wins = NULL ;
2007-09-15 22:25:27 +02:00
XWindowAttributes wa ;
2015-11-08 23:11:48 +01:00
if ( XQueryTree ( dpy , root , & d1 , & d2 , & wins , & num ) ) {
for ( i = 0 ; i < num ; i + + ) {
if ( ! XGetWindowAttributes ( dpy , wins [ i ] , & wa )
2008-05-13 14:33:02 +01:00
| | wa . override_redirect | | XGetTransientForHint ( dpy , wins [ i ] , & d1 ) )
2008-02-18 16:47:16 +00:00
continue ;
2015-11-08 23:11:48 +01:00
if ( wa . map_state = = IsViewable | | getstate ( wins [ i ] ) = = IconicState )
2008-02-18 16:47:16 +00:00
manage ( wins [ i ] , & wa ) ;
}
2015-11-08 23:11:48 +01:00
for ( i = 0 ; i < num ; i + + ) { /* now the transients */
if ( ! XGetWindowAttributes ( dpy , wins [ i ] , & wa ) )
2008-02-18 16:47:16 +00:00
continue ;
2015-11-08 23:11:48 +01:00
if ( XGetTransientForHint ( dpy , wins [ i ] , & d1 )
2008-05-13 14:33:02 +01:00
& & ( wa . map_state = = IsViewable | | getstate ( wins [ i ] ) = = IconicState ) )
2008-02-18 16:47:16 +00:00
manage ( wins [ i ] , & wa ) ;
2007-09-15 22:25:27 +02:00
}
2015-11-08 23:11:48 +01:00
if ( wins )
2008-08-18 10:14:51 +01:00
XFree ( wins ) ;
2007-09-15 22:25:27 +02:00
}
}
2009-06-27 18:39:03 +01:00
void
2015-11-08 23:11:48 +01:00
sendmon ( Client * c , Monitor * m )
{
if ( c - > mon = = m )
2009-06-27 18:39:03 +01:00
return ;
2015-11-08 22:48:43 +01:00
unfocus ( c , 1 ) ;
2009-06-27 18:39:03 +01:00
detach ( c ) ;
detachstack ( c ) ;
c - > mon = m ;
c - > tags = m - > tagset [ m - > seltags ] ; /* assign tags of target monitor */
attach ( c ) ;
attachstack ( c ) ;
focus ( NULL ) ;
2009-09-27 10:31:14 +01:00
arrange ( NULL ) ;
2009-06-27 18:39:03 +01:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
setclientstate ( Client * c , long state )
{
2009-07-02 20:56:23 +01:00
long data [ ] = { state , None } ;
2007-09-16 11:53:14 +02:00
XChangeProperty ( dpy , c - > win , wmatom [ WMState ] , wmatom [ WMState ] , 32 ,
2017-05-08 21:08:27 +02:00
PropModeReplace , ( unsigned char * ) data , 2 ) ;
2007-09-16 11:53:14 +02:00
}
2015-11-08 22:48:43 +01:00
int
2015-11-08 23:11:48 +01:00
sendevent ( Client * c , Atom proto )
{
2011-04-12 20:19:32 +00:00
int n ;
Atom * protocols ;
2015-11-08 22:48:43 +01:00
int exists = 0 ;
2011-04-12 20:19:32 +00:00
XEvent ev ;
2015-11-08 23:11:48 +01:00
if ( XGetWMProtocols ( dpy , c - > win , & protocols , & n ) ) {
while ( ! exists & & n - - )
2011-04-12 20:19:32 +00:00
exists = protocols [ n ] = = proto ;
XFree ( protocols ) ;
}
2015-11-08 23:11:48 +01:00
if ( exists ) {
2011-04-12 20:19:32 +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 ) ;
}
return exists ;
}
void
2015-11-08 23:11:48 +01:00
setfocus ( Client * c )
{
if ( ! c - > neverfocus ) {
2011-04-12 20:19:32 +00:00
XSetInputFocus ( dpy , c - > win , RevertToPointerRoot , CurrentTime ) ;
2012-03-25 17:46:03 +02:00
XChangeProperty ( dpy , root , netatom [ NetActiveWindow ] ,
2017-05-08 21:08:27 +02:00
XA_WINDOW , 32 , PropModeReplace ,
( unsigned char * ) & ( c - > win ) , 1 ) ;
2012-03-25 17:46:03 +02:00
}
2011-04-12 20:19:32 +00:00
sendevent ( c , wmatom [ WMTakeFocus ] ) ;
}
2011-11-06 20:30:06 +01:00
void
2015-11-08 23:11:48 +01:00
setfullscreen ( Client * c , int fullscreen )
{
if ( fullscreen & & ! c - > isfullscreen ) {
2011-11-06 20:30:06 +01:00
XChangeProperty ( dpy , c - > win , netatom [ NetWMState ] , XA_ATOM , 32 ,
2017-05-08 21:08:27 +02:00
PropModeReplace , ( unsigned char * ) & netatom [ NetWMFullscreen ] , 1 ) ;
2015-11-08 22:48:43 +01:00
c - > isfullscreen = 1 ;
2011-11-06 20:30:06 +01:00
c - > oldstate = c - > isfloating ;
2015-11-08 22:48:43 +01:00
c - > isfloating = 1 ;
2021-04-09 11:20:47 -04:00
resizeclient ( c , c - > mon - > mx , c - > mon - > my , c - > mon - > mw , c - > mon - > mh , 0 ) ;
2011-11-06 20:30:06 +01:00
XRaiseWindow ( dpy , c - > win ) ;
2015-11-08 23:11:48 +01:00
} else if ( ! fullscreen & & c - > isfullscreen ) {
2011-11-06 20:30:06 +01:00
XChangeProperty ( dpy , c - > win , netatom [ NetWMState ] , XA_ATOM , 32 ,
2017-05-08 21:08:27 +02:00
PropModeReplace , ( unsigned char * ) 0 , 0 ) ;
2015-11-08 22:48:43 +01:00
c - > isfullscreen = 0 ;
2011-11-06 20:30:06 +01:00
c - > isfloating = c - > oldstate ;
c - > x = c - > oldx ;
c - > y = c - > oldy ;
c - > w = c - > oldw ;
c - > h = c - > oldh ;
2021-04-09 11:20:47 -04:00
c - > bw = c - > oldbw ;
resizeclient ( c , c - > x , c - > y , c - > w , c - > h , c - > bw ) ;
2011-11-06 20:30:06 +01:00
arrange ( c - > mon ) ;
}
}
2008-06-19 11:38:53 +01:00
void
2015-11-08 23:11:48 +01:00
setlayout ( const Arg * arg )
{
2021-04-08 23:16:19 -04:00
unsigned int i ;
2015-11-08 23:11:48 +01:00
if ( ! arg | | ! arg - > v | | arg - > v ! = selmon - > lt [ selmon - > sellt ] )
2009-06-19 20:15:15 +01:00
selmon - > sellt ^ = 1 ;
2015-11-08 23:11:48 +01:00
if ( arg & & arg - > v )
2009-07-06 20:12:47 +01:00
selmon - > lt [ selmon - > sellt ] = ( Layout * ) arg - > v ;
2009-09-27 20:20:10 +01:00
strncpy ( selmon - > ltsymbol , selmon - > lt [ selmon - > sellt ] - > symbol , sizeof selmon - > ltsymbol ) ;
2021-04-08 23:16:19 -04:00
for ( i = 0 ; i < LENGTH ( tags ) ; + + i )
if ( selmon - > tagset [ selmon - > seltags ] & 1 < < i )
{
selmon - > pertag - > ltidxs [ i + 1 ] [ selmon - > sellt ] = selmon - > lt [ selmon - > sellt ] ;
selmon - > pertag - > sellts [ i + 1 ] = selmon - > sellt ;
}
if ( selmon - > pertag - > curtag = = 0 )
{
selmon - > pertag - > ltidxs [ 0 ] [ selmon - > sellt ] = selmon - > lt [ selmon - > sellt ] ;
selmon - > pertag - > sellts [ 0 ] = selmon - > sellt ;
}
2015-11-08 23:11:48 +01:00
if ( selmon - > sel )
2009-09-27 10:31:14 +01:00
arrange ( selmon ) ;
2008-06-19 11:38:53 +01:00
else
2009-09-27 10:31:14 +01:00
drawbar ( selmon ) ;
2008-06-19 11:38:53 +01:00
}
2017-01-07 17:21:28 +01:00
/* arg > 1.0 will set mfact absolutely */
2008-05-19 20:07:12 +01:00
void
2015-11-08 23:11:48 +01:00
setmfact ( const Arg * arg )
{
2008-06-11 09:12:06 +01:00
float f ;
2021-04-08 23:16:19 -04:00
unsigned int i ;
2008-05-19 20:07:12 +01:00
2015-11-08 23:11:48 +01:00
if ( ! arg | | ! selmon - > lt [ selmon - > sellt ] - > arrange )
2008-05-19 20:07:12 +01:00
return ;
2009-06-20 16:18:02 +01:00
f = arg - > f < 1.0 ? arg - > f + selmon - > mfact : arg - > f - 1.0 ;
2021-04-08 23:16:19 -04:00
if ( arg - > f = = 0.0 )
f = mfact ;
2020-04-20 16:41:52 +01:00
if ( f < 0.05 | | f > 0.95 )
2008-05-22 11:04:19 +01:00
return ;
2009-06-20 16:18:02 +01:00
selmon - > mfact = f ;
2021-04-08 23:16:19 -04:00
for ( i = 0 ; i < LENGTH ( tags ) ; + + i )
if ( selmon - > tagset [ selmon - > seltags ] & 1 < < i )
selmon - > pertag - > mfacts [ i + 1 ] = f ;
if ( selmon - > pertag - > curtag = = 0 )
{
selmon - > pertag - > mfacts [ 0 ] = f ;
}
2009-09-27 10:31:14 +01:00
arrange ( selmon ) ;
2008-05-19 20:07:12 +01:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
setup ( void )
{
2016-12-05 10:01:33 +01:00
int i ;
2007-09-15 22:25:27 +02:00
XSetWindowAttributes wa ;
2016-12-05 10:09:49 +01:00
Atom utf8string ;
2008-03-03 21:40:37 +00:00
2009-08-13 10:45:59 +01:00
/* clean up any zombies immediately */
sigchld ( 0 ) ;
2021-04-09 01:24:48 -04:00
signal ( SIGHUP , sighup ) ;
signal ( SIGTERM , sigterm ) ;
2008-03-03 21:40:37 +00:00
/* init screen */
screen = DefaultScreen ( dpy ) ;
2008-03-14 17:17:08 +00:00
sw = DisplayWidth ( dpy , screen ) ;
sh = DisplayHeight ( dpy , screen ) ;
2015-03-05 20:26:11 -08:00
root = RootWindow ( dpy , screen ) ;
2013-06-16 15:20:29 +02:00
drw = drw_create ( dpy , screen , root , sw , sh ) ;
2016-05-22 22:33:56 +02:00
if ( ! drw_fontset_create ( drw , fonts , LENGTH ( fonts ) ) )
2016-08-12 14:35:25 +02:00
die ( " no fonts could be loaded. " ) ;
2016-05-22 22:33:56 +02:00
lrpad = drw - > fonts - > h ;
bh = drw - > fonts - > h + 2 ;
2008-05-11 20:20:53 +01:00
updategeom ( ) ;
2007-09-15 22:25:27 +02:00
/* init atoms */
2016-12-05 10:09:49 +01:00
utf8string = XInternAtom ( dpy , " UTF8_STRING " , False ) ;
2007-09-15 22:25:27 +02:00
wmatom [ WMProtocols ] = XInternAtom ( dpy , " WM_PROTOCOLS " , False ) ;
wmatom [ WMDelete ] = XInternAtom ( dpy , " WM_DELETE_WINDOW " , False ) ;
wmatom [ WMState ] = XInternAtom ( dpy , " WM_STATE " , False ) ;
2011-04-12 20:19:32 +00:00
wmatom [ WMTakeFocus ] = XInternAtom ( dpy , " WM_TAKE_FOCUS " , False ) ;
2011-05-12 14:16:33 +00:00
netatom [ NetActiveWindow ] = XInternAtom ( dpy , " _NET_ACTIVE_WINDOW " , False ) ;
2007-09-15 22:25:27 +02:00
netatom [ NetSupported ] = XInternAtom ( dpy , " _NET_SUPPORTED " , False ) ;
netatom [ NetWMName ] = XInternAtom ( dpy , " _NET_WM_NAME " , False ) ;
2010-05-27 08:19:08 +01:00
netatom [ NetWMState ] = XInternAtom ( dpy , " _NET_WM_STATE " , False ) ;
2016-12-05 10:09:49 +01:00
netatom [ NetWMCheck ] = XInternAtom ( dpy , " _NET_SUPPORTING_WM_CHECK " , False ) ;
2010-05-30 10:02:56 +01:00
netatom [ NetWMFullscreen ] = XInternAtom ( dpy , " _NET_WM_STATE_FULLSCREEN " , False ) ;
2011-11-02 12:01:28 +00:00
netatom [ NetWMWindowType ] = XInternAtom ( dpy , " _NET_WM_WINDOW_TYPE " , False ) ;
netatom [ NetWMWindowTypeDialog ] = XInternAtom ( dpy , " _NET_WM_WINDOW_TYPE_DIALOG " , False ) ;
2012-03-25 17:49:35 +02:00
netatom [ NetClientList ] = XInternAtom ( dpy , " _NET_CLIENT_LIST " , False ) ;
2007-09-15 22:25:27 +02:00
/* init cursors */
2013-06-16 15:20:29 +02:00
cursor [ CurNormal ] = drw_cur_create ( drw , XC_left_ptr ) ;
cursor [ CurResize ] = drw_cur_create ( drw , XC_sizing ) ;
cursor [ CurMove ] = drw_cur_create ( drw , XC_fleur ) ;
2008-02-18 17:08:22 +00:00
/* init appearance */
2017-11-03 21:20:48 +01:00
scheme = ecalloc ( LENGTH ( colors ) , sizeof ( Clr * ) ) ;
2016-12-05 10:01:33 +01:00
for ( i = 0 ; i < LENGTH ( colors ) ; i + + )
scheme [ i ] = drw_scm_create ( drw , colors [ i ] , 3 ) ;
2009-06-20 15:10:04 +01:00
/* init bars */
2009-06-22 14:58:08 +01:00
updatebars ( ) ;
2008-12-12 19:49:06 +00:00
updatestatus ( ) ;
2016-12-05 10:09:49 +01:00
/* supporting window for NetWMCheck */
wmcheckwin = XCreateSimpleWindow ( dpy , root , 0 , 0 , 1 , 1 , 0 , 0 , 0 ) ;
XChangeProperty ( dpy , wmcheckwin , netatom [ NetWMCheck ] , XA_WINDOW , 32 ,
2017-05-08 21:08:27 +02:00
PropModeReplace , ( unsigned char * ) & wmcheckwin , 1 ) ;
2016-12-05 10:09:49 +01:00
XChangeProperty ( dpy , wmcheckwin , netatom [ NetWMName ] , utf8string , 8 ,
2017-12-27 13:36:53 +01:00
PropModeReplace , ( unsigned char * ) " dwm " , 3 ) ;
2016-12-05 10:09:49 +01:00
XChangeProperty ( dpy , root , netatom [ NetWMCheck ] , XA_WINDOW , 32 ,
2017-05-08 21:08:27 +02:00
PropModeReplace , ( unsigned char * ) & wmcheckwin , 1 ) ;
2008-03-03 21:40:37 +00:00
/* EWMH support per view */
XChangeProperty ( dpy , root , netatom [ NetSupported ] , XA_ATOM , 32 ,
2017-05-08 21:08:27 +02:00
PropModeReplace , ( unsigned char * ) netatom , NetLast ) ;
2012-03-25 17:49:35 +02:00
XDeleteProperty ( dpy , root , netatom [ NetClientList ] ) ;
2017-01-07 17:21:28 +01:00
/* select events */
2013-06-16 15:20:29 +02:00
wa . cursor = cursor [ CurNormal ] - > cursor ;
2017-01-07 17:21:28 +01:00
wa . event_mask = SubstructureRedirectMask | SubstructureNotifyMask
2017-05-08 21:08:27 +02:00
| ButtonPressMask | PointerMotionMask | EnterWindowMask
| LeaveWindowMask | StructureNotifyMask | PropertyChangeMask ;
2008-03-03 21:40:37 +00:00
XChangeWindowAttributes ( dpy , root , CWEventMask | CWCursor , & wa ) ;
XSelectInput ( dpy , root , wa . event_mask ) ;
2007-12-22 14:30:47 +00:00
grabkeys ( ) ;
2013-08-27 20:39:21 +02:00
focus ( NULL ) ;
2007-09-15 22:25:27 +02:00
}
2016-12-05 10:16:46 +01:00
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 ) ;
}
2008-09-06 09:21:32 +01:00
void
2015-11-08 23:11:48 +01:00
showhide ( Client * c )
{
if ( ! c )
2008-09-06 09:34:49 +01:00
return ;
2015-11-08 23:11:48 +01:00
if ( ISVISIBLE ( c ) ) {
/* show clients top down */
2008-09-06 09:21:32 +01:00
XMoveWindow ( dpy , c - > win , c - > x , c - > y ) ;
2015-11-08 23:11:48 +01:00
if ( ( ! c - > mon - > lt [ c - > mon - > sellt ] - > arrange | | c - > isfloating ) & & ! c - > isfullscreen )
2021-04-09 11:20:47 -04:00
resize ( c , c - > x , c - > y , c - > w , c - > h , c - > bw , 0 ) ;
2009-03-19 13:06:15 +00:00
showhide ( c - > snext ) ;
2015-11-08 23:11:48 +01:00
} else {
/* hide clients bottom up */
2009-03-19 13:06:15 +00:00
showhide ( c - > snext ) ;
2011-10-30 12:14:34 +01:00
XMoveWindow ( dpy , c - > win , WIDTH ( c ) * - 2 , c - > y ) ;
2008-09-06 09:34:49 +01:00
}
2008-09-06 09:21:32 +01:00
}
2008-12-12 19:55:03 +00:00
void
2015-11-08 23:11:48 +01:00
sigchld ( int unused )
{
if ( signal ( SIGCHLD , sigchld ) = = SIG_ERR )
2015-10-20 23:28:30 +02:00
die ( " can't install SIGCHLD handler: " ) ;
2015-11-08 23:11:48 +01:00
while ( 0 < waitpid ( - 1 , NULL , WNOHANG ) ) ;
2008-12-12 19:55:03 +00:00
}
2021-04-09 01:24:48 -04:00
void
sighup ( int unused )
{
Arg a = { . i = 1 } ;
quit ( & a ) ;
}
void
sigterm ( int unused )
{
Arg a = { . i = 0 } ;
quit ( & a ) ;
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
spawn ( const Arg * arg )
{
if ( arg - > v = = dmenucmd )
2013-08-02 22:40:20 +02:00
dmenumon [ 0 ] = ' 0 ' + selmon - > num ;
2015-11-08 23:11:48 +01:00
if ( fork ( ) = = 0 ) {
if ( dpy )
2008-12-12 19:55:03 +00:00
close ( ConnectionNumber ( dpy ) ) ;
setsid ( ) ;
execvp ( ( ( char * * ) arg - > v ) [ 0 ] , ( char * * ) arg - > v ) ;
fprintf ( stderr , " dwm: execvp %s " , ( ( char * * ) arg - > v ) [ 0 ] ) ;
perror ( " failed " ) ;
2011-05-12 14:16:33 +00:00
exit ( EXIT_SUCCESS ) ;
2007-09-15 22:25:27 +02:00
}
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
tag ( const Arg * arg )
{
if ( selmon - > sel & & arg - > ui & TAGMASK ) {
2009-06-23 17:17:25 +01:00
selmon - > sel - > tags = arg - > ui & TAGMASK ;
2011-07-29 20:01:22 +02:00
focus ( NULL ) ;
2009-09-27 10:31:14 +01:00
arrange ( selmon ) ;
2008-05-22 11:04:19 +01:00
}
2007-09-15 22:25:27 +02:00
}
2009-06-20 15:10:04 +01:00
void
2015-11-08 23:11:48 +01:00
tagmon ( const Arg * arg )
{
if ( ! selmon - > sel | | ! mons - > next )
2009-07-02 20:38:56 +01:00
return ;
2009-07-02 20:37:26 +01:00
sendmon ( selmon - > sel , dirtomon ( arg - > i ) ) ;
2009-06-20 15:10:04 +01:00
}
2008-05-19 12:34:54 +01:00
void
2015-11-08 23:11:48 +01:00
togglebar ( const Arg * arg )
{
2021-04-08 23:16:19 -04:00
unsigned int i ;
2009-06-20 15:10:04 +01:00
selmon - > showbar = ! selmon - > showbar ;
2021-04-08 23:16:19 -04:00
for ( i = 0 ; i < LENGTH ( tags ) ; + + i )
if ( selmon - > tagset [ selmon - > seltags ] & 1 < < i )
selmon - > pertag - > showbars [ i + 1 ] = selmon - > showbar ;
if ( selmon - > pertag - > curtag = = 0 )
{
selmon - > pertag - > showbars [ 0 ] = selmon - > showbar ;
}
2009-06-22 20:29:59 +01:00
updatebarpos ( selmon ) ;
2009-06-20 15:10:04 +01:00
XMoveResizeWindow ( dpy , selmon - > barwin , selmon - > wx , selmon - > by , selmon - > ww , bh ) ;
2009-09-27 10:31:14 +01:00
arrange ( selmon ) ;
2008-05-19 12:34:54 +01:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
togglefloating ( const Arg * arg )
{
if ( ! selmon - > sel )
2007-09-16 11:53:14 +02:00
return ;
2015-11-08 23:11:48 +01:00
if ( selmon - > sel - > isfullscreen ) /* no support for fullscreen windows */
2012-06-23 09:06:00 +02:00
return ;
2009-06-23 17:17:25 +01:00
selmon - > sel - > isfloating = ! selmon - > sel - > isfloating | | selmon - > sel - > isfixed ;
2015-11-08 23:11:48 +01:00
if ( selmon - > sel - > isfloating )
2009-07-02 18:30:01 +01:00
resize ( selmon - > sel , selmon - > sel - > x , selmon - > sel - > y ,
2021-04-09 11:20:47 -04:00
selmon - > sel - > w - 2 * ( borderpx - selmon - > sel - > bw ) ,
selmon - > sel - > h - 2 * ( borderpx - selmon - > sel - > bw ) ,
borderpx , 0 ) ;
2009-09-27 10:31:14 +01:00
arrange ( selmon ) ;
2007-09-16 11:53:14 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
toggletag ( const Arg * arg )
{
2009-08-16 08:18:54 +01:00
unsigned int newtags ;
2008-06-19 09:11:11 +01:00
2015-11-08 23:11:48 +01:00
if ( ! selmon - > sel )
2008-08-22 15:26:30 +02:00
return ;
2009-08-16 08:18:54 +01:00
newtags = selmon - > sel - > tags ^ ( arg - > ui & TAGMASK ) ;
2015-11-08 23:11:48 +01:00
if ( newtags ) {
2009-08-16 08:18:54 +01:00
selmon - > sel - > tags = newtags ;
2011-07-29 20:01:22 +02:00
focus ( NULL ) ;
2009-09-27 10:31:14 +01:00
arrange ( selmon ) ;
2008-06-19 09:11:11 +01:00
}
2007-09-16 11:53:14 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
toggleview ( const Arg * arg )
{
2009-08-16 08:18:54 +01:00
unsigned int newtagset = selmon - > tagset [ selmon - > seltags ] ^ ( arg - > ui & TAGMASK ) ;
2021-04-08 23:16:19 -04:00
int i ;
2008-06-19 09:11:11 +01:00
2015-11-08 23:11:48 +01:00
if ( newtagset ) {
2009-08-16 08:18:54 +01:00
selmon - > tagset [ selmon - > seltags ] = newtagset ;
2021-04-08 23:16:19 -04:00
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 ( selmon - > showbar ! = selmon - > pertag - > showbars [ selmon - > pertag - > curtag ] )
togglebar ( NULL ) ;
2011-07-29 20:01:22 +02:00
focus ( NULL ) ;
2009-09-27 10:31:14 +01:00
arrange ( selmon ) ;
2008-06-19 09:11:11 +01:00
}
2007-09-16 11:53:14 +02:00
}
2009-06-24 19:45:47 +01:00
void
2015-11-08 23:11:48 +01:00
unfocus ( Client * c , int setfocus )
{
if ( ! c )
2009-06-24 19:45:47 +01:00
return ;
2015-11-08 22:48:43 +01:00
grabbuttons ( c , 0 ) ;
2016-05-22 22:33:56 +02:00
XSetWindowBorder ( dpy , c - > win , scheme [ SchemeNorm ] [ ColBorder ] . pixel ) ;
2015-11-08 23:11:48 +01:00
if ( setfocus ) {
2010-05-30 10:02:56 +01:00
XSetInputFocus ( dpy , root , RevertToPointerRoot , CurrentTime ) ;
2012-03-25 17:46:03 +02:00
XDeleteProperty ( dpy , root , netatom [ NetActiveWindow ] ) ;
}
2009-06-24 19:45:47 +01:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
unmanage ( Client * c , int destroyed )
{
2009-09-27 10:31:14 +01:00
Monitor * m = c - > mon ;
2007-09-16 11:53:14 +02:00
XWindowChanges wc ;
detach ( c ) ;
detachstack ( c ) ;
2015-11-08 23:11:48 +01:00
if ( ! destroyed ) {
2009-09-08 13:13:03 +01:00
wc . border_width = c - > oldbw ;
2017-01-07 17:21:28 +01:00
XGrabServer ( dpy ) ; /* avoid race conditions */
2009-09-08 13:13:03 +01:00
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 ) ;
}
2007-09-16 11:53:14 +02:00
free ( c ) ;
2009-06-30 19:39:59 +01:00
focus ( NULL ) ;
2012-03-25 17:49:35 +02:00
updateclientlist ( ) ;
2009-09-27 10:31:14 +01:00
arrange ( m ) ;
2007-09-16 11:53:14 +02:00
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
unmapnotify ( XEvent * e )
{
2007-09-16 11:53:14 +02:00
Client * c ;
XUnmapEvent * ev = & e - > xunmap ;
2015-11-08 23:11:48 +01:00
if ( ( c = wintoclient ( ev - > window ) ) ) {
if ( ev - > send_event )
2011-08-08 16:55:06 +00:00
setclientstate ( c , WithdrawnState ) ;
else
2015-11-08 22:48:43 +01:00
unmanage ( c , 0 ) ;
2011-08-08 16:55:06 +00:00
}
2007-09-16 11:53:14 +02:00
}
2009-06-22 14:58:08 +01:00
void
2015-11-08 23:11:48 +01:00
updatebars ( void )
{
2009-06-22 14:58:08 +01:00
Monitor * m ;
2011-05-12 14:16:33 +00:00
XSetWindowAttributes wa = {
. override_redirect = True ,
. background_pixmap = ParentRelative ,
. event_mask = ButtonPressMask | ExposureMask
} ;
2017-11-03 09:58:38 -07:00
XClassHint ch = { " dwm " , " dwm " } ;
2015-11-08 23:11:48 +01:00
for ( m = mons ; m ; m = m - > next ) {
2012-01-12 07:36:05 +01:00
if ( m - > barwin )
continue ;
2009-06-22 14:58:08 +01:00
m - > barwin = XCreateWindow ( dpy , root , m - > wx , m - > by , m - > ww , bh , 0 , DefaultDepth ( dpy , screen ) ,
2017-05-08 21:08:27 +02:00
CopyFromParent , DefaultVisual ( dpy , screen ) ,
CWOverrideRedirect | CWBackPixmap | CWEventMask , & wa ) ;
2013-06-16 15:20:29 +02:00
XDefineCursor ( dpy , m - > barwin , cursor [ CurNormal ] - > cursor ) ;
2009-06-22 14:58:08 +01:00
XMapRaised ( dpy , m - > barwin ) ;
2017-11-03 09:58:38 -07:00
XSetClassHint ( dpy , m - > barwin , & ch ) ;
2009-06-22 14:58:08 +01:00
}
}
2009-06-22 20:29:59 +01:00
void
2015-11-08 23:11:48 +01:00
updatebarpos ( Monitor * m )
{
2009-06-22 20:29:59 +01:00
m - > wy = m - > my ;
m - > wh = m - > mh ;
2015-11-08 23:11:48 +01:00
if ( m - > showbar ) {
2009-06-22 20:29:59 +01:00
m - > wh - = bh ;
m - > by = m - > topbar ? m - > wy : m - > wy + m - > wh ;
m - > wy = m - > topbar ? m - > wy + bh : m - > wy ;
2015-11-08 23:11:48 +01:00
} else
2009-06-22 20:29:59 +01:00
m - > by = - bh ;
}
2012-03-25 17:49:35 +02:00
void
2015-11-08 23:11:48 +01:00
updateclientlist ( )
{
2012-03-25 17:49:35 +02:00
Client * c ;
Monitor * m ;
XDeleteProperty ( dpy , root , netatom [ NetClientList ] ) ;
2015-11-08 23:11:48 +01:00
for ( m = mons ; m ; m = m - > next )
for ( c = m - > clients ; c ; c = c - > next )
2012-03-25 17:49:35 +02:00
XChangeProperty ( dpy , root , netatom [ NetClientList ] ,
2017-05-08 21:08:27 +02:00
XA_WINDOW , 32 , PropModeAppend ,
( unsigned char * ) & ( c - > win ) , 1 ) ;
2012-03-25 17:49:35 +02:00
}
2015-11-08 22:48:43 +01:00
int
2015-11-08 23:11:48 +01:00
updategeom ( void )
{
2015-11-08 22:48:43 +01:00
int dirty = 0 ;
2009-09-21 19:51:17 +01:00
2009-06-30 19:39:59 +01:00
# ifdef XINERAMA
2015-11-08 23:11:48 +01:00
if ( XineramaIsActive ( dpy ) ) {
2012-07-08 09:43:11 +02:00
int i , j , n , nn ;
2009-09-22 20:33:42 +01:00
Client * c ;
2012-07-08 09:43:11 +02:00
Monitor * m ;
XineramaScreenInfo * info = XineramaQueryScreens ( dpy , & nn ) ;
2009-09-21 19:51:17 +01:00
XineramaScreenInfo * unique = NULL ;
2015-11-08 23:11:48 +01:00
for ( n = 0 , m = mons ; m ; m = m - > next , n + + ) ;
2009-09-21 19:51:17 +01:00
/* only consider unique geometries as separate screens */
2015-10-20 23:30:31 +02:00
unique = ecalloc ( nn , sizeof ( XineramaScreenInfo ) ) ;
2015-11-08 23:11:48 +01:00
for ( i = 0 , j = 0 ; i < nn ; i + + )
if ( isuniquegeom ( unique , j , & info [ i ] ) )
2009-09-21 19:51:17 +01:00
memcpy ( & unique [ j + + ] , & info [ i ] , sizeof ( XineramaScreenInfo ) ) ;
XFree ( info ) ;
2012-07-08 09:43:11 +02:00
nn = j ;
2017-01-07 17:21:28 +01:00
if ( n < = nn ) { /* new monitors available */
for ( i = 0 ; i < ( nn - n ) ; i + + ) {
2015-11-08 23:11:48 +01:00
for ( m = mons ; m & & m - > next ; m = m - > next ) ;
if ( m )
2012-07-08 09:43:11 +02:00
m - > next = createmon ( ) ;
else
mons = createmon ( ) ;
}
2015-11-08 23:11:48 +01:00
for ( i = 0 , m = mons ; i < nn & & m ; m = m - > next , i + + )
if ( i > = n
2017-01-07 17:21:28 +01:00
| | unique [ i ] . x_org ! = m - > mx | | unique [ i ] . y_org ! = m - > my
| | unique [ i ] . width ! = m - > mw | | unique [ i ] . height ! = m - > mh )
2012-07-08 09:43:11 +02:00
{
2015-11-08 22:48:43 +01:00
dirty = 1 ;
2012-07-08 09:43:11 +02:00
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 ) ;
}
2017-01-07 17:21:28 +01:00
} else { /* less monitors available nn < n */
2015-11-08 23:11:48 +01:00
for ( i = nn ; i < n ; i + + ) {
for ( m = mons ; m & & m - > next ; m = m - > next ) ;
2017-01-07 17:21:28 +01:00
while ( ( c = m - > clients ) ) {
2015-11-08 22:48:43 +01:00
dirty = 1 ;
2012-07-08 09:43:11 +02:00
m - > clients = c - > next ;
detachstack ( c ) ;
c - > mon = mons ;
attach ( c ) ;
attachstack ( c ) ;
}
2015-11-08 23:11:48 +01:00
if ( m = = selmon )
2012-07-08 09:43:11 +02:00
selmon = mons ;
cleanupmon ( m ) ;
2012-06-23 10:12:46 +02:00
}
}
2012-07-08 09:43:11 +02:00
free ( unique ) ;
2015-11-08 23:11:48 +01:00
} else
2009-06-30 19:39:59 +01:00
# endif /* XINERAMA */
2017-01-07 17:21:28 +01:00
{ /* default monitor setup */
2015-11-08 23:11:48 +01:00
if ( ! mons )
2009-09-21 19:51:17 +01:00
mons = createmon ( ) ;
2015-11-08 23:11:48 +01:00
if ( mons - > mw ! = sw | | mons - > mh ! = sh ) {
2015-11-08 22:48:43 +01:00
dirty = 1 ;
2009-09-21 19:51:17 +01:00
mons - > mw = mons - > ww = sw ;
mons - > mh = mons - > wh = sh ;
updatebarpos ( mons ) ;
}
2009-06-22 14:58:08 +01:00
}
2015-11-08 23:11:48 +01:00
if ( dirty ) {
2012-07-08 09:43:11 +02:00
selmon = mons ;
selmon = wintomon ( root ) ;
}
return dirty ;
2008-05-11 20:20:53 +01:00
}
2008-08-25 09:44:23 +01:00
void
2015-11-08 23:11:48 +01:00
updatenumlockmask ( void )
{
2008-08-25 09:44:23 +01:00
unsigned int i , j ;
XModifierKeymap * modmap ;
numlockmask = 0 ;
modmap = XGetModifierMapping ( dpy ) ;
2015-11-08 23:11:48 +01:00
for ( i = 0 ; i < 8 ; i + + )
for ( j = 0 ; j < modmap - > max_keypermod ; j + + )
if ( modmap - > modifiermap [ i * modmap - > max_keypermod + j ]
2017-05-08 21:08:27 +02:00
= = XKeysymToKeycode ( dpy , XK_Num_Lock ) )
2008-08-25 09:44:23 +01:00
numlockmask = ( 1 < < i ) ;
XFreeModifiermap ( modmap ) ;
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
updatesizehints ( Client * c )
{
2007-09-16 11:53:14 +02:00
long msize ;
XSizeHints size ;
2015-11-08 23:11:48 +01:00
if ( ! XGetWMNormalHints ( dpy , c - > win , & size , & msize ) )
2008-09-07 09:53:59 +01:00
/* size is uninitialized, ensure that size.flags aren't used */
2009-06-20 15:10:04 +01:00
size . flags = PSize ;
2015-11-08 23:11:48 +01:00
if ( size . flags & PBaseSize ) {
2007-09-16 11:53:14 +02:00
c - > basew = size . base_width ;
c - > baseh = size . base_height ;
2015-11-08 23:11:48 +01:00
} else if ( size . flags & PMinSize ) {
2007-09-16 11:53:14 +02:00
c - > basew = size . min_width ;
c - > baseh = size . min_height ;
2015-11-08 23:11:48 +01:00
} else
2007-09-16 11:53:14 +02:00
c - > basew = c - > baseh = 0 ;
2015-11-08 23:11:48 +01:00
if ( size . flags & PResizeInc ) {
2007-09-16 11:53:14 +02:00
c - > incw = size . width_inc ;
c - > inch = size . height_inc ;
2015-11-08 23:11:48 +01:00
} else
2007-09-16 11:53:14 +02:00
c - > incw = c - > inch = 0 ;
2015-11-08 23:11:48 +01:00
if ( size . flags & PMaxSize ) {
2007-09-16 11:53:14 +02:00
c - > maxw = size . max_width ;
c - > maxh = size . max_height ;
2015-11-08 23:11:48 +01:00
} else
2007-09-16 11:53:14 +02:00
c - > maxw = c - > maxh = 0 ;
2015-11-08 23:11:48 +01:00
if ( size . flags & PMinSize ) {
2007-09-16 11:53:14 +02:00
c - > minw = size . min_width ;
c - > minh = size . min_height ;
2015-11-08 23:11:48 +01:00
} else if ( size . flags & PBaseSize ) {
2007-09-16 11:53:14 +02:00
c - > minw = size . base_width ;
c - > minh = size . base_height ;
2015-11-08 23:11:48 +01:00
} else
2007-09-16 11:53:14 +02:00
c - > minw = c - > minh = 0 ;
2015-11-08 23:11:48 +01:00
if ( size . flags & PAspect ) {
2009-07-17 13:35:17 +01:00
c - > mina = ( float ) size . min_aspect . y / size . min_aspect . x ;
c - > maxa = ( float ) size . max_aspect . x / size . max_aspect . y ;
2015-11-08 23:11:48 +01:00
} else
2008-06-11 09:12:06 +01:00
c - > maxa = c - > mina = 0.0 ;
2017-10-11 08:10:45 +11:00
c - > isfixed = ( c - > maxw & & c - > maxh & & c - > maxw = = c - > minw & & c - > maxh = = c - > minh ) ;
2007-09-16 11:53:14 +02:00
}
2018-03-14 13:58:06 -04:00
void
updatestatus ( void )
{
if ( ! gettextprop ( root , XA_WM_NAME , stext , sizeof ( stext ) ) )
strcpy ( stext , " dwm- " VERSION ) ;
drawbar ( selmon ) ;
}
2007-09-17 16:42:37 +02:00
void
2015-11-08 23:11:48 +01:00
updatetitle ( Client * c )
{
if ( ! gettextprop ( c - > win , netatom [ NetWMName ] , c - > name , sizeof c - > name ) )
2008-08-25 11:43:45 +02:00
gettextprop ( c - > win , XA_WM_NAME , c - > name , sizeof c - > name ) ;
2015-11-08 23:11:48 +01:00
if ( c - > name [ 0 ] = = ' \0 ' ) /* hack to mark broken clients */
2009-07-12 22:49:06 +01:00
strcpy ( c - > name , broken ) ;
2007-09-16 11:53:14 +02:00
}
2011-11-02 12:01:28 +00:00
void
2015-11-08 23:11:48 +01:00
updatewindowtype ( Client * c )
{
2011-11-06 20:30:06 +01:00
Atom state = getatomprop ( c , netatom [ NetWMState ] ) ;
Atom wtype = getatomprop ( c , netatom [ NetWMWindowType ] ) ;
2011-11-02 12:01:28 +00:00
2015-11-08 23:11:48 +01:00
if ( state = = netatom [ NetWMFullscreen ] )
2015-11-08 22:48:43 +01:00
setfullscreen ( c , 1 ) ;
2015-11-08 23:11:48 +01:00
if ( wtype = = netatom [ NetWMWindowTypeDialog ] )
2015-11-08 22:48:43 +01:00
c - > isfloating = 1 ;
2011-11-02 12:01:28 +00:00
}
2008-02-11 20:34:17 +00:00
void
2015-11-08 23:11:48 +01:00
updatewmhints ( Client * c )
{
2008-02-11 20:34:17 +00:00
XWMHints * wmh ;
2015-11-08 23:11:48 +01:00
if ( ( wmh = XGetWMHints ( dpy , c - > win ) ) ) {
if ( c = = selmon - > sel & & wmh - > flags & XUrgencyHint ) {
2008-07-13 18:08:55 +01:00
wmh - > flags & = ~ XUrgencyHint ;
XSetWMHints ( dpy , c - > win , wmh ) ;
2015-11-08 23:11:48 +01:00
} else
2015-11-08 22:48:43 +01:00
c - > isurgent = ( wmh - > flags & XUrgencyHint ) ? 1 : 0 ;
2015-11-08 23:11:48 +01:00
if ( wmh - > flags & InputHint )
2011-04-14 13:46:25 +00:00
c - > neverfocus = ! wmh - > input ;
else
2015-11-08 22:48:43 +01:00
c - > neverfocus = 0 ;
2008-02-11 20:34:17 +00:00
XFree ( wmh ) ;
}
}
2008-02-26 22:51:23 +00:00
void
2015-11-08 23:11:48 +01:00
view ( const Arg * arg )
{
2021-04-08 23:16:19 -04:00
int i ;
unsigned int tmptag ;
2015-11-08 23:11:48 +01:00
if ( ( arg - > ui & TAGMASK ) = = selmon - > tagset [ selmon - > seltags ] )
2008-07-02 11:06:46 +01:00
return ;
2009-06-19 20:15:15 +01:00
selmon - > seltags ^ = 1 ; /* toggle sel tagset */
2021-04-08 23:16:19 -04:00
if ( arg - > ui & TAGMASK ) {
2009-06-20 17:02:55 +01:00
selmon - > tagset [ selmon - > seltags ] = arg - > ui & TAGMASK ;
2021-04-08 23:16:19 -04:00
selmon - > pertag - > prevtag = selmon - > pertag - > curtag ;
if ( arg - > ui = = ~ 0 )
selmon - > pertag - > curtag = 0 ;
else {
for ( i = 0 ; ! ( arg - > ui & 1 < < i ) ; i + + ) ;
selmon - > pertag - > curtag = i + 1 ;
}
} else {
tmptag = selmon - > pertag - > prevtag ;
selmon - > pertag - > prevtag = selmon - > pertag - > curtag ;
selmon - > pertag - > curtag = tmptag ;
}
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 ( selmon - > showbar ! = selmon - > pertag - > showbars [ selmon - > pertag - > curtag ] )
togglebar ( NULL ) ;
2011-07-29 20:01:22 +02:00
focus ( NULL ) ;
2009-09-27 10:31:14 +01:00
arrange ( selmon ) ;
2008-02-26 22:51:23 +00:00
}
2020-12-01 09:34:31 -05:00
void
warp ( const Client * c )
{
int x , y ;
if ( ! c ) {
XWarpPointer ( dpy , None , root , 0 , 0 , 0 , 0 , selmon - > wx + selmon - > ww / 2 , selmon - > wy + selmon - > wh / 2 ) ;
return ;
}
if ( ! getrootptr ( & x , & y ) | |
( x > c - > x - c - > bw & &
y > c - > y - c - > bw & &
x < c - > x + c - > w + c - > bw * 2 & &
y < c - > y + c - > h + c - > bw * 2 ) | |
( y > c - > mon - > by & & y < c - > mon - > by + bh ) | |
( c - > mon - > topbar & & ! y ) )
return ;
XWarpPointer ( dpy , None , c - > win , 0 , 0 , 0 , 0 , c - > w / 2 , c - > h / 2 ) ;
}
2009-06-30 19:39:59 +01:00
Client *
2015-11-08 23:11:48 +01:00
wintoclient ( Window w )
{
2009-06-30 19:39:59 +01:00
Client * c ;
Monitor * m ;
2015-11-08 23:11:48 +01:00
for ( m = mons ; m ; m = m - > next )
for ( c = m - > clients ; c ; c = c - > next )
if ( c - > win = = w )
2009-06-30 19:39:59 +01:00
return c ;
return NULL ;
}
Monitor *
2015-11-08 23:11:48 +01:00
wintomon ( Window w )
{
2009-06-30 19:39:59 +01:00
int x , y ;
Client * c ;
Monitor * m ;
2015-11-08 23:11:48 +01:00
if ( w = = root & & getrootptr ( & x , & y ) )
2011-11-06 20:31:29 +01:00
return recttomon ( x , y , 1 , 1 ) ;
2015-11-08 23:11:48 +01:00
for ( m = mons ; m ; m = m - > next )
if ( w = = m - > barwin )
2009-06-30 19:39:59 +01:00
return m ;
2015-11-08 23:11:48 +01:00
if ( ( c = wintoclient ( w ) ) )
2009-06-30 19:39:59 +01:00
return c - > mon ;
2009-07-02 14:42:06 +01:00
return selmon ;
2009-06-30 19:39:59 +01:00
}
2007-09-16 11:53:14 +02:00
/* There's no way to check accesses to destroyed windows, thus those cases are
2017-01-07 17:21:28 +01:00
* ignored ( especially on UnmapNotify ' s ) . Other types of errors call Xlibs
* default error handler , which may call exit . */
2007-09-17 16:42:37 +02:00
int
2015-11-08 23:11:48 +01:00
xerror ( Display * dpy , XErrorEvent * ee )
{
if ( ee - > error_code = = BadWindow
2007-09-16 11:53:14 +02:00
| | ( 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 )
2008-05-06 15:13:36 +01:00
| | ( ee - > request_code = = X_GrabButton & & ee - > error_code = = BadAccess )
2007-09-16 11:53:14 +02:00
| | ( 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 " ,
2017-05-08 21:08:27 +02:00
ee - > request_code , ee - > error_code ) ;
2007-09-16 11:53:14 +02:00
return xerrorxlib ( dpy , ee ) ; /* may call exit */
}
2007-09-17 16:42:37 +02:00
int
2015-11-08 23:11:48 +01:00
xerrordummy ( Display * dpy , XErrorEvent * ee )
{
2007-09-16 11:53:14 +02:00
return 0 ;
}
/* Startup Error handler to check if another window manager
* is already running . */
2007-09-17 16:42:37 +02:00
int
2015-11-08 23:11:48 +01:00
xerrorstart ( Display * dpy , XErrorEvent * ee )
{
2016-08-12 14:35:25 +02:00
die ( " dwm: another window manager is already running " ) ;
2007-09-16 11:53:14 +02:00
return - 1 ;
}
2008-05-19 20:07:12 +01:00
void
2015-11-08 23:11:48 +01:00
zoom ( const Arg * arg )
{
2009-06-23 17:17:25 +01:00
Client * c = selmon - > sel ;
2008-05-19 20:07:12 +01:00
2015-11-08 23:11:48 +01:00
if ( ! selmon - > lt [ selmon - > sellt ] - > arrange
2009-07-02 18:40:04 +01:00
| | ( selmon - > sel & & selmon - > sel - > isfloating ) )
2008-05-22 11:12:22 +01:00
return ;
2015-11-08 23:11:48 +01:00
if ( c = = nexttiled ( selmon - > clients ) )
if ( ! c | | ! ( c = nexttiled ( c - > next ) ) )
2008-05-19 20:07:12 +01:00
return ;
2011-04-15 08:12:20 +00:00
pop ( c ) ;
2008-05-19 20:07:12 +01:00
}
2007-09-15 22:25:27 +02:00
int
2015-11-08 23:11:48 +01:00
main ( int argc , char * argv [ ] )
{
if ( argc = = 2 & & ! strcmp ( " -v " , argv [ 1 ] ) )
2016-08-12 14:35:25 +02:00
die ( " dwm- " VERSION ) ;
2015-11-08 23:11:48 +01:00
else if ( argc ! = 1 )
2016-08-12 14:35:25 +02:00
die ( " usage: dwm [-v] " ) ;
2015-11-08 23:11:48 +01:00
if ( ! setlocale ( LC_CTYPE , " " ) | | ! XSupportsLocale ( ) )
2009-02-21 19:12:46 +00:00
fputs ( " warning: no locale support \n " , stderr ) ;
2015-11-08 23:11:48 +01:00
if ( ! ( dpy = XOpenDisplay ( NULL ) ) )
2016-08-12 14:35:25 +02:00
die ( " dwm: cannot open display " ) ;
2007-09-16 12:34:08 +02:00
checkotherwm ( ) ;
2007-09-15 22:25:27 +02:00
setup ( ) ;
2018-05-25 07:56:27 +02:00
# ifdef __OpenBSD__
2018-06-02 17:15:42 +02:00
if ( pledge ( " stdio rpath proc exec " , NULL ) = = - 1 )
2018-05-25 07:56:27 +02:00
die ( " pledge " ) ;
# endif /* __OpenBSD__ */
2007-09-15 22:25:27 +02:00
scan ( ) ;
2007-09-16 12:34:08 +02:00
run ( ) ;
2021-04-09 01:24:48 -04:00
if ( restart ) execvp ( argv [ 0 ] , argv ) ;
2007-09-15 22:25:27 +02:00
cleanup ( ) ;
XCloseDisplay ( dpy ) ;
2011-05-12 14:16:33 +00:00
return EXIT_SUCCESS ;
2007-09-15 22:25:27 +02:00
}