6 #include <sys/select.h>
25 void handleevent(XEvent *e);
26 void addicon(Window win);
27 void removeicon(Window win, int unmap);
28 int issystray(Atom *a, int n);
30 Window findclient(Window win);
31 int ignore_errors(Display *d, XErrorEvent *e);
32 void wait_time(unsigned int t);
44 display = XOpenDisplay(NULL);
46 fprintf(stderr, "Could not open display\n");
50 xfd = ConnectionNumber(display);
52 root = RootWindowOfScreen(DefaultScreenOfDisplay(display));
54 winhint = XInternAtom(display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", 0);
55 roothint = XInternAtom(display, "_KDE_NET_SYSTEM_TRAY_WINDOWS", 0);
57 XSelectInput(display, root, SubstructureNotifyMask);
67 while (XPending(display)) {
69 XNextEvent(display, &e);
75 select(xfd + 1, &set, NULL, NULL, NULL);
80 void handleevent(XEvent *e)
89 w = findclient(e->xmap.window);
91 a = XListProperties(display, w, &n);
99 removeicon(e->xunmap.window, True);
102 removeicon(e->xdestroywindow.window, False);
107 int ignore_errors(Display *d, XErrorEvent *e)
113 void addicon(Window win)
117 for (it = list; it; it = it->next)
118 if (it->win == win) return; /* duplicate */
121 list = malloc(sizeof(IList));
123 list->ignore_unmaps = 2;
126 XSelectInput(display, win, StructureNotifyMask);
127 /* if i set the root hint too fast the dock app can fuck itself up */
128 wait_time(1000000 / 8);
132 void removeicon(Window win, int unmap)
134 IList *it, *last = NULL;
137 for (it = list; it; last = it, it = it->next)
138 if (it->win == win) {
139 if (it->ignore_unmaps && unmap) {
147 last->next = it->next;
149 XSync(display, False);
150 old = XSetErrorHandler(ignore_errors);
151 XSelectInput(display, win, NoEventMask);
152 XSync(display, False);
153 XSetErrorHandler(old);
160 int issystray(Atom *a, int n)
164 for (i = 0; i < n; ++i) {
165 if (a[i] == winhint) {
178 for (it = list, n = 0; it; it = it->next, ++n) ;
180 wins = malloc(sizeof(int) * n);
181 for (it = list, i = 0; it; it = it->next, ++i)
184 XChangeProperty(display, root, roothint, XA_WINDOW, 32, PropModeReplace,
185 (unsigned char*) wins, n);
188 Window findclient(Window win)
192 Atom state = XInternAtom(display, "WM_STATE", True);
195 unsigned long ret_items, ret_bytesleft;
196 unsigned long *prop_return;
198 XQueryTree(display, win, &r, &r, &children, &n);
199 for (i = 0; i < n; ++i) {
200 Window w = findclient(children[i]);
205 XGetWindowProperty(display, win, state, 0, 1,
206 False, state, &ret_type, &ret_format,
207 &ret_items, &ret_bytesleft,
208 (unsigned char**) &prop_return);
209 if (ret_type == None || ret_items < 1)
211 return win; /* found it! */
214 void wait_time(unsigned int t)
219 select(1, NULL, NULL, NULL, &time);