]> Dogcows Code - chaz/openbox/blob - tools/kdetrayproxy/kdetrayproxy.c
31a4d97488de9e75ff11ba75095d124b62fe240a
[chaz/openbox] / tools / kdetrayproxy / kdetrayproxy.c
1 #include <X11/Xlib.h>
2 #include <X11/Xatom.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/select.h>
7 #include <unistd.h>
8
9 typedef struct IList {
10 Window win;
11 int ignore_unmaps;
12
13 struct IList *next;
14 } IList;
15
16 Display *display;
17 Window root;
18 Atom winhint;
19 Atom roothint;
20 int xfd;
21 IList *list;
22
23 void init();
24 void eventloop();
25 void handleevent(XEvent *e);
26 void addicon(Window win);
27 void removeicon(Window win, int unmap);
28 int issystray(Atom *a, int n);
29 void updatehint();
30 Window findclient(Window win);
31 int ignore_errors(Display *d, XErrorEvent *e);
32 void wait_time(unsigned int t);
33
34 int main()
35 {
36 init();
37 updatehint();
38 eventloop();
39 return 0;
40 }
41
42 void init()
43 {
44 display = XOpenDisplay(NULL);
45 if (!display) {
46 fprintf(stderr, "Could not open display\n");
47 exit(EXIT_FAILURE);
48 }
49
50 xfd = ConnectionNumber(display);
51
52 root = RootWindowOfScreen(DefaultScreenOfDisplay(display));
53
54 winhint = XInternAtom(display, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", 0);
55 roothint = XInternAtom(display, "_KDE_NET_SYSTEM_TRAY_WINDOWS", 0);
56
57 XSelectInput(display, root, SubstructureNotifyMask);
58 }
59
60 void eventloop()
61 {
62 XEvent e;
63 fd_set set;
64
65 while (1) {
66 int event = False;
67 while (XPending(display)) {
68 event = True;
69 XNextEvent(display, &e);
70 handleevent(&e);
71 }
72 if (!event) {
73 FD_ZERO(&set);
74 FD_SET(xfd, &set);
75 select(xfd + 1, &set, NULL, NULL, NULL);
76 }
77 }
78 }
79
80 void handleevent(XEvent *e)
81 {
82 switch (e->type) {
83 case MapNotify:
84 {
85 Atom *a;
86 int n;
87 Window w;
88
89 w = findclient(e->xmap.window);
90 if (w) {
91 a = XListProperties(display, w, &n);
92 if (issystray(a, n))
93 addicon(w);
94 XFree(a);
95 }
96 break;
97 }
98 case UnmapNotify:
99 removeicon(e->xunmap.window, True);
100 break;
101 case DestroyNotify:
102 removeicon(e->xdestroywindow.window, False);
103 break;
104 }
105 }
106
107 int ignore_errors(Display *d, XErrorEvent *e)
108 {
109 (void)d; (void)e;
110 return 1;
111 }
112
113 void addicon(Window win)
114 {
115 IList *it;
116
117 for (it = list; it; it = it->next)
118 if (it->win == win) return; /* duplicate */
119
120 it = list;
121 list = malloc(sizeof(IList));
122 list->win = win;
123 list->ignore_unmaps = 2;
124 list->next = it;
125
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);
129 updatehint();
130 }
131
132 void removeicon(Window win, int unmap)
133 {
134 IList *it, *last = NULL;
135 void *old;
136
137 for (it = list; it; last = it, it = it->next)
138 if (it->win == win) {
139 if (it->ignore_unmaps && unmap) {
140 it->ignore_unmaps--;
141 return;
142 }
143
144 if (!last)
145 list = it->next;
146 else
147 last->next = it->next;
148
149 XSync(display, False);
150 old = XSetErrorHandler(ignore_errors);
151 XSelectInput(display, win, NoEventMask);
152 XSync(display, False);
153 XSetErrorHandler(old);
154 free(it);
155
156 updatehint();
157 }
158 }
159
160 int issystray(Atom *a, int n)
161 {
162 int i, r = False;
163
164 for (i = 0; i < n; ++i) {
165 if (a[i] == winhint) {
166 r = True;
167 break;
168 }
169 }
170 return r;
171 }
172
173 void updatehint()
174 {
175 IList *it;
176 int *wins, n, i;
177
178 for (it = list, n = 0; it; it = it->next, ++n) ;
179 if (n) {
180 wins = malloc(sizeof(int) * n);
181 for (it = list, i = 0; it; it = it->next, ++i)
182 wins[i] = it->win;
183 }
184 XChangeProperty(display, root, roothint, XA_WINDOW, 32, PropModeReplace,
185 (unsigned char*) wins, n);
186 }
187
188 Window findclient(Window win)
189 {
190 Window r, *children;
191 unsigned int n, i;
192 Atom state = XInternAtom(display, "WM_STATE", True);
193 Atom ret_type;
194 int ret_format;
195 unsigned long ret_items, ret_bytesleft;
196 unsigned long *prop_return;
197
198 XQueryTree(display, win, &r, &r, &children, &n);
199 for (i = 0; i < n; ++i) {
200 Window w = findclient(children[i]);
201 if (w) return w;
202 }
203
204 /* try me */
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)
210 return None;
211 return win; /* found it! */
212 }
213
214 void wait_time(unsigned int t)
215 {
216 struct timeval time;
217 time.tv_sec = 0;
218 time.tv_usec = t;
219 select(1, NULL, NULL, NULL, &time);
220 }
This page took 0.046998 seconds and 3 git commands to generate.