1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 kdetrayproxy.c for the Openbox window manager
4 Copyright (c) 2003 Ben Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
20 #include <X11/Xatom.h>
24 #include <sys/select.h>
28 typedef struct IList {
44 void handleevent(XEvent *e);
45 void addicon(Window win);
46 void removeicon(Window win, int unmap);
47 int issystray(Atom *a, int n);
49 Window findclient(Window win);
50 int ignore_errors(Display *d, XErrorEvent *e);
51 void wait_time(unsigned int t);
63 display = XOpenDisplay(NULL);
65 fprintf(stderr, "Could not open display\n");
69 xfd = ConnectionNumber(display);
71 root = RootWindowOfScreen(DefaultScreenOfDisplay(display));
73 winhint = XInternAtom(display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", 0);
74 roothint = XInternAtom(display, "_KDE_NET_SYSTEM_TRAY_WINDOWS", 0);
76 XSelectInput(display, root, SubstructureNotifyMask);
86 while (XPending(display)) {
88 XNextEvent(display, &e);
94 select(xfd + 1, &set, NULL, NULL, NULL);
99 void handleevent(XEvent *e)
108 w = findclient(e->xmap.window);
110 a = XListProperties(display, w, &n);
118 removeicon(e->xunmap.window, True);
121 removeicon(e->xdestroywindow.window, False);
126 int ignore_errors(Display *d, XErrorEvent *e)
132 void addicon(Window win)
136 for (it = list; it; it = it->next)
137 if (it->win == win) return; /* duplicate */
140 list = malloc(sizeof(IList));
142 list->ignore_unmaps = 2;
145 XSelectInput(display, win, StructureNotifyMask);
146 /* if i set the root hint too fast the dock app can fuck itself up */
147 wait_time(1000000 / 8);
151 void removeicon(Window win, int unmap)
153 IList *it, *last = NULL;
154 int (*old)(Display *, XErrorEvent *);
156 for (it = list; it; last = it, it = it->next)
157 if (it->win == win) {
158 if (it->ignore_unmaps && unmap) {
166 last->next = it->next;
168 XSync(display, False);
169 old = XSetErrorHandler(ignore_errors);
170 XSelectInput(display, win, NoEventMask);
171 XSync(display, False);
172 XSetErrorHandler(old);
179 int issystray(Atom *a, int n)
183 for (i = 0; i < n; ++i) {
184 if (a[i] == winhint) {
197 for (it = list, n = 0; it; it = it->next, ++n) ;
199 wins = malloc(sizeof(int) * n);
200 for (it = list, i = 0; it; it = it->next, ++i)
204 XChangeProperty(display, root, roothint, XA_WINDOW, 32, PropModeReplace,
205 (unsigned char*) wins, n);
208 Window findclient(Window win)
212 Atom state = XInternAtom(display, "WM_STATE", True);
215 unsigned long ret_items, ret_bytesleft;
216 unsigned long *prop_return;
218 XQueryTree(display, win, &r, &r, &children, &n);
219 for (i = 0; i < n; ++i) {
220 Window w = findclient(children[i]);
225 XGetWindowProperty(display, win, state, 0, 1,
226 False, state, &ret_type, &ret_format,
227 &ret_items, &ret_bytesleft,
228 (unsigned char**) &prop_return);
229 if (ret_type == None || ret_items < 1)
231 return win; /* found it! */
234 void wait_time(unsigned int t)
239 select(1, NULL, NULL, NULL, &time);