+
+ // thanks to AngryLlama for the timer
+ // Create a File Description Set containing x11_fd, and every timer_fd
+ FD_ZERO (&fdset);
+ FD_SET (x11_fd, &fdset);
+ int max_fd = x11_fd;
+ timer_iter = timer_list;
+ while (timer_iter) {
+ timer = timer_iter->data;
+ max_fd = timer->id > max_fd ? timer->id : max_fd;
+ FD_SET(timer->id, &fdset);
+ timer_iter = timer_iter->next;
+ }
+
+ // Wait for X Event or a Timer
+ if (pselect(max_fd+1, &fdset, 0, 0, 0, &empty_mask) > 0) {
+ while (XPending (server.dsp)) {
+ XNextEvent(server.dsp, &e);
+
+ switch (e.type) {
+ case ButtonPress:
+ tooltip_hide();
+ event_button_press (&e);
+ break;
+
+ case ButtonRelease:
+ event_button_release(&e);
+ break;
+
+ case MotionNotify: {
+ if (!g_tooltip.enabled) break;
+ Panel* panel = get_panel(e.xmotion.window);
+ Area* area = click_area(panel, e.xmotion.x, e.xmotion.y);
+ if (area->_get_tooltip_text) {
+ tooltip_trigger_show(area, panel, e.xmotion.x_root, e.xmotion.y_root);
+ }
+ else
+ tooltip_trigger_hide();
+ break;
+ }
+
+ case LeaveNotify:
+ tooltip_trigger_hide();
+ break;
+
+ case Expose:
+ event_expose(&e);
+ break;
+
+ case MapNotify:
+ if (e.xany.window == g_tooltip.window)
+ tooltip_update();
+ break;
+
+ case PropertyNotify:
+ event_property_notify(&e);
+ break;
+
+ case ConfigureNotify:
+ event_configure_notify (e.xconfigure.window);
+ break;
+
+ case ReparentNotify:
+ if (!systray_enabled)
+ break;
+ panel = (Panel*)systray.area.panel;
+ if (e.xany.window == panel->main_win) // reparented to us
+ break;
+ // FIXME: 'reparent to us' badly detected => disabled
+ break;
+ case UnmapNotify:
+ case DestroyNotify:
+ if (e.xany.window == g_tooltip.window || !systray.area.on_screen)
+ break;
+ for (it = systray.list_icons; it; it = g_slist_next(it)) {
+ if (((TrayWindow*)it->data)->id == e.xany.window) {
+ remove_icon((TrayWindow*)it->data);
+ break;
+ }
+ }
+ break;
+
+ case ClientMessage:
+ if (!systray.area.on_screen) break;
+ if (e.xclient.message_type == server.atom._NET_SYSTEM_TRAY_OPCODE && e.xclient.format == 32 && e.xclient.window == net_sel_win) {
+ net_message(&e.xclient);
+ }
+ else if (e.xclient.message_type == server.atom.XdndPosition) {
+ dnd_message(&e.xclient);
+ }
+ break;
+ }
+ }
+
+ // we need to iterate over the whole timer list, since fd_set can only be checked with the
+ // brute force method FD_ISSET for every possible timer
+ timer_iter = timer_list;
+ while (timer_iter) {
+ timer = timer_iter->data;
+ if (FD_ISSET(timer->id, &fdset)) {
+ uint64_t dummy;
+ read(timer->id, &dummy, sizeof(uint64_t));
+ timer->_callback();
+ }
+ timer_iter = timer_iter->next;
+ }
+ }
+
+ switch (signal_pending) {
+ case SIGUSR1: // reload config file
+ signal_pending = 0;
+ init_config();
+ config_read_file (config_path);
+ init_panel();
+ cleanup_config();
+ break;
+ case SIGINT:
+ case SIGTERM:
+ case SIGHUP:
+ cleanup ();
+ return 0;
+ }
+ }