~ubuntu-branches/ubuntu/saucy/stalonetray/saucy

« back to all changes in this revision

Viewing changes to src/main.c

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2009-10-10 02:05:20 UTC
  • mfrom: (1.1.7 upstream) (3.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091010020520-adj6s9i1ujpvzapo
Tags: 0.8.0~beta1-1
* New upstream release
* bump Standards-Version to 3.8.3
* Remove Torsten from Uploaders as requested

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
#include <X11/Xatom.h>
13
13
#include <X11/X.h>
14
14
 
 
15
#include <sys/time.h>
 
16
#include <sys/types.h>
15
17
#include <string.h>
16
18
#include <signal.h>
17
19
#include <stdlib.h>
 
20
#include <unistd.h>
 
21
#include <sys/select.h>
18
22
 
19
23
#include "config.h"
20
24
 
21
25
#ifdef DEBUG
22
 
#include <unistd.h>
23
26
#if defined(HAVE_BACKTRACE)
24
27
        #include <execinfo.h>
25
28
#elif defined(HAVE_PRINTSTACK)
34
37
#include "embed.h"
35
38
#include "xembed.h"
36
39
#include "xutils.h"
 
40
#include "wmh.h"
37
41
 
38
42
#ifndef NO_NATIVE_KDE
39
43
#include "kde_tray.h"
40
44
#endif
41
45
 
42
46
#include "settings.h"
 
47
#include "scrollbars.h"
43
48
#include "tray.h"
44
49
 
45
50
struct TrayData tray_data;
46
 
 
47
51
static int tray_status_requested = 0;
48
52
 
49
53
/****************************
50
54
 * Signal handlers, cleanup
51
55
 ***************************/
52
 
 
53
56
void request_tray_status_on_signal(int sig)
54
57
{
55
 
        psignal(sig, NULL);
56
58
        tray_status_requested = 1;
57
 
        /* This message is not handled, instead it will
58
 
         * force event loop to spin and eventually reach
59
 
         * periodic tasks handler, which will read
60
 
         * tray_status_requestd flag and print out 
61
 
         * tray status */
62
 
        x11_send_client_msg32(tray_data.async_dpy, 
63
 
                        tray_data.tray, 
64
 
                        tray_data.tray, 
65
 
                        tray_data.xa_tray_opcode, 
66
 
                        0, 
67
 
                        STALONE_TRAY_STATUS_REQUESTED,
68
 
                        0, 0, 0);
69
 
        /* Force event delivery */
70
 
        XSync(tray_data.async_dpy, False);
71
59
}
72
60
 
73
61
void cleanup()
74
62
{
75
63
        static int clean = 0;
76
64
        static int cleanup_in_progress = 0;
77
 
 
78
65
        if (!clean && cleanup_in_progress) {
79
 
                ERR(("forced to die\n"));
 
66
                LOG_ERROR(("forced to die\n"));
80
67
                abort();
81
68
        }
82
69
        if (clean) return;
83
70
        cleanup_in_progress = 1;
84
 
        DBG(6, ("start\n"));
85
 
 
86
71
        if (x11_connection_status()) {
87
 
                DBG(8, ("being nice to the icons\n"));
 
72
                LOG_TRACE(("being nice to the icons\n"));
88
73
                /* Clean the list unembedding icons one by one */
89
74
                icon_list_clean_callback(&embedder_unembed);
90
75
                /* Give away the selection */
94
79
                 * process */
95
80
                XSync(tray_data.dpy, False);
96
81
                XCloseDisplay(tray_data.dpy);
97
 
                XCloseDisplay(tray_data.async_dpy);
 
82
                tray_data.dpy = NULL;
98
83
        }
99
84
        cleanup_in_progress = 0;
100
85
        clean = 1;
101
 
        DBG(3, ("done\n"));
102
 
}
103
 
 
104
 
void dump_core_on_signal(int sig)
105
 
{
106
 
#ifdef DEBUG
107
 
# ifdef HAVE_BACKTRACE
108
 
#   define BACKTRACE_LEN        15
109
 
        void *array[BACKTRACE_LEN];
110
 
        size_t size;
111
 
# endif
112
 
#endif
113
 
        psignal(sig, NULL);
114
 
#ifdef DEBUG
115
 
        DBG(0, ("-- backtrace --\n"));
116
 
# if defined(HAVE_BACKTRACE)
117
 
        size = backtrace(array, BACKTRACE_LEN);
118
 
        DBG(0, ("%d stack frames obtained\n", size));
119
 
        DBG(0, ("printing out backtrace\n"));
120
 
        backtrace_symbols_fd(array, size, STDERR_FILENO);
121
 
# elif defined(HAVE_PRINTSTACK)
122
 
        printstack(STDERR_FILENO);
123
 
# endif
124
 
#endif
125
 
        abort();
126
 
}
127
 
 
128
 
void exit_on_signal(int sig)
129
 
{
130
 
        psignal(sig, NULL);
131
 
        /* This is UGLY and is, probably, to be submitted to
132
 
         * Daily WTF, but it is the only way I found not to 
133
 
         * use usleep in main event loop. */
134
 
        DBG(8, ("Sending fake WM_DELETE_WINDOW message\n"));
135
 
        x11_send_client_msg32(tray_data.async_dpy, tray_data.tray, tray_data.tray, tray_data.xa_wm_protocols, tray_data.xa_wm_delete_window, 0, 0, 0, 0);
136
 
        XSync(tray_data.async_dpy, False);
 
86
}
 
87
 
 
88
/**************************************
 
89
 * Helper functions
 
90
 **************************************/
 
91
 
 
92
/* Print tray status */
 
93
void dump_tray_status()
 
94
{
 
95
        int grid_w, grid_h;
 
96
        tray_status_requested = 0;
 
97
        layout_get_size(&grid_w, &grid_h);
 
98
        LOG_INFO(("----------- tray status -----------\n"));
 
99
        LOG_INFO(("active: %s\n", tray_data.is_active ? "yes" : "no"));
 
100
        LOG_INFO(("geometry: %dx%d+%d+%d\n",
 
101
                        tray_data.xsh.width, tray_data.xsh.height,
 
102
                        tray_data.xsh.x, tray_data.xsh.y));
 
103
        if (tray_data.xembed_data.current)
 
104
                LOG_INFO(("XEMBED focus: 0x%x\n", tray_data.xembed_data.current->wid));
 
105
        else
 
106
                LOG_INFO(("XEMBED focus: none\n"));
 
107
        LOG_INFO(("currently managed icons:\n"));
 
108
        icon_list_forall(&print_icon_data);
 
109
        LOG_INFO(("-----------------------------------\n"));
137
110
}
138
111
 
139
112
/**************************************
144
117
void add_icon(Window w, int cmode)
145
118
{
146
119
        struct TrayIcon *ti;
147
 
 
148
120
        /* Aviod adding duplicates */
149
121
        if ((ti = icon_list_find(w)) != NULL) {
150
 
                DBG(4, ("ignoring second request to embed 0x%x (requested cmode=%d, current cmode=%d\n",
151
 
                                        w,
152
 
                                        cmode,
153
 
                                        ti->cmode));
 
122
                LOG_TRACE(("ignoring second request to embed 0x%x"
 
123
                                        "(requested cmode=%d, current cmode=%d\n",
 
124
                                        w, cmode, ti->cmode));
154
125
                return;
155
126
        }
156
127
        /* Dear Edsger W. Dijkstra, I see you behind my back =( */
157
 
        ti = icon_list_new(w, cmode);
158
 
        if (ti == NULL) return;
159
 
 
160
 
#ifdef DEBUG
161
 
        DBG(6, ("starting embedding process for 0x%x with cmode=%d\n", w, cmode));
 
128
        if ((ti = icon_list_new(w, cmode)) == NULL) goto failed0;
 
129
        LOG_TRACE(("starting embedding for icon 0x%x, cmode=%d\n", w, cmode));
162
130
        x11_dump_win_info(tray_data.dpy, w);
163
 
#endif
164
 
 
 
131
        /* Start embedding cycle */
165
132
        if (!xembed_check_support(ti)) goto failed1;
166
 
        
167
133
        if (ti->is_xembed_supported)
168
134
                ti->is_visible = xembed_get_mapped_state(ti);
169
135
        else
170
136
                ti->is_visible = True;
171
 
 
172
137
        if (ti->is_visible) {
173
138
                if (!embedder_reset_size(ti)) goto failed1;
174
139
                if (!layout_add(ti)) goto failed1;
175
140
        }
176
 
        
177
141
        if (!xembed_embed(ti)) goto failed1;
178
142
        if (!embedder_embed(ti)) goto failed2;
179
 
 
180
143
        embedder_update_positions(False);
181
 
        tray_update_window_size();
182
 
 
183
 
        DBG(0, ("0x%x: icon added as %s\n", ti->wid, ti->is_visible ? "visible" : "hidden"));
184
 
#ifdef DEBUG
185
 
        print_icon_data(ti);
186
 
#endif
187
 
        return;
188
 
 
 
144
        tray_update_window_props();
 
145
        /* Report success */
 
146
        LOG_INFO(("added icon %s (wid 0x%x) as %s\n", 
 
147
                        x11_get_window_name(tray_data.dpy, ti->wid, "<unknown>"),
 
148
                        ti->wid, 
 
149
                        ti->is_visible ? "visible" : "hidden"));
 
150
        goto ok;
189
151
failed2:
190
152
        layout_remove(ti);
191
153
failed1:
192
 
#ifdef DEBUG
193
 
        DBG(0, ("0x%x: embedding failed\n", ti->wid));
194
 
        print_icon_data(ti);    
195
 
#endif
196
154
        icon_list_free(ti);
 
155
failed0:
 
156
        LOG_INFO(("failed to add icon %s (wid 0x%x)\n", 
 
157
                        x11_get_window_name(tray_data.dpy, ti->wid, "<unknown>"),
 
158
                        ti->wid));
 
159
ok:
 
160
        if (settings.log_level >= LOG_LEVEL_TRACE) dump_tray_status();
197
161
        return;
198
162
}
199
163
 
201
165
void remove_icon(Window w)
202
166
{
203
167
        struct TrayIcon *ti;
204
 
        
 
168
        char *name;
 
169
        /* Ignore false alarms */
205
170
        if ((ti = icon_list_find(w)) == NULL) return;
206
 
 
 
171
        dump_tray_status();
207
172
        embedder_unembed(ti);
208
173
        xembed_unembed(ti);
209
174
        layout_remove(ti);
210
175
        icon_list_free(ti);
211
 
 
212
 
        DBG(0, ("0x%x: icon removed\n", w));
213
 
 
214
 
        embedder_update_positions(False);
215
 
        tray_update_window_size();
 
176
        LOG_INFO(("removed icon %s (wid 0x%x)\n",
 
177
                                x11_get_window_name(tray_data.dpy, ti->wid, "<unknown>"), 
 
178
                                w));
 
179
        /* no need to call embedde_update_positions(), as
 
180
         * scrollbars_click(SB_WND_MAX) will call it */
 
181
        /* XXX: maybe we need a different name for this
 
182
         * routine instad of passing cryptinc constant? */
 
183
        scrollbars_click(SB_WND_MAX);
 
184
        tray_update_window_props();
 
185
        dump_tray_status();
216
186
}
217
187
 
218
188
/* Track icon visibility state changes */
220
190
{
221
191
        struct TrayIcon *ti;
222
192
        int mapped;
223
 
 
224
193
        /* Ignore false alarms */
225
194
        if ((ti = icon_list_find(w)) == NULL || !ti->is_xembed_supported) return;
226
 
 
227
195
        mapped = xembed_get_mapped_state(ti);
228
 
 
229
 
        DBG(8, ("xembed_is_mapped(0x%x) = %u\n", w, mapped));
230
 
        DBG(8, ("is_visible = %u\n", ti->is_visible));
 
196
        LOG_TRACE(("xembed_is_mapped(0x%x) = %u\n", w, mapped));
 
197
        LOG_TRACE(("is_visible = %u\n", ti->is_visible));
231
198
#ifdef DEBUG
232
199
        x11_dump_win_info(tray_data.dpy, ti->wid);
233
200
#endif
234
 
 
235
201
        /* Nothing has changed */
236
202
        if (mapped == ti->is_visible) return;
237
 
 
238
203
        ti->is_visible = mapped;
239
 
        DBG(0, ("0x%x: %s\n", w, mapped ? "showing" : "hiding"));
240
 
 
 
204
        LOG_INFO(("%s icon 0x%x\n", mapped ? "showing" : "hiding", w));
241
205
        if (mapped) { /* Icon has become mapped and is listed as hidden. Show this icon. */
242
206
                embedder_reset_size(ti);
243
207
                if (!layout_add(ti)) {
250
214
                embedder_hide(ti);
251
215
        }
252
216
        embedder_update_positions(False);
253
 
        tray_update_window_size();
 
217
        tray_update_window_props();
254
218
}
255
219
 
256
220
/* helper to identify invalid icons */
266
230
{
267
231
        unsigned long list_len, i;
268
232
        Window *kde_tray_icons;
269
 
 
270
233
        if (tray_data.kde_tray_old_mode || 
271
234
                !x11_get_root_winlist_prop(tray_data.dpy, tray_data.xa_kde_net_system_tray_windows, 
272
235
                                (unsigned char **) &kde_tray_icons, &list_len)) 
273
236
        {
274
237
                return;
275
238
        }
276
 
 
277
239
        for (i = 0; i < list_len; i++) 
278
240
                /* If the icon is not None and is non old, try to add it
279
241
                 * (if the icon is already there, nothing is gonna happen). */
280
242
                if (kde_tray_icons[i] != None && !kde_tray_is_old_icon(kde_tray_icons[i])) 
281
243
                {
282
 
                        DBG(8, ("(possibly unembedded) KDE icon 0x%x\n", kde_tray_icons[i]));
 
244
                        LOG_TRACE(("found (possibly unembedded) KDE icon %s (wid 0x%x)\n", 
 
245
                                                x11_get_window_name(tray_data.dpy, kde_tray_icons[i], "<unknown>"),
 
246
                                                kde_tray_icons[i]));
283
247
                        add_icon(kde_tray_icons[i], CM_KDE);
284
248
                }
285
 
 
286
249
        XFree(kde_tray_icons);
287
250
}
288
251
#endif
289
252
 
 
253
#define PT_MASK_SB      (1L << 0)
 
254
#define PT_MASK_ALL     PT_MASK_SB
 
255
 
290
256
/* Perform several periodic tasks */
291
 
void perform_periodic_tasks()
 
257
void perform_periodic_tasks(int mask)
292
258
{
293
259
        struct TrayIcon *ti;
294
260
        /* 1. Remove all invalid icons */
295
261
        while ((ti = icon_list_forall(&find_invalid_icons)) != NULL) {
296
 
                DBG(4, ("0x%x is invalid. removing\n", ti->wid));
 
262
                LOG_TRACE(("icon 0x%x is invalid; removing\n", ti->wid));
297
263
                remove_icon(ti->wid);
298
264
        }
299
265
        /* 2. Print tray status if asked to */
300
 
        if (tray_status_requested) {
301
 
                unsigned int grid_w, grid_h;
302
 
                tray_status_requested = 0;
303
 
                layout_get_size(&grid_w, &grid_h);
304
 
 
305
 
#ifdef DEBUG
306
 
#       define SHOWMSG(msg) DBG(0, msg)
307
 
#else
308
 
#       define SHOWMSG(msg)     print_message_to_stderr msg
309
 
#endif
310
 
 
311
 
#ifdef DEBUG
312
 
                trace_mode = 1;
313
 
#endif
314
 
                SHOWMSG(("Someone asked for tray status. Here it comes.\n"));
315
 
                SHOWMSG(("===================================\n"));
316
 
                SHOWMSG(("tray status: %sactive\n", tray_data.is_active ? "" : "not "));
317
 
                SHOWMSG(("grid geometry: %dx%d\n", 
318
 
                                        grid_w / settings.icon_size, 
319
 
                                        grid_h / settings.icon_size));
320
 
                SHOWMSG(("tray geometry: %dx%d+%d+%d\n",
321
 
                                tray_data.xsh.width, tray_data.xsh.height,
322
 
                                tray_data.xsh.x, tray_data.xsh.y));
323
 
#ifdef DEBUG
324
 
                {
325
 
                        XWindowAttributes xwa;
326
 
                        XGetWindowAttributes(tray_data.dpy, tray_data.tray, &xwa);
327
 
                        SHOWMSG(("real tray geometry: %dx%d+%d+%d\n",
328
 
                                                xwa.width, xwa.height, xwa.x, xwa.y));
329
 
                }
330
 
                if (tray_data.xembed_data.current)
331
 
                        SHOWMSG(("icon with focus: 0x%x (pointer %p)\n", tray_data.xembed_data.current->wid, tray_data.xembed_data.current));
332
 
                else
333
 
                        SHOWMSG(("no icon is focused\n"));
334
 
#endif
335
 
                dump_icon_list();
336
 
                SHOWMSG(("===================================\n"));
337
 
#ifdef DEBUG
338
 
                trace_mode = 0;
339
 
#endif
340
 
#undef SHOWMSG
341
 
        }
342
 
        {
 
266
        if (tray_status_requested) dump_tray_status();
 
267
        /* 3. KLUDGE to fix window size on (buggy?) WMs */
 
268
        if (settings.kludge_flags & KLUDGE_FIX_WND_SIZE) {
343
269
                /* KLUDGE TODO: resolve */
344
270
                XWindowAttributes xwa;
345
271
                XGetWindowAttributes(tray_data.dpy, tray_data.tray, &xwa);
346
272
                if (!tray_data.is_reparented && 
347
273
                                (xwa.width != tray_data.xsh.width || xwa.height != tray_data.xsh.height)) 
348
274
                {
349
 
                        DBG(8, ("KLUDGE: fixing window size (current: %dx%d, required: %dx%d)\n",
 
275
                        LOG_TRACE(("KLUDGE: fixing tray window size (current: %dx%d, required: %dx%d)\n",
350
276
                                                xwa.width, xwa.height,
351
277
                                                tray_data.xsh.width, tray_data.xsh.height));
352
 
                        tray_update_window_size();
 
278
                        tray_update_window_props();
353
279
                } 
354
280
        }
 
281
        /* 4. run scrollbars periodic tasks */
 
282
        if (mask & PT_MASK_SB) scrollbars_periodic_tasks();
355
283
}
356
284
 
357
285
/**********************
360
288
 
361
289
void expose(XExposeEvent ev)
362
290
{
363
 
        if (ev.window == tray_data.tray && settings.parent_bg) 
 
291
        if (ev.window == tray_data.tray && settings.parent_bg && ev.count == 0) 
364
292
                tray_refresh_window(False);
365
293
}
366
294
 
367
295
void visibility_notify(XVisibilityEvent ev)
368
296
{
369
 
#if 0 /* Too much flicker, no real benefit :( */
370
 
        if (ev.state == VisibilityUnobscured && ev.window == tray_data.tray) {
371
 
                static int local_state = True;
372
 
                if (local_state) 
373
 
                        tray_refresh_window(False);
374
 
                local_state = !local_state;
375
 
        }
376
 
#endif
377
297
}
378
298
 
379
299
void property_notify(XPropertyEvent ev)
382
302
#if defined(DEBUG) && defined(TRACE_PROPS)
383
303
        char *atom_name;
384
304
        atom_name = XGetAtomName(tray_data.dpy, ev.atom);
385
 
        DBG(6, ("atom = %s\n", atom_name));
 
305
        LOG_TRACE(("atom = %s\n", atom_name));
386
306
        XFree(atom_name);
387
307
#endif
388
308
        /* React on wallpaper change */
397
317
                if (tray_data.is_active) 
398
318
                        kde_icons_update();
399
319
                else 
400
 
                        DBG(6, ("not updating KDE icons list: tray is not active\n"));
 
320
                        LOG_TRACE(("not updating KDE icons list: tray is not active\n"));
401
321
                kde_tray_update_old_icons(tray_data.dpy);
402
322
        }
403
323
#endif
 
324
        /* React on WM (re)starts */
 
325
        if (ev.atom == XInternAtom(tray_data.dpy, _NET_SUPPORTING_WM_CHECK, False)) {
 
326
                ewmh_list_supported_atoms(tray_data.dpy);
 
327
                tray_set_wm_hints();
 
328
                kde_tray_update_fallback_mode(tray_data.dpy);
 
329
        }
404
330
        /* React on _XEMBED_INFO changes of embedded icons
405
331
         * (currently used to track icon visibility status) */
406
332
        if (ev.atom == tray_data.xembed_data.xa_xembed_info) {
421
347
                                        break;
422
348
                                }
423
349
                }
424
 
                DBG(6, ("tray is %sreparented\n", tray_data.is_reparented ? "" : "not "));
 
350
                if (nwindows) XFree(windows);
 
351
                LOG_TRACE(("tray was %sreparented\n", tray_data.is_reparented ? "" : "not "));
425
352
        }
426
353
}
427
354
 
428
355
void reparent_notify(XReparentEvent ev)
429
356
{
430
357
        struct TrayIcon *ti;
431
 
 
432
358
        ti = icon_list_find(ev.window);
433
359
        if (ti == NULL) return;
434
 
 
435
360
        /* Reparenting out of the tray is one of non-destructive
436
361
         * ways to end XEMBED protocol (see spec) */
437
362
        if (ti->is_embedded && ti->mid_parent != ev.parent) {
438
 
                DBG(3, ("initiating unembedding for 0x%x\n", ti->wid));
 
363
                LOG_TRACE(("will now unembed 0x%x\n", ti->wid));
439
364
#ifdef DEBUG
 
365
                print_icon_data(ti);
440
366
                x11_dump_win_info(tray_data.dpy, ev.parent);
441
 
                dump_icon_list();
442
367
#endif
443
368
                remove_icon(ev.window);
444
 
#ifdef DEBUG
445
 
                dump_icon_list();
446
 
#endif
447
369
        }
448
370
}
449
371
 
454
376
#ifdef DEBUG
455
377
        /* Print neat message(s) about this event to aid debugging */
456
378
        char *msg_type_name;
457
 
 
458
379
        msg_type_name = XGetAtomName(tray_data.dpy, ev.message_type);
459
 
 
460
380
        if (msg_type_name != NULL) {
461
 
                DBG(4, ("message \"%s\"\n", msg_type_name));
 
381
                LOG_TRACE(("message \"%s\"\n", msg_type_name));
462
382
                XFree(msg_type_name);
463
383
        }
464
 
 
465
384
        if (ev.message_type == tray_data.xa_wm_protocols) {
466
385
                msg_type_name = XGetAtomName(tray_data.dpy, ev.data.l[0]);
467
386
                if (msg_type_name != NULL) {
468
 
                        DBG(6, ("WM_PROTOCOLS message type: %s\n", msg_type_name));
 
387
                        LOG_TRACE(("WM_PROTOCOLS message type: %s\n", msg_type_name));
469
388
                        XFree(msg_type_name);
470
389
                }
471
390
        }
472
391
#endif
473
 
 
474
392
        /* Graceful exit */
475
393
        if (ev.message_type == tray_data.xa_wm_protocols &&
476
394
                ev.data.l[0] == tray_data.xa_wm_delete_window && 
477
395
                ev.window == tray_data.tray)
478
396
        {
479
 
                DBG(3, ("got WM_DELETE message, will now exit\n"));
 
397
                LOG_TRACE(("got WM_DELETE message, will now exit\n"));
480
398
                exit(0);
481
399
        } 
482
 
 
483
400
        /* Handle _NET_SYSTEM_TRAY_* messages */
484
401
        if (ev.message_type == tray_data.xa_tray_opcode && tray_data.is_active) {
485
 
                DBG(6, ("this is the _NET_SYSTEM_TRAY_OPCODE(%lu) message\n", ev.data.l[1]));
486
 
        
 
402
                LOG_TRACE(("this is the _NET_SYSTEM_TRAY_OPCODE(%lu) message\n", ev.data.l[1]));
487
403
                switch (ev.data.l[1]) {
488
404
                        /* This is the starting point of NET SYSTEM TRAY protocol */
489
405
                        case SYSTEM_TRAY_REQUEST_DOCK:
490
 
                                DBG(3, ("dockin' requested by 0x%x, serving in a moment\n", ev.data.l[2]));
 
406
                                LOG_TRACE(("dockin' requested by window 0x%x, serving in a moment\n", ev.data.l[2]));
491
407
#ifndef NO_NATIVE_KDE
492
408
                                if (kde_tray_check_for_icon(tray_data.dpy, ev.data.l[2])) cmode = CM_KDE;
493
409
                                if (kde_tray_is_old_icon(ev.data.l[2])) kde_tray_old_icons_remove(ev.data.l[2]);
494
410
#endif
495
411
                                add_icon(ev.data.l[2], cmode);
496
412
                                break;
497
 
                        /* This is a special case added by this implementation.
498
 
                         * STALONETRAY_TRAY_DOCK_CONFIRMED is sent by stalonetray 
 
413
                        /* We ignore these messages, since we do not show
 
414
                         * any baloons anyways */
 
415
                        case SYSTEM_TRAY_BEGIN_MESSAGE:
 
416
                        case SYSTEM_TRAY_CANCEL_MESSAGE:
 
417
                                break;
 
418
                        /* Below are special cases added by this implementation */
 
419
                        /* STALONETRAY_TRAY_DOCK_CONFIRMED is sent by stalonetray 
499
420
                         * to itself. (see embed.c) */
500
421
                        case STALONE_TRAY_DOCK_CONFIRMED:
501
422
                                ti = icon_list_find(ev.data.l[2]);
502
423
                                if (ti != NULL && !ti->is_embedded) {
503
424
                                        ti->is_embedded = True;
504
 
                                        DBG(3, ("0x%x: embedding confirmed\n", ti->wid));
 
425
                                        LOG_TRACE(("embedding confirmed for icon 0x%x\n", ti->wid));
505
426
#ifdef DEBUG
506
 
                                        dump_icon_list();
 
427
                                        dump_tray_status();
507
428
#endif
508
429
                                }
509
 
                                tray_update_window_size();
510
 
                                break;
511
 
                        /* We ignore these messages, since we do not show
512
 
                         * any baloons anyways */
513
 
                        case SYSTEM_TRAY_BEGIN_MESSAGE:
514
 
                        case SYSTEM_TRAY_CANCEL_MESSAGE:
 
430
                                tray_update_window_props();
 
431
                                break;
 
432
                        /* Dump tray status on request */
 
433
                        case STALONE_TRAY_STATUS_REQUESTED:
 
434
                                dump_tray_status();
 
435
                                break;
 
436
                        /* Find icon and scroll to it if necessary */
 
437
                        case STALONE_TRAY_REMOTE_CONTROL:
 
438
                                ti = icon_list_find(ev.window);
 
439
                                if (ti == NULL) break;
 
440
                                scrollbars_scroll_to(ti);
 
441
                                break;
515
442
                        default:
516
443
                                break;
517
444
                }
518
445
        }
519
446
#ifdef DEBUG
520
447
        if (ev.message_type == tray_data.xa_tray_opcode && !tray_data.is_active)
521
 
                DBG(6, ("ignoring _NET_SYSTEM_TRAY_OPCODE(%lu) message: tray not active\n", tray_data.is_active));
 
448
                LOG_TRACE(("ignoring _NET_SYSTEM_TRAY_OPCODE(%lu) message because tray is not active\n", tray_data.is_active));
522
449
#endif
523
450
}
524
451
 
544
471
        struct TrayIcon *ti;
545
472
        struct Point sz;
546
473
        XWindowAttributes xwa;
547
 
 
548
474
        if (ev.window == tray_data.tray) {
549
475
                /* Tray window was resized */
550
476
                /* TODO: distinguish between synthetic and real configure notifies */
551
477
                /* TODO: catch rejected configure requests */
552
 
                DBG(8, ("window geometry from event: %ux%u+%d+%d\n", ev.width, ev.height, ev.x, ev.y));
553
 
 
 
478
                /* XXX: Geometry stuff is a mess. Geometry
 
479
                 * is specified in slots, but almost always is 
 
480
                 * stored in pixels... */
 
481
                LOG_TRACE(("tray window geometry from event: %ux%u+%d+%d\n", ev.width, ev.height, ev.x, ev.y));
554
482
                /* Sometimes, configure notifies come too late, so we fetch real geometry ourselves */
555
483
                XGetWindowAttributes(tray_data.dpy, tray_data.tray, &xwa);
556
484
                x11_get_window_abs_coords(tray_data.dpy, tray_data.tray, &tray_data.xsh.x, &tray_data.xsh.y);
557
 
                DBG(8, ("real window geometry: %dx%d+%d+%d\n", xwa.width, xwa.height, tray_data.xsh.x, tray_data.xsh.y));
 
485
                LOG_TRACE(("tray window geometry from X11 calls: %dx%d+%d+%d\n", xwa.width, xwa.height, tray_data.xsh.x, tray_data.xsh.y));
558
486
                tray_data.xsh.width = xwa.width;
559
487
                tray_data.xsh.height = xwa.height;
560
 
 
561
488
                /* Update icons positions */
562
 
                icon_list_forall(&grid2window);
 
489
                /* XXX: internal API is bad. example below */
 
490
                icon_list_forall(&layout_translate_to_window);
563
491
                embedder_update_positions(True);
564
 
 
565
492
                /* Adjust window background if necessary */
566
493
                tray_update_bg(False);
567
494
                tray_refresh_window(True);
568
 
        } else if ((ti = icon_list_find(ev.window)) != NULL) {
569
 
                /* Some icon has resized its window */
570
 
                if (ti->cmode == CM_KDE) {
571
 
                        /* KDE icons are not allowed to change their size. Reset their size. */
 
495
                scrollbars_update();
 
496
        } else if ((ti = icon_list_find(ev.window)) != NULL) { /* Some icon has resized its window */
 
497
                /* KDE icons are not allowed to change their size. Reset icon size. */
 
498
                if (ti->cmode == CM_KDE || settings.kludge_flags & KLUDGE_FORCE_ICONS_SIZE) {
572
499
                        embedder_reset_size(ti);
573
500
                        return;
574
501
                }
 
502
                if (settings.kludge_flags & KLUDGE_FORCE_ICONS_SIZE) return;
575
503
                /* Get new window size */
576
504
                if (!x11_get_window_size(tray_data.dpy, ti->wid, &sz.x, &sz.y)) {
577
505
                        embedder_unembed(ti);
578
506
                        return;
579
507
                }
580
 
                DBG(3, ("icon window 0x%x was resized, new size: %ux%u, old size: %ux%u\n", ev.window, 
 
508
                LOG_TRACE(("icon 0x%x was resized, new size: %ux%u, old size: %ux%u\n", ev.window, 
581
509
                                        sz.x, sz.y, ti->l.wnd_sz.x, ti->l.wnd_sz.y));
582
510
                /* Check if the size has really changed */
583
511
                if (sz.x == ti->l.wnd_sz.x && sz.y == ti->l.wnd_sz.y) return;
584
512
                ti->l.wnd_sz = sz;
585
513
                ti->is_resized = True;
586
514
                /* Do the job */
587
 
#if 0
588
 
                if (layout_handle_icon_resize(ti)) {
589
 
                        embedder_refresh(ti);
590
 
#ifdef DEBUG
591
 
                        print_icon_data(ti);
592
 
#endif
593
 
                        embedder_update_positions(False);
594
 
                        tray_update_window_size();
595
 
                }
596
 
#else
597
515
                layout_handle_icon_resize(ti);
598
516
                embedder_refresh(ti);
599
517
#ifdef DEBUG
600
518
                print_icon_data(ti);
601
519
#endif
602
520
                embedder_update_positions(False);
603
 
                tray_update_window_size();
604
 
#endif
 
521
                tray_update_window_props();
605
522
#ifdef DEBUG
606
 
                dump_icon_list();
 
523
                dump_tray_status();
607
524
#endif
608
525
        }
609
526
}
614
531
        if (ev.selection == tray_data.xa_tray_selection) {
615
532
                /* Is it us who has lost the selection */
616
533
                if (ev.window == tray_data.tray) {
617
 
                        DBG(0, ("stalonetray has lost _NET_WM_SYSTRAY selection; deactivating\n"));
 
534
                        LOG_INFO(("another tray detected; deactivating\n"));
618
535
                        tray_data.is_active = False;
619
536
                        tray_data.old_selection_owner = XGetSelectionOwner(tray_data.dpy, tray_data.xa_tray_selection);
620
537
                        if (!x11_ok()) {
621
 
                                DBG(0, ("could not get new selection owner. re-acquiring selection\n"));
 
538
                                LOG_INFO(("could not find proper new tray; reactivating\n"));
622
539
                                tray_acquire_selection();
623
540
                        };
624
 
                                
625
 
                        DBG(4, ("the new selection owner 0x%x\n", tray_data.old_selection_owner));
 
541
                        LOG_TRACE(("new selection owner is 0x%x\n", tray_data.old_selection_owner));
626
542
                        XSelectInput(tray_data.dpy, tray_data.old_selection_owner, StructureNotifyMask);
627
543
                        return;
628
544
                } else if (!tray_data.is_active) {
629
545
                        /* Someone else has lost selection and tray is not active --- take over the selection */
630
 
                        DBG(0, ("re-reacquiring tray selection\n"));
 
546
                        LOG_INFO(("another tray exited; reactivating\n"));
631
547
                        tray_acquire_selection();
632
548
                } else {
633
549
                        /* Just in case */
634
 
                        DBG(0, ("WEIRD: tray is active and someone else has lost tray selection :s\n"));
 
550
                        LOG_TRACE(("WEIRD: tray is active and someone else has lost tray selection\n"));
635
551
                }
636
552
        }
637
553
}
641
557
#ifndef NO_NATIVE_KDE
642
558
        /* Legacy scheme to handle KDE icons */
643
559
        if (tray_data.kde_tray_old_mode) {
644
 
                Window w = kde_tray_find_icon(tray_data.dpy, ev.window);
645
 
                if (w != None) {
646
 
                        DBG(4, ("Legacy scheme for KDE icons: detected KDE icon 0x%x. Adding.\n", w));
647
 
                        add_icon(w, CM_KDE);
648
 
                        /* TODO: remove some properties to trick ion3 so that it no longer thinks that w is a toplevel. 
649
 
                         * Candidates for removal: 
650
 
                         *      - WM_STATE */
 
560
                struct TrayIcon *ti = icon_list_find_ex(ev.window);
 
561
                if (ti == NULL) {
 
562
                        Window w = kde_tray_find_icon(tray_data.dpy, ev.window);
 
563
                        if (w != None) {
 
564
                                LOG_TRACE(("Legacy scheme for KDE icons: detected KDE icon 0x%x. Adding.\n", w));
 
565
                                add_icon(w, CM_KDE);
 
566
                                /* TODO: remove some properties to trick ion3 so that it no longer thinks that w is a toplevel. 
 
567
                                 * Candidates for removal: 
 
568
                                 *      - WM_STATE */
 
569
                        }
651
570
                }
652
571
        }
653
572
#endif
657
576
{
658
577
        struct TrayIcon *ti;
659
578
        ti = icon_list_find(ev.window);
660
 
        if (ti != NULL && !ti->is_invalid && ti->cmode == CM_KDE) {
661
 
                /* KLUDGE! sometimes KDE icons occasionally 
 
579
        if (ti != NULL && !ti->is_invalid) {
 
580
                /* KLUDGE! sometimes icons occasionally 
662
581
                 * unmap their windows, but do _not_ destroy 
663
582
                 * them. We map those windows back */
664
 
                /* XXX: root cause unidentified */
665
 
                DBG(8, ("Unmap KDE icons KLUDGE for 0x%x\n", ti->wid));
 
583
                /* XXX: not root caused */
 
584
                LOG_TRACE(("Unmap icons KLUDGE executed for 0x%x\n", ti->wid));
666
585
                XMapRaised(tray_data.dpy, ti->wid);
667
586
                if (!x11_ok()) ti->is_invalid = True;
668
587
        }
669
588
}
670
589
 
 
590
void my_usleep(useconds_t usec)
 
591
{
 
592
        struct timeval timeout;
 
593
        fd_set rfds;
 
594
        FD_ZERO(&rfds);
 
595
        timeout.tv_sec = 0;
 
596
        timeout.tv_usec = usec;
 
597
        select(1, &rfds, NULL, NULL, &timeout);
 
598
}
 
599
 
671
600
/*********************************************************/
 
601
/* main() for usual operation */
 
602
int tray_main(int argc, char **argv)
 
603
{
 
604
        XEvent          ev;
 
605
        /* Interpret those settings that need an open display */
 
606
        interpret_settings();
 
607
#ifdef DEBUG
 
608
        ewmh_list_supported_atoms(tray_data.dpy);
 
609
#endif
 
610
        /* Create and show tray window */
 
611
        tray_create_window(argc, argv);
 
612
        tray_acquire_selection();
 
613
        tray_show_window();
 
614
#ifndef NO_NATIVE_KDE
 
615
        kde_tray_init(tray_data.dpy);
 
616
#endif
 
617
        xembed_init();
 
618
#ifndef NO_NATIVE_KDE
 
619
        kde_icons_update();
 
620
#endif
 
621
        /* Main event loop */
 
622
        while ("my guitar gently wheeps") {
 
623
                /* This is ugly and extra dependency. But who cares?
 
624
                 * Rationale: we want to block unless absolutely needed.
 
625
                 * This way we ensure that stalonetray does not show up
 
626
                 * in powertop (i.e. does not eat unnecessary power and
 
627
                 * CPU cycles) 
 
628
                 * Drawback: handling of signals is very limited. XNextEvent()
 
629
                 * does not if signal occurs. This means that graceful
 
630
                 * exit on e.g. Ctrl-C cannot be implemented without hacks. */
 
631
                while (XPending(tray_data.dpy) || tray_data.scrollbars_data.scrollbar_down == -1) {
 
632
                        XNextEvent(tray_data.dpy, &ev);
 
633
                        if (tray_data.terminated) goto bailout;
 
634
                        xembed_handle_event(ev);
 
635
                        scrollbars_handle_event(ev);
 
636
                        switch (ev.type) {
 
637
                        case VisibilityNotify:
 
638
                                LOG_TRACE(("VisibilityNotify (0x%x, state=%d)\n", ev.xvisibility.window, ev.xvisibility.state));
 
639
                                visibility_notify(ev.xvisibility);
 
640
                                break;
 
641
                        case Expose:
 
642
                                LOG_TRACE(("Expose (0x%x)\n", ev.xexpose.window));
 
643
                                expose(ev.xexpose);
 
644
                                break;
 
645
                        case PropertyNotify:
 
646
                                LOG_TRACE(("PropertyNotify(0x%x)\n", ev.xproperty.window));
 
647
                                property_notify(ev.xproperty);
 
648
                                break;
 
649
                        case DestroyNotify:
 
650
                                LOG_TRACE(("DestroyNotify(0x%x)\n", ev.xdestroywindow.window));
 
651
                                destroy_notify(ev.xdestroywindow);
 
652
                                break;
 
653
                        case ClientMessage:
 
654
                                LOG_TRACE(("ClientMessage(from 0x%x?)\n", ev.xclient.window));
 
655
                                client_message(ev.xclient);
 
656
                                break;
 
657
                        case ConfigureNotify:
 
658
                                LOG_TRACE(("ConfigureNotify(0x%x)\n", ev.xconfigure.window));
 
659
                                configure_notify(ev.xconfigure);
 
660
                                break;
 
661
                        case MapNotify:
 
662
                                LOG_TRACE(("MapNotify(0x%x)\n", ev.xmap.window));
 
663
                                map_notify(ev.xmap);
 
664
                                break;
 
665
                        case ReparentNotify:
 
666
                                LOG_TRACE(("ReparentNotify(0x%x to 0x%x)\n", ev.xreparent.window, ev.xreparent.parent));
 
667
                                reparent_notify(ev.xreparent);
 
668
                                break;
 
669
                        case SelectionClear:
 
670
                                LOG_TRACE(("SelectionClear (0x%x has lost selection)\n", ev.xselectionclear.window));
 
671
                                selection_clear(ev.xselectionclear);
 
672
                                break;
 
673
                        case SelectionNotify:
 
674
                                LOG_TRACE(("SelectionNotify\n"));
 
675
                                break;
 
676
                        case SelectionRequest:
 
677
                                LOG_TRACE(("SelectionRequest (from 0x%x to 0x%x)\n", ev.xselectionrequest.requestor, ev.xselectionrequest.owner));
 
678
                                break;
 
679
                        case UnmapNotify:
 
680
                                LOG_TRACE(("UnmapNotify(0x%x)\n", ev.xunmap.window));
 
681
                                unmap_notify(ev.xunmap);
 
682
                                break;
 
683
                        default:
 
684
#if defined(DEBUG) && defined(TRACE_EVENTS)
 
685
                                LOG_TRACE(("Unhandled event: %s, serial: %d, window: 0x%x\n", x11_event_names[ev.type], ev.xany.serial, ev.xany.window));
 
686
#endif
 
687
                                break;
 
688
                        }
 
689
                        /* Perform all periodic tasks but for scrollbars */
 
690
                        perform_periodic_tasks(PT_MASK_ALL & (~PT_MASK_SB));
 
691
                }
 
692
                perform_periodic_tasks(PT_MASK_ALL);
 
693
                my_usleep(500000L);
 
694
        }
 
695
bailout:
 
696
        LOG_TRACE(("Clean exit\n"));
 
697
        return 0;
 
698
}
 
699
 
 
700
/* main() for controlling stalonetray remotely */
 
701
int remote_main(int argc, char **argv)
 
702
{
 
703
        Window tray, icon = None;
 
704
        int rc;
 
705
        int x, y, depth = 0, idummy, i;
 
706
        Window win, root;
 
707
        unsigned int udummy, w, h;
 
708
        tray_init_selection_atoms();
 
709
        tray_create_phony_window();
 
710
        LOG_TRACE(("name=\"%s\" btn=%d cnt=%d x=%d y=%d\n", 
 
711
                                settings.remote_click_name,
 
712
                                settings.remote_click_btn,
 
713
                                settings.remote_click_cnt,
 
714
                                settings.remote_click_pos.x,
 
715
                                settings.remote_click_pos.y));
 
716
        tray = XGetSelectionOwner(tray_data.dpy, tray_data.xa_tray_selection);
 
717
        if (tray == None) return 255;
 
718
        /* 1. find window matching requested name */
 
719
        icon = x11_find_subwindow_by_name(tray_data.dpy, tray, settings.remote_click_name);
 
720
        if (icon == None) return 127;
 
721
        /* 2. form a message to tray requesting it to show the icon */
 
722
        rc = x11_send_client_msg32(tray_data.dpy, /* display */
 
723
                        tray, /* destination */
 
724
                        icon, /* window */ 
 
725
                        tray_data.xa_tray_opcode, /* atom */
 
726
                        0, /* data0 */
 
727
                        STALONE_TRAY_REMOTE_CONTROL, /* data1 */
 
728
                        0, /* data2 */
 
729
                        0, /* data3 */
 
730
                        0 /* data4 */
 
731
                        );
 
732
        if (!rc) return 63;
 
733
        /* 3. Execute the click */
 
734
        /* 3.1. Sort out click position */
 
735
        XGetGeometry(tray_data.dpy, icon, &root, 
 
736
                        &idummy, &idummy, 
 
737
                        &w, &h, &udummy, &udummy);
 
738
        x = (settings.remote_click_pos.x == REMOTE_CLICK_POS_DEFAULT) ? w / 2 : settings.remote_click_pos.x;
 
739
        y = (settings.remote_click_pos.y == REMOTE_CLICK_POS_DEFAULT) ? h / 2 : settings.remote_click_pos.y;
 
740
        /* 3.2. Find subwindow to execute click on */
 
741
        win = x11_find_subwindow_at(tray_data.dpy, icon, x, y, depth);
 
742
        /* 3.3. Send mouse click(s) to target */
 
743
        LOG_TRACE(("wid=0x%x btn=%d x=%d y=%d\n", 
 
744
                                settings.remote_click_name,
 
745
                                win,
 
746
                                settings.remote_click_btn,
 
747
                                settings.remote_click_pos.x,
 
748
                                settings.remote_click_pos.y));
 
749
#define SEND_BTN_EVENT(press, time) do { \
 
750
        x11_send_button(tray_data.dpy, /* dispslay */ \
 
751
                        press, /* event type */ \
 
752
                        win, /* target window */ \
 
753
                        root, /* root window */ \
 
754
                        time, /* time */ \
 
755
                        settings.remote_click_btn, /* button */ \
 
756
                        Button1Mask << (settings.remote_click_btn - 1), /* state mask */ \
 
757
                        x, /* x coord (relative) */ \
 
758
                        y); /* y coord (relative) */ \
 
759
} while (0)
 
760
        for (i = 0; i < settings.remote_click_cnt; i++) {
 
761
                SEND_BTN_EVENT(1, x11_get_server_timestamp(tray_data.dpy, tray_data.tray));
 
762
                SEND_BTN_EVENT(0, x11_get_server_timestamp(tray_data.dpy, tray_data.tray));
 
763
        }
 
764
#undef SEND_BTN_EVENT
 
765
        return 0;
 
766
}
 
767
 
 
768
/* main() */
672
769
int main(int argc, char** argv)
673
770
{
674
 
        XEvent          ev;
675
 
        
676
771
        /* Read settings */
677
772
        tray_init();
678
773
        read_settings(argc, argv);
679
 
 
680
774
        /* Register cleanup and signal handlers */
681
775
        atexit(cleanup);
682
 
 
683
 
        signal(SIGINT,  &exit_on_signal);
684
 
        signal(SIGTERM, &exit_on_signal);
685
 
        signal(SIGHUP,  &exit_on_signal);
686
 
 
687
 
        signal(SIGSEGV, &dump_core_on_signal);
688
 
        signal(SIGQUIT, &dump_core_on_signal);
689
 
 
690
776
        signal(SIGUSR1, &request_tray_status_on_signal);
691
 
        
692
777
        /* Open display */
693
 
        if ((tray_data.dpy = XOpenDisplay(settings.display_str)) == NULL ||
694
 
                (tray_data.async_dpy = XOpenDisplay(settings.display_str)) == NULL)
695
 
        {
 
778
        if ((tray_data.dpy = XOpenDisplay(settings.display_str)) == NULL) 
696
779
                DIE(("could not open display\n"));
697
 
        }
698
 
 
 
780
        else 
 
781
                LOG_TRACE(("Opened dpy %p\n", tray_data.dpy));
699
782
        if (settings.xsync)
700
783
                XSynchronize(tray_data.dpy, True);
701
 
 
702
784
        x11_trap_errors();
703
 
 
704
 
        /* Interpret those settings that need a display */
705
 
        interpret_settings();
706
 
 
707
 
        /* Create and show tray window */
708
 
        tray_create_window(argc, argv);
709
 
        tray_acquire_selection();
710
 
        tray_show_window();
711
 
#ifndef NO_NATIVE_KDE
712
 
        kde_tray_init(tray_data.dpy);
713
 
#endif
714
 
        xembed_init();
715
 
#ifndef NO_NATIVE_KDE
716
 
        kde_icons_update();
717
 
#endif
718
 
 
719
 
        /* Main event loop */
720
 
        while ("my guitar gently wheeps") {
721
 
                XNextEvent(tray_data.dpy, &ev);
722
 
                xembed_handle_event(ev);
723
 
                switch (ev.type) {
724
 
                case VisibilityNotify:
725
 
                        DBG(7, ("VisibilityNotify (0x%x, state=%d)\n", ev.xvisibility.window, ev.xvisibility.state));
726
 
                        visibility_notify(ev.xvisibility);
727
 
                        break;
728
 
                case Expose:
729
 
                        DBG(7, ("Expose (0x%x)\n", ev.xexpose.window));
730
 
                        expose(ev.xexpose);
731
 
                        break;
732
 
                case PropertyNotify:
733
 
                        DBG(7, ("PropertyNotify(0x%x)\n", ev.xproperty.window));
734
 
                        property_notify(ev.xproperty);
735
 
                        break;
736
 
                case DestroyNotify:
737
 
                        DBG(7, ("DestroyNotify(0x%x)\n", ev.xdestroywindow.window));
738
 
                        destroy_notify(ev.xdestroywindow);
739
 
                        break;
740
 
                case ClientMessage:
741
 
                        DBG(5, ("ClientMessage(from 0x%x?)\n", ev.xclient.window));
742
 
                        client_message(ev.xclient);
743
 
                        break;
744
 
                case ConfigureNotify:
745
 
                        DBG(7, ("ConfigureNotify(0x%x)\n", ev.xconfigure.window));
746
 
                        configure_notify(ev.xconfigure);
747
 
                        break;
748
 
                case MapNotify:
749
 
                        DBG(7, ("MapNotify(0x%x)\n", ev.xmap.window));
750
 
                        map_notify(ev.xmap);
751
 
                        break;
752
 
                case ReparentNotify:
753
 
                        DBG(5, ("ReparentNotify(0x%x to 0x%x)\n", ev.xreparent.window, ev.xreparent.parent));
754
 
                        reparent_notify(ev.xreparent);
755
 
                        break;
756
 
                case SelectionClear:
757
 
                        DBG(5, ("SelectionClear (0x%x has lost selection)\n", ev.xselectionclear.window));
758
 
                        selection_clear(ev.xselectionclear);
759
 
                        break;
760
 
                case SelectionNotify:
761
 
                        DBG(5, ("SelectionNotify\n"));
762
 
                        break;
763
 
                case SelectionRequest:
764
 
                        DBG(5, ("SelectionRequest (from 0x%x to 0x%x)\n", ev.xselectionrequest.requestor, ev.xselectionrequest.owner));
765
 
                        break;
766
 
                case UnmapNotify:
767
 
                        DBG(7, ("UnmapNotify(0x%x)\n", ev.xunmap.window));
768
 
                        unmap_notify(ev.xunmap);
769
 
                        break;
770
 
                default:
771
 
#if defined(DEBUG) && defined(TRACE_EVENTS)
772
 
                        DBG(8, ("Unhandled event: %s, serial: %d, window: 0x%x\n", x11_event_names[ev.type], ev.xany.serial, ev.xany.window));
773
 
#endif
774
 
                        break;
775
 
                }
776
 
                perform_periodic_tasks();
777
 
        }
778
 
        return 0;
 
785
        /* Execute proper main() function */
 
786
        if (settings.remote_click_name != NULL) 
 
787
                return remote_main(argc, argv);
 
788
        else
 
789
                return tray_main(argc, argv);
779
790
}
 
791