- XEvent e;
- fd_set fd;
- int x11_fd, i, c;
- struct timeval tv;
-
- c = getopt (argc, argv, "c:");
- init ();
-
-load_config:
- if (server.root_pmap) XFreePixmap (server.dsp, server.root_pmap);
- server.root_pmap = 0;
- // read tint2rc config
- i = 0;
- if (c != -1)
- i = config_read_file (optarg);
- if (!i)
- i = config_read ();
- if (!i) {
- fprintf(stderr, "usage: tint2 [-c] <config_file>\n");
- cleanup();
- exit(1);
- }
- config_finish ();
-
- window_draw_panel ();
-
- // BUG: draw(clock) is needed here, but 'on the paper' it's not necessary.
- draw(&panel.clock.area);
-
- x11_fd = ConnectionNumber (server.dsp);
- XSync (server.dsp, False);
-
- while (1) {
- // thanks to AngryLlama for the timer
- // Create a File Description Set containing x11_fd
- FD_ZERO (&fd);
- FD_SET (x11_fd, &fd);
-
- tv.tv_usec = 500000;
- tv.tv_sec = 0;
-
- // Wait for X Event or a Timer
- if (select(x11_fd+1, &fd, 0, 0, &tv)) {
- while (XPending (server.dsp)) {
- XNextEvent(server.dsp, &e);
-
- switch (e.type) {
- case ButtonPress:
- if (e.xbutton.button == 1) event_button_press (e.xbutton.x, e.xbutton.y);
- break;
-
- case ButtonRelease:
- event_button_release (e.xbutton.button, e.xbutton.x, e.xbutton.y);
- break;
-
- case Expose:
- XCopyArea (server.dsp, server.pmap, window.main_win, server.gc, 0, 0, panel.area.width, panel.area.height, 0, 0);
- break;
-
- case PropertyNotify:
- //printf("PropertyNotify\n");
- event_property_notify (e.xproperty.window, e.xproperty.atom);
- break;
-
- case ConfigureNotify:
- if (e.xconfigure.window == server.root_win)
- goto load_config;
- else
- if (panel.mode == MULTI_MONITOR)
- event_configure_notify (e.xconfigure.window);
- break;
- }
- }
- }
- else event_timer();
-
- switch (panel.signal_pending) {
- case SIGUSR1:
- goto load_config;
- case SIGINT:
- case SIGTERM:
- cleanup ();
- return 0;
- }
-
- if (panel.refresh && !panel.sleep_mode) {
- visual_refresh ();
- //printf(" *** visual_refresh\n");
- }
- }
+ XEvent e;
+ fd_set fdset;
+ int x11_fd, i;
+ Panel *panel;
+ GSList *it;
+ struct timeval* timeout;
+
+ init (argc, argv);
+ init_config();
+ i = 0;
+ if (config_path)
+ i = config_read_file (config_path);
+ else
+ i = config_read ();
+ if (!i) {
+ fprintf(stderr, "usage: tint2 [-c] <config_file>\n");
+ cleanup();
+ exit(1);
+ }
+
+ init_X11();
+ init_panel();
+ cleanup_config();
+ if (snapshot_path) {
+ get_snapshot(snapshot_path);
+ cleanup();
+ exit(0);
+ }
+
+ int damage_event, damage_error;
+ XDamageQueryExtension(server.dsp, &damage_event, &damage_error);
+ x11_fd = ConnectionNumber(server.dsp);
+ XSync(server.dsp, False);
+
+// sigset_t empty_mask;
+// sigemptyset(&empty_mask);
+
+ while (1) {
+ if (panel_refresh) {
+ panel_refresh = 0;
+
+ // QUESTION: do we need this first refresh_systray, because we check refresh_systray once again later...
+ if (refresh_systray) {
+ panel = (Panel*)systray.area.panel;
+ XSetWindowBackgroundPixmap (server.dsp, panel->main_win, None);
+ }
+ for (i=0 ; i < nb_panel ; i++) {
+ panel = &panel1[i];
+
+ if (panel->is_hidden) {
+ XCopyArea(server.dsp, panel->hidden_pixmap, panel->main_win, server.gc, 0, 0, panel->hidden_width, panel->hidden_height, 0, 0);
+ XSetWindowBackgroundPixmap(server.dsp, panel->main_win, panel->hidden_pixmap);
+ }
+ else {
+ if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap);
+ panel->temp_pmap = XCreatePixmap(server.dsp, server.root_win, panel->area.width, panel->area.height, server.depth);
+ refresh(&panel->area);
+ XCopyArea(server.dsp, panel->temp_pmap, panel->main_win, server.gc, 0, 0, panel->area.width, panel->area.height, 0, 0);
+ }
+ }
+ XFlush (server.dsp);
+
+ panel = (Panel*)systray.area.panel;
+ if (refresh_systray && !panel->is_hidden) {
+ refresh_systray = 0;
+ panel = (Panel*)systray.area.panel;
+ // tint2 doen't draw systray icons. it just redraw background.
+ XSetWindowBackgroundPixmap (server.dsp, panel->main_win, panel->temp_pmap);
+ // force icon's refresh
+ refresh_systray_icon();
+ }
+ }
+
+ // thanks to AngryLlama for the timer
+ // Create a File Description Set containing x11_fd
+ FD_ZERO (&fdset);
+ FD_SET (x11_fd, &fdset);
+ update_next_timeout();
+ if (next_timeout.tv_sec >= 0 && next_timeout.tv_usec >= 0)
+ timeout = &next_timeout;
+ else
+ timeout = 0;
+
+ // Wait for X Event or a Timer
+ if (select(x11_fd+1, &fdset, 0, 0, timeout) > 0) {
+ while (XPending (server.dsp)) {
+ XNextEvent(server.dsp, &e);
+
+ panel = get_panel(e.xany.window);
+ if (panel && panel_autohide) {
+ if (e.type == EnterNotify)
+ autohide_trigger_show(panel);
+ else if (e.type == LeaveNotify)
+ autohide_trigger_hide(panel);
+ if (panel->is_hidden)
+ continue; // discard further processing of this event because the panel is not visible yet
+ }
+
+ switch (e.type) {
+ case ButtonPress:
+ tooltip_hide(0);
+ 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:
+ if (g_tooltip.enabled)
+ tooltip_trigger_hide();
+ break;
+
+ case Expose:
+ event_expose(&e);
+ 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)->tray_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;
+
+ default:
+ if (e.type == XDamageNotify+damage_event) {
+ // union needed to avoid strict-aliasing warnings by gcc
+ union { XEvent e; XDamageNotifyEvent de; } event_union = {.e=e};
+ TrayWindow *traywin;
+ GSList *l;
+ XDamageNotifyEvent* de = &event_union.de;
+ for (l = systray.list_icons; l ; l = l->next) {
+ traywin = (TrayWindow*)l->data;
+ if ( traywin->id == de->drawable && !de->more ) {
+ systray_render_icon(traywin);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ callback_timeout_expired();
+
+ 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;
+ }
+ }