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