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; |
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 |