dwm.c
changeset 1519 72272822ddf2
parent 1517 1ed1e75c9c2e
child 1522 0d86faf4b05c
equal deleted inserted replaced
1518:b18b2317ee8e 1519:72272822ddf2
    55 #define TEXTW(X)                (textnw(X, strlen(X)) + dc.font.height)
    55 #define TEXTW(X)                (textnw(X, strlen(X)) + dc.font.height)
    56 
    56 
    57 /* enums */
    57 /* enums */
    58 enum { CurNormal, CurResize, CurMove, CurLast };        /* cursor */
    58 enum { CurNormal, CurResize, CurMove, CurLast };        /* cursor */
    59 enum { ColBorder, ColFG, ColBG, ColLast };              /* color */
    59 enum { ColBorder, ColFG, ColBG, ColLast };              /* color */
    60 enum { NetSupported, NetWMName, NetWMState, NetLast };  /* EWMH atoms */
    60 enum { NetSupported, NetWMName, NetWMState,
       
    61        NetWMFullscreen, NetLast };                      /* EWMH atoms */
    61 enum { WMProtocols, WMDelete, WMState, WMLast };        /* default atoms */
    62 enum { WMProtocols, WMDelete, WMState, WMLast };        /* default atoms */
    62 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
    63 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
    63        ClkClientWin, ClkRootWin, ClkLast };             /* clicks */
    64        ClkClientWin, ClkRootWin, ClkLast };             /* clicks */
    64 
    65 
    65 typedef union {
    66 typedef union {
    81 typedef struct Client Client;
    82 typedef struct Client Client;
    82 struct Client {
    83 struct Client {
    83 	char name[256];
    84 	char name[256];
    84 	float mina, maxa;
    85 	float mina, maxa;
    85 	int x, y, w, h;
    86 	int x, y, w, h;
       
    87 	int oldx, oldy, oldw, oldh;
    86 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    88 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    87 	int bw, oldbw;
    89 	int bw, oldbw;
    88 	unsigned int tags;
    90 	unsigned int tags;
    89 	Bool isfixed, isfloating, isurgent;
    91 	Bool isfixed, isfloating, isurgent, oldstate;
    90 	Client *next;
    92 	Client *next;
    91 	Client *snext;
    93 	Client *snext;
    92 	Monitor *mon;
    94 	Monitor *mon;
    93 	Window win;
    95 	Window win;
    94 };
    96 };
   159 static void buttonpress(XEvent *e);
   161 static void buttonpress(XEvent *e);
   160 static void checkotherwm(void);
   162 static void checkotherwm(void);
   161 static void cleanup(void);
   163 static void cleanup(void);
   162 static void cleanupmon(Monitor *mon);
   164 static void cleanupmon(Monitor *mon);
   163 static void clearurgent(Client *c);
   165 static void clearurgent(Client *c);
       
   166 static void clientmessage(XEvent *e);
   164 static void configure(Client *c);
   167 static void configure(Client *c);
   165 static void configurenotify(XEvent *e);
   168 static void configurenotify(XEvent *e);
   166 static void configurerequest(XEvent *e);
   169 static void configurerequest(XEvent *e);
   167 static Monitor *createmon(void);
   170 static Monitor *createmon(void);
   168 static void destroynotify(XEvent *e);
   171 static void destroynotify(XEvent *e);
   198 static Client *nexttiled(Client *c);
   201 static Client *nexttiled(Client *c);
   199 static Monitor *ptrtomon(int x, int y);
   202 static Monitor *ptrtomon(int x, int y);
   200 static void propertynotify(XEvent *e);
   203 static void propertynotify(XEvent *e);
   201 static void quit(const Arg *arg);
   204 static void quit(const Arg *arg);
   202 static void resize(Client *c, int x, int y, int w, int h, Bool interact);
   205 static void resize(Client *c, int x, int y, int w, int h, Bool interact);
       
   206 static void resizeclient(Client *c, int x, int y, int w, int h);
   203 static void resizemouse(const Arg *arg);
   207 static void resizemouse(const Arg *arg);
   204 static void restack(Monitor *m);
   208 static void restack(Monitor *m);
   205 static void run(void);
   209 static void run(void);
   206 static void scan(void);
   210 static void scan(void);
   207 static void sendmon(Client *c, Monitor *m);
   211 static void sendmon(Client *c, Monitor *m);
   218 static void tile(Monitor *);
   222 static void tile(Monitor *);
   219 static void togglebar(const Arg *arg);
   223 static void togglebar(const Arg *arg);
   220 static void togglefloating(const Arg *arg);
   224 static void togglefloating(const Arg *arg);
   221 static void toggletag(const Arg *arg);
   225 static void toggletag(const Arg *arg);
   222 static void toggleview(const Arg *arg);
   226 static void toggleview(const Arg *arg);
   223 static void unfocus(Client *c);
   227 static void unfocus(Client *c, Bool setfocus);
   224 static void unmanage(Client *c, Bool destroyed);
   228 static void unmanage(Client *c, Bool destroyed);
   225 static void unmapnotify(XEvent *e);
   229 static void unmapnotify(XEvent *e);
   226 static Bool updategeom(void);
   230 static Bool updategeom(void);
   227 static void updatebarpos(Monitor *m);
   231 static void updatebarpos(Monitor *m);
   228 static void updatebars(void);
   232 static void updatebars(void);
   247 static int bh, blw = 0;      /* bar geometry */
   251 static int bh, blw = 0;      /* bar geometry */
   248 static int (*xerrorxlib)(Display *, XErrorEvent *);
   252 static int (*xerrorxlib)(Display *, XErrorEvent *);
   249 static unsigned int numlockmask = 0;
   253 static unsigned int numlockmask = 0;
   250 static void (*handler[LASTEvent]) (XEvent *) = {
   254 static void (*handler[LASTEvent]) (XEvent *) = {
   251 	[ButtonPress] = buttonpress,
   255 	[ButtonPress] = buttonpress,
       
   256 	[ClientMessage] = clientmessage,
   252 	[ConfigureRequest] = configurerequest,
   257 	[ConfigureRequest] = configurerequest,
   253 	[ConfigureNotify] = configurenotify,
   258 	[ConfigureNotify] = configurenotify,
   254 	[DestroyNotify] = destroynotify,
   259 	[DestroyNotify] = destroynotify,
   255 	[EnterNotify] = enternotify,
   260 	[EnterNotify] = enternotify,
   256 	[Expose] = expose,
   261 	[Expose] = expose,
   421 	XButtonPressedEvent *ev = &e->xbutton;
   426 	XButtonPressedEvent *ev = &e->xbutton;
   422 
   427 
   423 	click = ClkRootWin;
   428 	click = ClkRootWin;
   424 	/* focus monitor if necessary */
   429 	/* focus monitor if necessary */
   425 	if((m = wintomon(ev->window)) && m != selmon) {
   430 	if((m = wintomon(ev->window)) && m != selmon) {
   426 		unfocus(selmon->sel);
   431 		unfocus(selmon->sel, True);
   427 		selmon = m;
   432 		selmon = m;
   428 		focus(NULL);
   433 		focus(NULL);
   429 	}
   434 	}
   430 	if(ev->window == selmon->barwin) {
   435 	if(ev->window == selmon->barwin) {
   431 		i = x = 0;
   436 		i = x = 0;
   790 	XCrossingEvent *ev = &e->xcrossing;
   795 	XCrossingEvent *ev = &e->xcrossing;
   791 
   796 
   792 	if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
   797 	if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
   793 		return;
   798 		return;
   794 	if((m = wintomon(ev->window)) && m != selmon) {
   799 	if((m = wintomon(ev->window)) && m != selmon) {
   795 		unfocus(selmon->sel);
   800 		unfocus(selmon->sel, True);
   796 		selmon = m;
   801 		selmon = m;
   797 	}
   802 	}
   798 	if((c = wintoclient(ev->window)))
   803 	if((c = wintoclient(ev->window)))
   799 		focus(c);
   804 		focus(c);
   800 	else
   805 	else
   812 
   817 
   813 void
   818 void
   814 focus(Client *c) {
   819 focus(Client *c) {
   815 	if(!c || !ISVISIBLE(c))
   820 	if(!c || !ISVISIBLE(c))
   816 		for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
   821 		for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
   817 	if(selmon->sel)
   822 	/* was if(selmon->sel) */
   818 		unfocus(selmon->sel);
   823 	if(selmon->sel && selmon->sel != c)
       
   824 		unfocus(selmon->sel, False);
   819 	if(c) {
   825 	if(c) {
   820 		if(c->mon != selmon)
   826 		if(c->mon != selmon)
   821 			selmon = c->mon;
   827 			selmon = c->mon;
   822 		if(c->isurgent)
   828 		if(c->isurgent)
   823 			clearurgent(c);
   829 			clearurgent(c);
   847 
   853 
   848 	if(!mons->next)
   854 	if(!mons->next)
   849 		return;
   855 		return;
   850 	if((m = dirtomon(arg->i)) == selmon)
   856 	if((m = dirtomon(arg->i)) == selmon)
   851 		return;
   857 		return;
   852 	unfocus(selmon->sel);
   858 	unfocus(selmon->sel, True);
   853 	selmon = m;
   859 	selmon = m;
   854 	focus(NULL);
   860 	focus(NULL);
   855 }
   861 }
   856 
   862 
   857 void
   863 void
   899 	return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
   905 	return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui);
   900 }
   906 }
   901 
   907 
   902 long
   908 long
   903 getstate(Window w) {
   909 getstate(Window w) {
   904 	int format, status;
   910 	int format;
   905 	long result = -1;
   911 	long result = -1;
   906 	unsigned char *p = NULL;
   912 	unsigned char *p = NULL;
   907 	unsigned long n, extra;
   913 	unsigned long n, extra;
   908 	Atom real;
   914 	Atom real;
   909 
   915 
   910 	status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
   916 	if(XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
   911 	                            &real, &format, &n, &extra, (unsigned char **)&p);
   917 	                      &real, &format, &n, &extra, (unsigned char **)&p) != Success)
   912 	if(status != Success)
       
   913 		return -1;
   918 		return -1;
   914 	if(n != 0)
   919 	if(n != 0)
   915 		result = *p;
   920 		result = *p;
   916 	XFree(p);
   921 	XFree(p);
   917 	return result;
   922 	return result;
  1108 	else {
  1113 	else {
  1109 		c->mon = selmon;
  1114 		c->mon = selmon;
  1110 		applyrules(c);
  1115 		applyrules(c);
  1111 	}
  1116 	}
  1112 	/* geometry */
  1117 	/* geometry */
  1113 	c->x = wa->x + c->mon->wx;
  1118 	c->x = c->oldx = wa->x + c->mon->wx;
  1114 	c->y = wa->y + c->mon->wy;
  1119 	c->y = c->oldy = wa->y + c->mon->wy;
  1115 	c->w = wa->width;
  1120 	c->w = c->oldw = wa->width;
  1116 	c->h = wa->height;
  1121 	c->h = c->oldh = wa->height;
  1117 	c->oldbw = wa->border_width;
  1122 	c->oldbw = wa->border_width;
  1118 	if(c->w == c->mon->mw && c->h == c->mon->mh) {
  1123 	if(c->w == c->mon->mw && c->h == c->mon->mh) {
       
  1124 		c->isfloating = 1;
  1119 		c->x = c->mon->mx;
  1125 		c->x = c->mon->mx;
  1120 		c->y = c->mon->my;
  1126 		c->y = c->mon->my;
  1121 		c->bw = 0;
  1127 		c->bw = 0;
  1122 	}
  1128 	}
  1123 	else {
  1129 	else {
  1137 	configure(c); /* propagates border_width, if size doesn't change */
  1143 	configure(c); /* propagates border_width, if size doesn't change */
  1138 	updatesizehints(c);
  1144 	updatesizehints(c);
  1139 	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
  1145 	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
  1140 	grabbuttons(c, False);
  1146 	grabbuttons(c, False);
  1141 	if(!c->isfloating)
  1147 	if(!c->isfloating)
  1142 		c->isfloating = trans != None || c->isfixed;
  1148 		c->isfloating = c->oldstate = trans != None || c->isfixed;
  1143 	if(c->isfloating)
  1149 	if(c->isfloating)
  1144 		XRaiseWindow(dpy, c->win);
  1150 		XRaiseWindow(dpy, c->win);
  1145 	attach(c);
  1151 	attach(c);
  1146 	attachstack(c);
  1152 	attachstack(c);
  1147 	XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
  1153 	XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
  1290 		}
  1296 		}
  1291 	}
  1297 	}
  1292 }
  1298 }
  1293 
  1299 
  1294 void
  1300 void
       
  1301 clientmessage(XEvent *e) {
       
  1302 	XClientMessageEvent *cme = &e->xclient;
       
  1303 	Client *c;
       
  1304 
       
  1305 	if((c = wintoclient(cme->window))
       
  1306 	&& (cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]))
       
  1307 	{
       
  1308 		if(cme->data.l[0]) {
       
  1309 			XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32,
       
  1310 			                PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
       
  1311 			c->oldstate = c->isfloating;
       
  1312 			c->oldbw = c->bw;
       
  1313 			c->bw = 0;
       
  1314 			c->isfloating = 1;
       
  1315 			resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
       
  1316 			XRaiseWindow(dpy, c->win);
       
  1317 		}
       
  1318 		else {
       
  1319 			XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32,
       
  1320 			                PropModeReplace, (unsigned char*)0, 0);
       
  1321 			c->isfloating = c->oldstate;
       
  1322 			c->bw = c->oldbw;
       
  1323 			c->x = c->oldx;
       
  1324 			c->y = c->oldy;
       
  1325 			c->w = c->oldw;
       
  1326 			c->h = c->oldh;
       
  1327 			resizeclient(c, c->x, c->y, c->w, c->h);
       
  1328 			arrange(c->mon);
       
  1329 		}
       
  1330 	}
       
  1331 }
       
  1332 
       
  1333 void
  1295 quit(const Arg *arg) {
  1334 quit(const Arg *arg) {
  1296 	running = False;
  1335 	running = False;
  1297 }
  1336 }
  1298 
  1337 
  1299 void
  1338 void
  1300 resize(Client *c, int x, int y, int w, int h, Bool interact) {
  1339 resize(Client *c, int x, int y, int w, int h, Bool interact) {
       
  1340 	if(applysizehints(c, &x, &y, &w, &h, interact))
       
  1341 		resizeclient(c, x, y, w, h);
       
  1342 }
       
  1343 
       
  1344 void
       
  1345 resizeclient(Client *c, int x, int y, int w, int h) {
  1301 	XWindowChanges wc;
  1346 	XWindowChanges wc;
  1302 
  1347 
  1303 	if(applysizehints(c, &x, &y, &w, &h, interact)) {
  1348 	c->oldx = c->x; c->x = wc.x = x;
  1304 		c->x = wc.x = x;
  1349 	c->oldy = c->y; c->y = wc.y = y;
  1305 		c->y = wc.y = y;
  1350 	c->oldw = c->w; c->w = wc.width = w;
  1306 		c->w = wc.width = w;
  1351 	c->oldh = c->h; c->h = wc.height = h;
  1307 		c->h = wc.height = h;
  1352 	wc.border_width = c->bw;
  1308 		wc.border_width = c->bw;
  1353 	XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
  1309 		XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
  1354 	configure(c);
  1310 		configure(c);
  1355 	XSync(dpy, False);
  1311 		XSync(dpy, False);
       
  1312 	}
       
  1313 }
  1356 }
  1314 
  1357 
  1315 void
  1358 void
  1316 resizemouse(const Arg *arg) {
  1359 resizemouse(const Arg *arg) {
  1317 	int ocx, ocy;
  1360 	int ocx, ocy;
  1425 
  1468 
  1426 void
  1469 void
  1427 sendmon(Client *c, Monitor *m) {
  1470 sendmon(Client *c, Monitor *m) {
  1428 	if(c->mon == m)
  1471 	if(c->mon == m)
  1429 		return;
  1472 		return;
  1430 	unfocus(c);
  1473 	unfocus(c, True);
  1431 	detach(c);
  1474 	detach(c);
  1432 	detachstack(c);
  1475 	detachstack(c);
  1433 	c->mon = m;
  1476 	c->mon = m;
  1434 	c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
  1477 	c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
  1435 	attach(c);
  1478 	attach(c);
  1493 	wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  1536 	wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  1494 	wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
  1537 	wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
  1495 	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
  1538 	netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
  1496 	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
  1539 	netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
  1497 	netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
  1540 	netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
       
  1541 	netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
  1498 	/* init cursors */
  1542 	/* init cursors */
  1499 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  1543 	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
  1500 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  1544 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
  1501 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
  1545 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
  1502 	/* init appearance */
  1546 	/* init appearance */
  1661 		arrange(selmon);
  1705 		arrange(selmon);
  1662 	}
  1706 	}
  1663 }
  1707 }
  1664 
  1708 
  1665 void
  1709 void
  1666 unfocus(Client *c) {
  1710 unfocus(Client *c, Bool setfocus) {
  1667 	if(!c)
  1711 	if(!c)
  1668 		return;
  1712 		return;
  1669 	grabbuttons(c, False);
  1713 	grabbuttons(c, False);
  1670 	XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]);
  1714 	XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]);
  1671 	XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
  1715 	if(setfocus)
       
  1716 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
  1672 }
  1717 }
  1673 
  1718 
  1674 void
  1719 void
  1675 unmanage(Client *c, Bool destroyed) {
  1720 unmanage(Client *c, Bool destroyed) {
  1676 	Monitor *m = c->mon;
  1721 	Monitor *m = c->mon;