172 static void enternotify(XEvent *e); |
171 static void enternotify(XEvent *e); |
173 static void expose(XEvent *e); |
172 static void expose(XEvent *e); |
174 static void focus(Client *c); |
173 static void focus(Client *c); |
175 static void focusin(XEvent *e); |
174 static void focusin(XEvent *e); |
176 static void focusstack(const Arg *arg); |
175 static void focusstack(const Arg *arg); |
177 static Client *getclient(Window w); |
|
178 static unsigned long getcolor(const char *colstr); |
176 static unsigned long getcolor(const char *colstr); |
179 static Monitor *getmon(Window w); |
|
180 static Monitor *getmonn(unsigned int n); |
|
181 static Monitor *getmonxy(int x, int y); |
|
182 static Bool getrootpointer(int *x, int *y); |
177 static Bool getrootpointer(int *x, int *y); |
183 static long getstate(Window w); |
178 static long getstate(Window w); |
184 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
179 static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size); |
185 static void grabbuttons(Client *c, Bool focused); |
180 static void grabbuttons(Client *c, Bool focused); |
186 static void grabkeys(void); |
181 static void grabkeys(void); |
|
182 static Monitor *idxtomon(unsigned int n); |
187 static void initfont(const char *fontstr); |
183 static void initfont(const char *fontstr); |
188 static Bool isprotodel(Client *c); |
184 static Bool isprotodel(Client *c); |
189 static void keypress(XEvent *e); |
185 static void keypress(XEvent *e); |
190 static void killclient(const Arg *arg); |
186 static void killclient(const Arg *arg); |
191 static void manage(Window w, XWindowAttributes *wa); |
187 static void manage(Window w, XWindowAttributes *wa); |
192 static void mappingnotify(XEvent *e); |
188 static void mappingnotify(XEvent *e); |
193 static void maprequest(XEvent *e); |
189 static void maprequest(XEvent *e); |
194 static void monocle(Monitor *m); |
190 static void monocle(Monitor *m); |
195 static void movemouse(const Arg *arg); |
191 static void movemouse(const Arg *arg); |
196 static Client *nexttiled(Client *c); |
192 static Client *nexttiled(Client *c); |
|
193 static Monitor *pointertomon(int x, int y); |
197 static void propertynotify(XEvent *e); |
194 static void propertynotify(XEvent *e); |
198 static void quit(const Arg *arg); |
195 static void quit(const Arg *arg); |
199 static void resize(Client *c, int x, int y, int w, int h); |
196 static void resize(Client *c, int x, int y, int w, int h); |
200 static void resizemouse(const Arg *arg); |
197 static void resizemouse(const Arg *arg); |
201 static void restack(Monitor *m); |
198 static void restack(Monitor *m); |
226 static void updatesizehints(Client *c); |
223 static void updatesizehints(Client *c); |
227 static void updatestatus(void); |
224 static void updatestatus(void); |
228 static void updatetitle(Client *c); |
225 static void updatetitle(Client *c); |
229 static void updatewmhints(Client *c); |
226 static void updatewmhints(Client *c); |
230 static void view(const Arg *arg); |
227 static void view(const Arg *arg); |
|
228 static Client *wintoclient(Window w); |
|
229 static Monitor *wintomon(Window w); |
231 static int xerror(Display *dpy, XErrorEvent *ee); |
230 static int xerror(Display *dpy, XErrorEvent *ee); |
232 static int xerrordummy(Display *dpy, XErrorEvent *ee); |
231 static int xerrordummy(Display *dpy, XErrorEvent *ee); |
233 static int xerrorstart(Display *dpy, XErrorEvent *ee); |
232 static int xerrorstart(Display *dpy, XErrorEvent *ee); |
234 static void zoom(const Arg *arg); |
233 static void zoom(const Arg *arg); |
235 #ifdef XINERAMA |
234 #ifdef XINERAMA |
837 focus(c); |
839 focus(c); |
838 restack(selmon); |
840 restack(selmon); |
839 } |
841 } |
840 } |
842 } |
841 |
843 |
842 Client * |
|
843 getclient(Window w) { |
|
844 Client *c; |
|
845 Monitor *m; |
|
846 |
|
847 for(m = mons; m; m = m->next) |
|
848 for(c = m->clients; c; c = c->next) |
|
849 if(c->win == w) |
|
850 return c; |
|
851 return NULL; |
|
852 } |
|
853 |
|
854 unsigned long |
844 unsigned long |
855 getcolor(const char *colstr) { |
845 getcolor(const char *colstr) { |
856 Colormap cmap = DefaultColormap(dpy, screen); |
846 Colormap cmap = DefaultColormap(dpy, screen); |
857 XColor color; |
847 XColor color; |
858 |
848 |
859 if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) |
849 if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) |
860 die("error, cannot allocate color '%s'\n", colstr); |
850 die("error, cannot allocate color '%s'\n", colstr); |
861 return color.pixel; |
851 return color.pixel; |
862 } |
|
863 |
|
864 Monitor * |
|
865 getmon(Window w) { |
|
866 int x, y; |
|
867 Client *c; |
|
868 Monitor *m; |
|
869 |
|
870 if(w == root && getrootpointer(&x, &y)) |
|
871 return getmonxy(x, y); |
|
872 for(m = mons; m; m = m->next) |
|
873 if(w == m->barwin) |
|
874 return m; |
|
875 if((c = getclient(w))) |
|
876 return c->mon; |
|
877 return mons; |
|
878 } |
|
879 |
|
880 Monitor * |
|
881 getmonn(unsigned int n) { |
|
882 unsigned int i; |
|
883 Monitor *m; |
|
884 |
|
885 for(m = mons, i = 0; m && i != n; m = m->next, i++); |
|
886 return m; |
|
887 } |
|
888 |
|
889 Monitor * |
|
890 getmonxy(int x, int y) { |
|
891 Monitor *m; |
|
892 |
|
893 for(m = mons; m; m = m->next) |
|
894 if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh)) |
|
895 return m; |
|
896 return mons; |
|
897 } |
852 } |
898 |
853 |
899 Bool |
854 Bool |
900 getrootpointer(int *x, int *y) { |
855 getrootpointer(int *x, int *y) { |
901 int di; |
856 int di; |
1223 nexttiled(Client *c) { |
1187 nexttiled(Client *c) { |
1224 for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); |
1188 for(; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); |
1225 return c; |
1189 return c; |
1226 } |
1190 } |
1227 |
1191 |
|
1192 Monitor * |
|
1193 pointertomon(int x, int y) { |
|
1194 Monitor *m; |
|
1195 |
|
1196 for(m = mons; m; m = m->next) |
|
1197 if(INRECT(x, y, m->wx, m->wy, m->ww, m->wh)) |
|
1198 return m; |
|
1199 return mons; |
|
1200 } |
|
1201 |
1228 void |
1202 void |
1229 propertynotify(XEvent *e) { |
1203 propertynotify(XEvent *e) { |
1230 Client *c; |
1204 Client *c; |
1231 Window trans; |
1205 Window trans; |
1232 XPropertyEvent *ev = &e->xproperty; |
1206 XPropertyEvent *ev = &e->xproperty; |
1233 |
1207 |
1234 if((ev->window == root) && (ev->atom == XA_WM_NAME)) |
1208 if((ev->window == root) && (ev->atom == XA_WM_NAME)) |
1235 updatestatus(); |
1209 updatestatus(); |
1236 else if(ev->state == PropertyDelete) |
1210 else if(ev->state == PropertyDelete) |
1237 return; /* ignore */ |
1211 return; /* ignore */ |
1238 else if((c = getclient(ev->window))) { |
1212 else if((c = wintoclient(ev->window))) { |
1239 switch (ev->atom) { |
1213 switch (ev->atom) { |
1240 default: break; |
1214 default: break; |
1241 case XA_WM_TRANSIENT_FOR: |
1215 case XA_WM_TRANSIENT_FOR: |
1242 XGetTransientForHint(dpy, c->win, &trans); |
1216 XGetTransientForHint(dpy, c->win, &trans); |
1243 if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL))) |
1217 if(!c->isfloating && (c->isfloating = (wintoclient(trans) != NULL))) |
1244 arrange(); |
1218 arrange(); |
1245 break; |
1219 break; |
1246 case XA_WM_NORMAL_HINTS: |
1220 case XA_WM_NORMAL_HINTS: |
1247 updatesizehints(c); |
1221 updatesizehints(c); |
1248 break; |
1222 break; |
1322 } |
1296 } |
1323 while(ev.type != ButtonRelease); |
1297 while(ev.type != ButtonRelease); |
1324 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); |
1298 XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); |
1325 XUngrabPointer(dpy, CurrentTime); |
1299 XUngrabPointer(dpy, CurrentTime); |
1326 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1300 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev)); |
1327 if((m = getmonxy(c->x + c->w / 2, c->y + c->h / 2)) != selmon) { |
1301 if((m = pointertomon(c->x + c->w / 2, c->y + c->h / 2)) != selmon) { |
1328 sendmon(c, m); |
1302 sendmon(c, m); |
1329 selmon = m; |
1303 selmon = m; |
1330 focus(NULL); |
1304 focus(NULL); |
1331 } |
1305 } |
1332 } |
1306 } |
1668 XGrabServer(dpy); |
1642 XGrabServer(dpy); |
1669 XSetErrorHandler(xerrordummy); |
1643 XSetErrorHandler(xerrordummy); |
1670 XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ |
1644 XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ |
1671 detach(c); |
1645 detach(c); |
1672 detachstack(c); |
1646 detachstack(c); |
1673 if(c->mon->sel == c) { |
|
1674 /* TODO: consider separate the next code into a function or into detachstack? */ |
|
1675 Client *tc; |
|
1676 for(tc = c->mon->stack; tc && !ISVISIBLE(tc); tc = tc->snext); |
|
1677 c->mon->sel = tc; |
|
1678 focus(NULL); |
|
1679 } |
|
1680 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
1647 XUngrabButton(dpy, AnyButton, AnyModifier, c->win); |
1681 setclientstate(c, WithdrawnState); |
1648 setclientstate(c, WithdrawnState); |
1682 free(c); |
1649 free(c); |
1683 XSync(dpy, False); |
1650 XSync(dpy, False); |
1684 XSetErrorHandler(xerror); |
1651 XSetErrorHandler(xerror); |
1685 XUngrabServer(dpy); |
1652 XUngrabServer(dpy); |
|
1653 focus(NULL); |
1686 arrange(); |
1654 arrange(); |
1687 } |
1655 } |
1688 |
1656 |
1689 void |
1657 void |
1690 unmapnotify(XEvent *e) { |
1658 unmapnotify(XEvent *e) { |
1691 Client *c; |
1659 Client *c; |
1692 XUnmapEvent *ev = &e->xunmap; |
1660 XUnmapEvent *ev = &e->xunmap; |
1693 |
1661 |
1694 if((c = getclient(ev->window))) |
1662 if((c = wintoclient(ev->window))) |
1695 unmanage(c); |
1663 unmanage(c); |
1696 } |
1664 } |
1697 |
1665 |
1698 void |
1666 void |
1699 updatebars(void) { |
1667 updatebars(void) { |
1731 updategeom(void) { |
1699 updategeom(void) { |
1732 int i, n = 1; |
1700 int i, n = 1; |
1733 Client *c; |
1701 Client *c; |
1734 Monitor *newmons = NULL, *m, *tm; |
1702 Monitor *newmons = NULL, *m, *tm; |
1735 |
1703 |
1736 #ifdef XINULATOR |
1704 #ifdef XINERAMA |
1737 n = 2; |
|
1738 #elif defined(XINERAMA) |
|
1739 XineramaScreenInfo *info = NULL; |
1705 XineramaScreenInfo *info = NULL; |
1740 |
1706 |
1741 if(XineramaIsActive(dpy)) |
1707 if(XineramaIsActive(dpy)) |
1742 info = XineramaQueryScreens(dpy, &n); |
1708 info = XineramaQueryScreens(dpy, &n); |
1743 #endif |
1709 #endif /* XINERAMA */ |
1744 /* allocate monitor(s) for the new geometry setup */ |
1710 /* allocate monitor(s) for the new geometry setup */ |
1745 for(i = 0; i < n; i++) { |
1711 for(i = 0; i < n; i++) { |
1746 m = (Monitor *)malloc(sizeof(Monitor)); |
1712 m = (Monitor *)malloc(sizeof(Monitor)); |
1747 m->next = newmons; |
1713 m->next = newmons; |
1748 newmons = m; |
1714 newmons = m; |
1749 } |
1715 } |
1750 |
1716 |
1751 /* initialise monitor(s) */ |
1717 /* initialise monitor(s) */ |
1752 #ifdef XINULATOR |
1718 #ifdef XINERAMA |
1753 if(1) { |
|
1754 m = newmons; |
|
1755 m->screen_number = 0; |
|
1756 m->wx = sx; |
|
1757 m->my = m->wy = sy; |
|
1758 m->ww = sw; |
|
1759 m->mh = m->wh = sh / 2; |
|
1760 m = newmons->next; |
|
1761 m->screen_number = 1; |
|
1762 m->wx = sx; |
|
1763 m->my = m->wy = sy + sh / 2; |
|
1764 m->ww = sw; |
|
1765 m->mh = m->wh = sh / 2; |
|
1766 } |
|
1767 else |
|
1768 #elif defined(XINERAMA) |
|
1769 if(XineramaIsActive(dpy)) { |
1719 if(XineramaIsActive(dpy)) { |
1770 for(i = 0, m = newmons; m; m = m->next, i++) { |
1720 for(i = 0, m = newmons; m; m = m->next, i++) { |
1771 m->screen_number = info[i].screen_number; |
1721 m->screen_number = info[i].screen_number; |
1772 m->mx = m->wx = info[i].x_org; |
1722 m->mx = m->wx = info[i].x_org; |
1773 m->my = m->wy = info[i].y_org; |
1723 m->my = m->wy = info[i].y_org; |
1919 return; |
1866 return; |
1920 selmon->seltags ^= 1; /* toggle sel tagset */ |
1867 selmon->seltags ^= 1; /* toggle sel tagset */ |
1921 if(arg->ui & TAGMASK) |
1868 if(arg->ui & TAGMASK) |
1922 selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; |
1869 selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; |
1923 arrange(); |
1870 arrange(); |
|
1871 } |
|
1872 |
|
1873 Client * |
|
1874 wintoclient(Window w) { |
|
1875 Client *c; |
|
1876 Monitor *m; |
|
1877 |
|
1878 for(m = mons; m; m = m->next) |
|
1879 for(c = m->clients; c; c = c->next) |
|
1880 if(c->win == w) |
|
1881 return c; |
|
1882 return NULL; |
|
1883 } |
|
1884 |
|
1885 Monitor * |
|
1886 wintomon(Window w) { |
|
1887 int x, y; |
|
1888 Client *c; |
|
1889 Monitor *m; |
|
1890 |
|
1891 if(w == root && getrootpointer(&x, &y)) |
|
1892 return pointertomon(x, y); |
|
1893 for(m = mons; m; m = m->next) |
|
1894 if(w == m->barwin) |
|
1895 return m; |
|
1896 if((c = wintoclient(w))) |
|
1897 return c->mon; |
|
1898 return mons; |
1924 } |
1899 } |
1925 |
1900 |
1926 /* There's no way to check accesses to destroyed windows, thus those cases are |
1901 /* There's no way to check accesses to destroyed windows, thus those cases are |
1927 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs |
1902 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs |
1928 * default error handler, which may call exit. */ |
1903 * default error handler, which may call exit. */ |