6 #include <sys/select.h>
10 typedef struct IList {
26 void handleevent(XEvent *e);
27 void addicon(Window win);
28 void removeicon(Window win, int unmap);
29 int issystray(Atom *a, int n);
31 Window findclient(Window win);
32 int ignore_errors(Display *d, XErrorEvent *e);
33 void wait_time(unsigned int t);
45 display = XOpenDisplay(NULL);
47 fprintf(stderr, "Could not open display\n");
51 xfd = ConnectionNumber(display);
53 root = RootWindowOfScreen(DefaultScreenOfDisplay(display));
55 winhint = XInternAtom(display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", 0);
56 roothint = XInternAtom(display, "_KDE_NET_SYSTEM_TRAY_WINDOWS", 0);
58 XSelectInput(display, root, SubstructureNotifyMask);
68 while (XPending(display)) {
70 XNextEvent(display, &e);
76 select(xfd + 1, &set, NULL, NULL, NULL);
81 void handleevent(XEvent *e)
90 w = findclient(e->xmap.window);
92 a = XListProperties(display, w, &n);
100 removeicon(e->xunmap.window, True);
103 removeicon(e->xdestroywindow.window, False);
108 int ignore_errors(Display *d, XErrorEvent *e)
114 void addicon(Window win)
118 for (it = list; it; it = it->next)
119 if (it->win == win) return; /* duplicate */
122 list = malloc(sizeof(IList));
124 list->ignore_unmaps = 2;
127 XSelectInput(display, win, StructureNotifyMask);
128 /* if i set the root hint too fast the dock app can fuck itself up */
129 wait_time(1000000 / 8);
133 void removeicon(Window win, int unmap)
135 IList *it, *last = NULL;
138 for (it = list; it; last = it, it = it->next)
139 if (it->win == win) {
140 if (it->ignore_unmaps && unmap) {
148 last->next = it->next;
150 XSync(display, False);
151 old = XSetErrorHandler(ignore_errors);
152 XSelectInput(display, win, NoEventMask);
153 XSync(display, False);
154 XSetErrorHandler(old);
161 int issystray(Atom *a, int n)
165 for (i = 0; i < n; ++i) {
166 if (a[i] == winhint) {
179 for (it = list, n = 0; it; it = it->next, ++n) ;
181 wins = malloc(sizeof(int) * n);
182 for (it = list, i = 0; it; it = it->next, ++i)
186 XChangeProperty(display, root, roothint, XA_WINDOW, 32, PropModeReplace,
187 (unsigned char*) wins, n);
190 Window findclient(Window win)
194 Atom state = XInternAtom(display, "WM_STATE", True);
197 unsigned long ret_items, ret_bytesleft;
198 unsigned long *prop_return;
200 XQueryTree(display, win, &r, &r, &children, &n);
201 for (i = 0; i < n; ++i) {
202 Window w = findclient(children[i]);
207 XGetWindowProperty(display, win, state, 0, 1,
208 False, state, &ret_type, &ret_format,
209 &ret_items, &ret_bytesleft,
210 (unsigned char**) &prop_return);
211 if (ret_type == None || ret_items < 1)
213 return win; /* found it! */
216 void wait_time(unsigned int t)
221 select(1, NULL, NULL, NULL, &time);