95
80
XSync(tray_data.dpy, False);
96
81
XCloseDisplay(tray_data.dpy);
97
XCloseDisplay(tray_data.async_dpy);
99
84
cleanup_in_progress = 0;
104
void dump_core_on_signal(int sig)
107
# ifdef HAVE_BACKTRACE
108
# define BACKTRACE_LEN 15
109
void *array[BACKTRACE_LEN];
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);
128
void exit_on_signal(int sig)
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);
88
/**************************************
90
**************************************/
92
/* Print tray status */
93
void dump_tray_status()
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));
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"));
139
112
/**************************************
144
117
void add_icon(Window w, int cmode)
146
119
struct TrayIcon *ti;
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",
122
LOG_TRACE(("ignoring second request to embed 0x%x"
123
"(requested cmode=%d, current cmode=%d\n",
124
w, cmode, ti->cmode));
156
127
/* Dear Edsger W. Dijkstra, I see you behind my back =( */
157
ti = icon_list_new(w, cmode);
158
if (ti == NULL) return;
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);
131
/* Start embedding cycle */
165
132
if (!xembed_check_support(ti)) goto failed1;
167
133
if (ti->is_xembed_supported)
168
134
ti->is_visible = xembed_get_mapped_state(ti);
170
136
ti->is_visible = True;
172
137
if (ti->is_visible) {
173
138
if (!embedder_reset_size(ti)) goto failed1;
174
139
if (!layout_add(ti)) goto failed1;
177
141
if (!xembed_embed(ti)) goto failed1;
178
142
if (!embedder_embed(ti)) goto failed2;
180
143
embedder_update_positions(False);
181
tray_update_window_size();
183
DBG(0, ("0x%x: icon added as %s\n", ti->wid, ti->is_visible ? "visible" : "hidden"));
144
tray_update_window_props();
146
LOG_INFO(("added icon %s (wid 0x%x) as %s\n",
147
x11_get_window_name(tray_data.dpy, ti->wid, "<unknown>"),
149
ti->is_visible ? "visible" : "hidden"));
190
152
layout_remove(ti);
193
DBG(0, ("0x%x: embedding failed\n", ti->wid));
196
154
icon_list_free(ti);
156
LOG_INFO(("failed to add icon %s (wid 0x%x)\n",
157
x11_get_window_name(tray_data.dpy, ti->wid, "<unknown>"),
160
if (settings.log_level >= LOG_LEVEL_TRACE) dump_tray_status();
267
231
unsigned long list_len, i;
268
232
Window *kde_tray_icons;
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))
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]))
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>"),
283
247
add_icon(kde_tray_icons[i], CM_KDE);
286
249
XFree(kde_tray_icons);
253
#define PT_MASK_SB (1L << 0)
254
#define PT_MASK_ALL PT_MASK_SB
290
256
/* Perform several periodic tasks */
291
void perform_periodic_tasks()
257
void perform_periodic_tasks(int mask)
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);
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);
306
# define SHOWMSG(msg) DBG(0, msg)
308
# define SHOWMSG(msg) print_message_to_stderr msg
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));
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));
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));
333
SHOWMSG(("no icon is focused\n"));
336
SHOWMSG(("===================================\n"));
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))
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();
281
/* 4. run scrollbars periodic tasks */
282
if (mask & PT_MASK_SB) scrollbars_periodic_tasks();
357
285
/**********************
455
377
/* Print neat message(s) about this event to aid debugging */
456
378
char *msg_type_name;
458
379
msg_type_name = XGetAtomName(tray_data.dpy, ev.message_type);
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);
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);
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)
479
DBG(3, ("got WM_DELETE message, will now exit\n"));
397
LOG_TRACE(("got WM_DELETE message, will now exit\n"));
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]));
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]);
495
411
add_icon(ev.data.l[2], cmode);
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:
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));
509
tray_update_window_size();
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();
432
/* Dump tray status on request */
433
case STALONE_TRAY_STATUS_REQUESTED:
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);
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));
544
471
struct TrayIcon *ti;
546
473
XWindowAttributes xwa;
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));
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;
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);
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. */
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);
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);
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;
588
if (layout_handle_icon_resize(ti)) {
589
embedder_refresh(ti);
593
embedder_update_positions(False);
594
tray_update_window_size();
597
515
layout_handle_icon_resize(ti);
598
516
embedder_refresh(ti);
600
518
print_icon_data(ti);
602
520
embedder_update_positions(False);
603
tray_update_window_size();
521
tray_update_window_props();
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;
590
void my_usleep(useconds_t usec)
592
struct timeval timeout;
596
timeout.tv_usec = usec;
597
select(1, &rfds, NULL, NULL, &timeout);
671
600
/*********************************************************/
601
/* main() for usual operation */
602
int tray_main(int argc, char **argv)
605
/* Interpret those settings that need an open display */
606
interpret_settings();
608
ewmh_list_supported_atoms(tray_data.dpy);
610
/* Create and show tray window */
611
tray_create_window(argc, argv);
612
tray_acquire_selection();
614
#ifndef NO_NATIVE_KDE
615
kde_tray_init(tray_data.dpy);
618
#ifndef NO_NATIVE_KDE
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
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);
637
case VisibilityNotify:
638
LOG_TRACE(("VisibilityNotify (0x%x, state=%d)\n", ev.xvisibility.window, ev.xvisibility.state));
639
visibility_notify(ev.xvisibility);
642
LOG_TRACE(("Expose (0x%x)\n", ev.xexpose.window));
646
LOG_TRACE(("PropertyNotify(0x%x)\n", ev.xproperty.window));
647
property_notify(ev.xproperty);
650
LOG_TRACE(("DestroyNotify(0x%x)\n", ev.xdestroywindow.window));
651
destroy_notify(ev.xdestroywindow);
654
LOG_TRACE(("ClientMessage(from 0x%x?)\n", ev.xclient.window));
655
client_message(ev.xclient);
657
case ConfigureNotify:
658
LOG_TRACE(("ConfigureNotify(0x%x)\n", ev.xconfigure.window));
659
configure_notify(ev.xconfigure);
662
LOG_TRACE(("MapNotify(0x%x)\n", ev.xmap.window));
666
LOG_TRACE(("ReparentNotify(0x%x to 0x%x)\n", ev.xreparent.window, ev.xreparent.parent));
667
reparent_notify(ev.xreparent);
670
LOG_TRACE(("SelectionClear (0x%x has lost selection)\n", ev.xselectionclear.window));
671
selection_clear(ev.xselectionclear);
673
case SelectionNotify:
674
LOG_TRACE(("SelectionNotify\n"));
676
case SelectionRequest:
677
LOG_TRACE(("SelectionRequest (from 0x%x to 0x%x)\n", ev.xselectionrequest.requestor, ev.xselectionrequest.owner));
680
LOG_TRACE(("UnmapNotify(0x%x)\n", ev.xunmap.window));
681
unmap_notify(ev.xunmap);
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));
689
/* Perform all periodic tasks but for scrollbars */
690
perform_periodic_tasks(PT_MASK_ALL & (~PT_MASK_SB));
692
perform_periodic_tasks(PT_MASK_ALL);
696
LOG_TRACE(("Clean exit\n"));
700
/* main() for controlling stalonetray remotely */
701
int remote_main(int argc, char **argv)
703
Window tray, icon = None;
705
int x, y, depth = 0, idummy, i;
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 */
725
tray_data.xa_tray_opcode, /* atom */
727
STALONE_TRAY_REMOTE_CONTROL, /* data1 */
733
/* 3. Execute the click */
734
/* 3.1. Sort out click position */
735
XGetGeometry(tray_data.dpy, icon, &root,
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,
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 */ \
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) */ \
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));
764
#undef SEND_BTN_EVENT
672
769
int main(int argc, char** argv)
676
771
/* Read settings */
678
773
read_settings(argc, argv);
680
774
/* Register cleanup and signal handlers */
683
signal(SIGINT, &exit_on_signal);
684
signal(SIGTERM, &exit_on_signal);
685
signal(SIGHUP, &exit_on_signal);
687
signal(SIGSEGV, &dump_core_on_signal);
688
signal(SIGQUIT, &dump_core_on_signal);
690
776
signal(SIGUSR1, &request_tray_status_on_signal);
692
777
/* Open display */
693
if ((tray_data.dpy = XOpenDisplay(settings.display_str)) == NULL ||
694
(tray_data.async_dpy = XOpenDisplay(settings.display_str)) == NULL)
778
if ((tray_data.dpy = XOpenDisplay(settings.display_str)) == NULL)
696
779
DIE(("could not open display\n"));
781
LOG_TRACE(("Opened dpy %p\n", tray_data.dpy));
699
782
if (settings.xsync)
700
783
XSynchronize(tray_data.dpy, True);
702
784
x11_trap_errors();
704
/* Interpret those settings that need a display */
705
interpret_settings();
707
/* Create and show tray window */
708
tray_create_window(argc, argv);
709
tray_acquire_selection();
711
#ifndef NO_NATIVE_KDE
712
kde_tray_init(tray_data.dpy);
715
#ifndef NO_NATIVE_KDE
719
/* Main event loop */
720
while ("my guitar gently wheeps") {
721
XNextEvent(tray_data.dpy, &ev);
722
xembed_handle_event(ev);
724
case VisibilityNotify:
725
DBG(7, ("VisibilityNotify (0x%x, state=%d)\n", ev.xvisibility.window, ev.xvisibility.state));
726
visibility_notify(ev.xvisibility);
729
DBG(7, ("Expose (0x%x)\n", ev.xexpose.window));
733
DBG(7, ("PropertyNotify(0x%x)\n", ev.xproperty.window));
734
property_notify(ev.xproperty);
737
DBG(7, ("DestroyNotify(0x%x)\n", ev.xdestroywindow.window));
738
destroy_notify(ev.xdestroywindow);
741
DBG(5, ("ClientMessage(from 0x%x?)\n", ev.xclient.window));
742
client_message(ev.xclient);
744
case ConfigureNotify:
745
DBG(7, ("ConfigureNotify(0x%x)\n", ev.xconfigure.window));
746
configure_notify(ev.xconfigure);
749
DBG(7, ("MapNotify(0x%x)\n", ev.xmap.window));
753
DBG(5, ("ReparentNotify(0x%x to 0x%x)\n", ev.xreparent.window, ev.xreparent.parent));
754
reparent_notify(ev.xreparent);
757
DBG(5, ("SelectionClear (0x%x has lost selection)\n", ev.xselectionclear.window));
758
selection_clear(ev.xselectionclear);
760
case SelectionNotify:
761
DBG(5, ("SelectionNotify\n"));
763
case SelectionRequest:
764
DBG(5, ("SelectionRequest (from 0x%x to 0x%x)\n", ev.xselectionrequest.requestor, ev.xselectionrequest.owner));
767
DBG(7, ("UnmapNotify(0x%x)\n", ev.xunmap.window));
768
unmap_notify(ev.xunmap);
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));
776
perform_periodic_tasks();
785
/* Execute proper main() function */
786
if (settings.remote_click_name != NULL)
787
return remote_main(argc, argv);
789
return tray_main(argc, argv);