dwm.c
changeset 1270 262ee84a2fdb
parent 1269 ce94428739ab
child 1271 c5ea09e8d2fc
equal deleted inserted replaced
1269:ce94428739ab 1270:262ee84a2fdb
    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, NetLast };              /* EWMH atoms */
    60 enum { NetSupported, NetWMName, NetLast };              /* EWMH atoms */
    61 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
    61 enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
       
    62 enum { ClkLtSymbol = -1, ClkStatusText = -2, ClkWinTitle = -3,
       
    63        ClkClientWin = -4, ClkRootWin = -5, ClkLast = -6};/* clicks */
    62 
    64 
    63 /* typedefs */
    65 /* typedefs */
    64 typedef unsigned int uint;
    66 typedef unsigned int uint;
    65 typedef unsigned long ulong;
    67 typedef unsigned long ulong;
       
    68 
       
    69 typedef union {
       
    70 	int i;
       
    71 	uint ui;
       
    72 	float f;
       
    73 	void *v;
       
    74 } Arg;
       
    75 
       
    76 typedef struct {
       
    77 	uint click;
       
    78 	uint mask;
       
    79 	uint button;
       
    80 	void (*func)(const Arg *arg);
       
    81 	const Arg arg;
       
    82 } Button;
       
    83 
    66 typedef struct Client Client;
    84 typedef struct Client Client;
    67 struct Client {
    85 struct Client {
    68 	char name[256];
    86 	char name[256];
    69 	int x, y, w, h;
    87 	int x, y, w, h;
    70 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    88 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
    89 		int height;
   107 		int height;
    90 		XFontSet set;
   108 		XFontSet set;
    91 		XFontStruct *xfont;
   109 		XFontStruct *xfont;
    92 	} font;
   110 	} font;
    93 } DC; /* draw context */
   111 } DC; /* draw context */
    94 
       
    95 typedef union {
       
    96 	int i;
       
    97 	uint ui;
       
    98 	float f;
       
    99 	void *v;
       
   100 } Arg;
       
   101 
   112 
   102 typedef struct {
   113 typedef struct {
   103 	uint mod;
   114 	uint mod;
   104 	KeySym keysym;
   115 	KeySym keysym;
   105 	void (*func)(const Arg *);
   116 	void (*func)(const Arg *);
   155 static void keypress(XEvent *e);
   166 static void keypress(XEvent *e);
   156 static void killclient(const Arg *arg);
   167 static void killclient(const Arg *arg);
   157 static void manage(Window w, XWindowAttributes *wa);
   168 static void manage(Window w, XWindowAttributes *wa);
   158 static void mappingnotify(XEvent *e);
   169 static void mappingnotify(XEvent *e);
   159 static void maprequest(XEvent *e);
   170 static void maprequest(XEvent *e);
   160 static void movemouse(Client *c);
   171 static void movemouse(const Arg *arg);
   161 static Client *nexttiled(Client *c);
   172 static Client *nexttiled(Client *c);
   162 static void propertynotify(XEvent *e);
   173 static void propertynotify(XEvent *e);
   163 static void quit(const Arg *arg);
   174 static void quit(const Arg *arg);
   164 static void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
   175 static void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
   165 static void resizemouse(Client *c);
   176 static void resizemouse(const Arg *arg);
   166 static void restack(void);
   177 static void restack(void);
   167 static void run(void);
   178 static void run(void);
   168 static void scan(void);
   179 static void scan(void);
   169 static void setclientstate(Client *c, long state);
   180 static void setclientstate(Client *c, long state);
   170 static void setmfact(const Arg *arg);
   181 static void setmfact(const Arg *arg);
   295 	stack = c;
   306 	stack = c;
   296 }
   307 }
   297 
   308 
   298 void
   309 void
   299 buttonpress(XEvent *e) {
   310 buttonpress(XEvent *e) {
   300 	uint i, mask;
   311 	uint i, x, click;
   301 	int x;
       
   302 	Client *c;
   312 	Client *c;
   303 	XButtonPressedEvent *ev = &e->xbutton;
   313 	XButtonPressedEvent *ev = &e->xbutton;
   304 
   314 
       
   315 	click = ClkRootWin;
   305 	if(ev->window == barwin) {
   316 	if(ev->window == barwin) {
   306 		x = 0;
   317 		x = 0;
   307 		for(i = 0; i < LENGTH(tags); i++) {
   318 		for(i = 0; i < LENGTH(tags) && ev->x >= x; i++) {
   308 			x += TEXTW(tags[i]);
   319 			x += TEXTW(tags[i]);
   309 			if(ev->x < x) {
   320 			if(i < LENGTH(tags) || ev->x <= x)
   310 				mask = 1 << i;
   321 				click = i - 1;
   311 				if(ev->button == Button1) {
   322 			else if(ev->x < x + blw)
   312 					if(ev->state & MODKEY)
   323 				click = ClkLtSymbol;
   313 						tag((Arg*)&mask);
   324 			else if(ev->x > wx + ww - TEXTW(stext))
   314 					else
   325 				click = ClkStatusText;
   315 						view((Arg*)&mask);
   326 			else
   316 				}
   327 				click = ClkWinTitle;
   317 				else if(ev->button == Button3) {
   328 		}
   318 					if(ev->state & MODKEY)
   329 	}
   319 						toggletag((Arg*)&mask);
   330 	else if((c = getclient(ev->window)))
   320 					else
   331 		click = ClkClientWin;
   321 						toggleview((Arg*)&mask);
   332 
   322 				}
   333 	for(i = 0; i < LENGTH(buttons); i++)
   323 				return;
   334 		if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
   324 			}
   335 			buttons[i].func(&buttons[i].arg);
   325 		}
       
   326 		if(ev->x < x + blw) {
       
   327 			if(ev->button == Button1)
       
   328 				togglelayout(NULL);
       
   329 			else if(ev->button == Button3)
       
   330 				togglemax(NULL);
       
   331 		}
       
   332 	}
       
   333 	else if((c = getclient(ev->window))) {
       
   334 		focus(c);
       
   335 		if(CLEANMASK(ev->state) != MODKEY || (ismax && !c->isfixed))
       
   336 			return;
       
   337 		if(ev->button == Button1)
       
   338 			movemouse(c);
       
   339 		else if(ev->button == Button2)
       
   340 			togglefloating(NULL);
       
   341 		else if(ev->button == Button3 && !c->isfixed)
       
   342 			resizemouse(c);
       
   343 	}
       
   344 }
   336 }
   345 
   337 
   346 void
   338 void
   347 checkotherwm(void) {
   339 checkotherwm(void) {
   348 	otherwm = False;
   340 	otherwm = False;
   969 	if(!getclient(ev->window))
   961 	if(!getclient(ev->window))
   970 		manage(ev->window, &wa);
   962 		manage(ev->window, &wa);
   971 }
   963 }
   972 
   964 
   973 void
   965 void
   974 movemouse(Client *c) {
   966 movemouse(const Arg *arg) {
   975 	int x1, y1, ocx, ocy, di, nx, ny;
   967 	int x1, y1, ocx, ocy, di, nx, ny;
   976 	uint dui;
   968 	uint dui;
       
   969 	Client *c;
   977 	Window dummy;
   970 	Window dummy;
   978 	XEvent ev;
   971 	XEvent ev;
   979 
   972 
       
   973 	if(!(c = sel))
       
   974 		return;
   980 	restack();
   975 	restack();
   981 	ocx = nx = c->x;
   976 	ocx = nx = c->x;
   982 	ocy = ny = c->y;
   977 	ocy = ny = c->y;
   983 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
   978 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
   984 	None, cursor[CurMove], CurrentTime) != GrabSuccess)
   979 	None, cursor[CurMove], CurrentTime) != GrabSuccess)
   985 		return;
   980 		return;
   986 	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
   981 	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
       
   982 	if(x1 < c->x || x1 > c->x + c->w || y1 < c->y || y1 > c->y + c->h) {
       
   983 		XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, 0, 0);
       
   984 		x1 = c->x + 1;
       
   985 		y1 = c->y + 1;
       
   986 	}
   987 	for(;;) {
   987 	for(;;) {
   988 		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
   988 		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
   989 		switch (ev.type) {
   989 		switch (ev.type) {
   990 		case ButtonRelease:
   990 		case ButtonRelease:
   991 			XUngrabPointer(dpy, CurrentTime);
   991 			XUngrabPointer(dpy, CurrentTime);
  1129 		XSync(dpy, False);
  1129 		XSync(dpy, False);
  1130 	}
  1130 	}
  1131 }
  1131 }
  1132 
  1132 
  1133 void
  1133 void
  1134 resizemouse(Client *c) {
  1134 resizemouse(const Arg *arg) {
  1135 	int ocx, ocy;
  1135 	int ocx, ocy;
  1136 	int nw, nh;
  1136 	int nw, nh;
       
  1137 	Client *c;
  1137 	XEvent ev;
  1138 	XEvent ev;
  1138 
  1139 
       
  1140 	if(!(c = sel))
       
  1141 		return;
  1139 	restack();
  1142 	restack();
  1140 	ocx = c->x;
  1143 	ocx = c->x;
  1141 	ocy = c->y;
  1144 	ocy = c->y;
  1142 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1145 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
  1143 	None, cursor[CurResize], CurrentTime) != GrabSuccess)
  1146 	None, cursor[CurResize], CurrentTime) != GrabSuccess)
  1375 	/* EWMH support per view */
  1378 	/* EWMH support per view */
  1376 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
  1379 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
  1377 			PropModeReplace, (unsigned char *) netatom, NetLast);
  1380 			PropModeReplace, (unsigned char *) netatom, NetLast);
  1378 
  1381 
  1379 	/* select for events */
  1382 	/* select for events */
  1380 	wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
  1383 	wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask
  1381 			|EnterWindowMask|LeaveWindowMask|StructureNotifyMask;
  1384 			|EnterWindowMask|LeaveWindowMask|StructureNotifyMask;
  1382 	XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
  1385 	XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
  1383 	XSelectInput(dpy, root, wa.event_mask);
  1386 	XSelectInput(dpy, root, wa.event_mask);
  1384 
  1387 
  1385 
  1388 
  1641 }
  1644 }
  1642 
  1645 
  1643 void
  1646 void
  1644 view(const Arg *arg) {
  1647 view(const Arg *arg) {
  1645 	seltags ^= 1; /* toggle sel tagset */
  1648 	seltags ^= 1; /* toggle sel tagset */
  1646 	if(arg && (arg->ui & TAGMASK))
  1649 	if(arg && (arg->ui & TAGMASK) && (arg->ui & TAGMASK) != tagset[seltags ^ 1])
  1647 		tagset[seltags] = arg->i & TAGMASK;
  1650 		tagset[seltags] = arg->i & TAGMASK;
  1648 	arrange();
  1651 	arrange();
  1649 }
  1652 }
  1650 
  1653 
  1651 /* There's no way to check accesses to destroyed windows, thus those cases are
  1654 /* There's no way to check accesses to destroyed windows, thus those cases are