]> Dogcows Code - chaz/tint2/blob - src/systray/docker.c
New import
[chaz/tint2] / src / systray / docker.c
1 #include "version.h"
2 #include "kde.h"
3 #include "icons.h"
4 #include "docker.h"
5 #include "net.h"
6
7 #include <assert.h>
8 #include <signal.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <X11/Xutil.h>
13
14 int argc;
15 char **argv;
16
17 Window win = None, hint_win = None, root = None;
18 gboolean wmaker = FALSE; /* WindowMakerMode!!! wheeee */
19 Display *display = NULL;
20 GSList *icons = NULL;
21 int width = 0, height = 0;
22 int border = 1; /* blank area around icons. must be > 0 */
23 gboolean horizontal = TRUE; /* layout direction */
24 int icon_size = 24; /* width and height of systray icons */
25
26 //static char *display_string = NULL;
27 /* excluding the border. sum of all child apps */
28 static gboolean exit_app = FALSE;
29
30 /*
31 void parse_cmd_line()
32 {
33 int i;
34 gboolean help = FALSE;
35
36 for (i = 1; i < argc; i++) {
37 if (0 == strcasecmp(argv[i], "-display")) {
38 ++i;
39 if (i < argc) {
40 display_string = argv[i];
41 } else {
42 g_printerr("-display requires a parameter\n");
43 help = TRUE;
44 }
45 } else if (0 == strcasecmp(argv[i], "-wmaker")) {
46 wmaker = TRUE;
47 } else if (0 == strcasecmp(argv[i], "-vertical")) {
48 horizontal = FALSE;
49 } else if (0 == strcasecmp(argv[i], "-border")) {
50 ++i;
51
52 if (i < argc) {
53 int b = atoi(argv[i]);
54 if (b > 0) {
55 border = b;
56 } else {
57 g_printerr("-border must be a value greater than 0\n");
58 help = TRUE;
59 }
60 } else {
61 g_printerr("-border requires a parameter\n");
62 help = TRUE;
63 }
64 } else if (0 == strcasecmp(argv[i], "-iconsize")) {
65 ++i;
66 if (i < argc) {
67 int s = atoi(argv[i]);
68 if (s > 0) {
69 icon_size = s;
70 } else {
71 g_printerr("-iconsize must be a value greater than 0\n");
72 help = TRUE;
73 }
74 } else {
75 g_printerr("-iconsize requires a parameter\n");
76 help = TRUE;
77 }
78 } else {
79 if (argv[i][0] == '-')
80 help = TRUE;
81 }
82
83
84 if (help) {
85
86 g_print("%s - version %s\n", argv[0], VERSION);
87 g_print("Copyright 2003, Ben Jansens <ben@orodu.net>\n\n");
88 g_print("Usage: %s [OPTIONS]\n\n", argv[0]);
89 g_print("Options:\n");
90 g_print(" -help Show this help.\n");
91 g_print(" -display DISLPAY The X display to connect to.\n");
92 g_print(" -border The width of the border to put around the\n"
93 " system tray icons. Defaults to 1.\n");
94 g_print(" -vertical Line up the icons vertically. Defaults to\n"
95 " horizontally.\n");
96 g_print(" -wmaker WindowMaker mode. This makes docker a\n"
97 " fixed size (64x64) to appear nicely in\n"
98 " in WindowMaker.\n"
99 " Note: In this mode, you have a fixed\n"
100 " number of icons that docker can hold.\n");
101 g_print(" -iconsize SIZE The size (width and height) to display\n"
102 " icons as in the system tray. Defaults to\n"
103 " 24.\n");
104 exit(1);
105 }
106 }
107 }
108 */
109
110 void create_hint_win()
111 {
112 XWMHints hints;
113 XClassHint classhints;
114
115 hint_win = XCreateSimpleWindow(display, root, 0, 0, 1, 1, 0, 0, 0);
116 assert(hint_win);
117
118 hints.flags = StateHint | WindowGroupHint | IconWindowHint;
119 hints.initial_state = WithdrawnState;
120 hints.window_group = hint_win;
121 hints.icon_window = win;
122
123 classhints.res_name = "docker";
124 classhints.res_class = "Docker";
125
126 XSetWMProperties(display, hint_win, NULL, NULL, argv, argc,
127 NULL, &hints, &classhints);
128
129 XMapWindow(display, hint_win);
130 }
131
132
133 void create_main_window()
134 {
135 XWMHints hints;
136 XTextProperty text;
137 char *name = "Docker";
138
139 /* the border must be > 0 if not in wmaker mode */
140 assert(wmaker || border > 0);
141
142 if (!wmaker)
143 win = XCreateSimpleWindow(display, root, 0, 0,
144 border * 2, border * 2, 0, 0, 0);
145 else
146 win = XCreateSimpleWindow(display, root, 0, 0,
147 64, 64, 0, 0, 0);
148
149 assert(win);
150
151 XStringListToTextProperty(&name, 1, &text);
152 XSetWMName(display, win, &text);
153
154 hints.flags = StateHint;
155 hints.initial_state = WithdrawnState;
156 XSetWMHints(display, win, &hints);
157
158 create_hint_win();
159
160 XSync(display, False);
161 XSetWindowBackgroundPixmap(display, win, ParentRelative);
162 XClearWindow(display, win);
163 }
164
165
166 void reposition_icons()
167 {
168 int x = border + ((width % icon_size) / 2),
169 y = border + ((height % icon_size) / 2);
170 GSList *it;
171
172 for (it = icons; it != NULL; it = g_slist_next(it)) {
173 TrayWindow *traywin = it->data;
174 traywin->x = x;
175 traywin->y = y;
176 XMoveWindow(display, traywin->id, x, y);
177 XSync(display, False);
178 if (wmaker) {
179 x += icon_size;
180 if (x + icon_size > width) {
181 x = border;
182 y += icon_size;
183 }
184 } else if (horizontal)
185 x += icon_size;
186 else
187 y += icon_size;
188 }
189 }
190
191
192 void fix_geometry()
193 {
194 GSList *it;
195
196 /* in wmaker mode we're a fixed size */
197 if (wmaker) return;
198
199 /* find the proper width and height */
200 width = horizontal ? 0 : icon_size;
201 height = horizontal ? icon_size : 0;
202 for (it = icons; it != NULL; it = g_slist_next(it)) {
203 if (horizontal)
204 width += icon_size;
205 else
206 height += icon_size;
207 }
208
209 XResizeWindow(display, win, width + border * 2, height + border * 2);
210 }
211
212
213 void event_loop()
214 {
215 XEvent e;
216 Window cover;
217 GSList *it;
218
219 while (!exit_app) {
220 while (XPending(display)) {
221 XNextEvent(display, &e);
222
223 switch (e.type)
224 {
225 case PropertyNotify:
226 /* systray window list has changed? */
227 if (e.xproperty.atom == kde_systray_prop) {
228 XSelectInput(display, win, NoEventMask);
229 kde_update_icons();
230 XSelectInput(display, win, StructureNotifyMask);
231
232 while (XCheckTypedEvent(display, PropertyNotify, &e));
233 }
234
235 break;
236
237 case ConfigureNotify:
238 if (e.xany.window != win) {
239 /* find the icon it pertains to and beat it into submission */
240 GSList *it;
241
242 for (it = icons; it != NULL; it = g_slist_next(it)) {
243 TrayWindow *traywin = it->data;
244 if (traywin->id == e.xany.window) {
245 XMoveResizeWindow(display, traywin->id, traywin->x, traywin->y,
246 icon_size, icon_size);
247 break;
248 }
249 }
250 break;
251 }
252
253 /* briefly cover the entire containing window, which causes it and
254 all of the icons to refresh their windows. finally, they update
255 themselves when the background of the main window's parent changes.
256 */
257 cover = XCreateSimpleWindow(display, win, 0, 0,
258 border * 2 + width, border * 2 + height,
259 0, 0, 0);
260 XMapWindow(display, cover);
261 XDestroyWindow(display, cover);
262
263 break;
264
265 case ReparentNotify:
266 if (e.xany.window == win) /* reparented to us */
267 break;
268 case UnmapNotify:
269 case DestroyNotify:
270 for (it = icons; it; it = g_slist_next(it)) {
271 if (((TrayWindow*)it->data)->id == e.xany.window) {
272 icon_remove(it);
273 break;
274 }
275 }
276 break;
277
278 case ClientMessage:
279 if (e.xclient.message_type == net_opcode_atom &&
280 e.xclient.format == 32 &&
281 e.xclient.window == net_sel_win)
282 net_message(&e.xclient);
283
284 default:
285 break;
286 }
287 }
288 usleep(500000);
289 }
290
291 /* remove/unparent all the icons */
292 while (icons) {
293 /* do the remove here explicitly, cuz the event handler isn't going to
294 happen anymore. */
295 icon_remove(icons);
296 }
297 }
298
299 /*
300 int main(int c, char **v)
301 {
302 struct sigaction act;
303
304 argc = c; argv = v;
305
306 act.sa_handler = signal_handler;
307 act.sa_flags = 0;
308 sigaction(SIGSEGV, &act, NULL);
309 sigaction(SIGPIPE, &act, NULL);
310 sigaction(SIGFPE, &act, NULL);
311 sigaction(SIGTERM, &act, NULL);
312 sigaction(SIGINT, &act, NULL);
313 sigaction(SIGHUP, &act, NULL);
314
315 parse_cmd_line(argc, argv);
316
317 display = XOpenDisplay(display_string);
318 if (!display) {
319 g_printerr("Unable to open Display %s. Exiting.\n",
320 DisplayString(display_string));
321 }
322
323 root = RootWindow(display, DefaultScreen(display));
324 assert(root);
325
326 if (wmaker)
327 width = height = 64 - border * 2;
328
329 create_main_window();
330
331 // set up to find KDE systray icons, and get any that already exist
332 kde_init();
333
334 net_init();
335
336 // we want to get ConfigureNotify events, and assume our parent's background
337 // has changed when we do, so we need to refresh ourself to match
338 XSelectInput(display, win, StructureNotifyMask);
339
340 event_loop();
341
342 XCloseDisplay(display);
343
344 return 0;
345 }
346 */
This page took 0.047018 seconds and 4 git commands to generate.