X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Ftint.c;h=44b6d9e8952702855230b7c4d92f418191b4435a;hb=bef508d2e43e3fb90e3f4e31ec36ba1d7cd6b8bc;hp=3696911387bbff9813b4dbb796905f8c70c47cf5;hpb=386f2fec6d8d7c3ebe1e2192f4632ed0b12f0df1;p=chaz%2Ftint2 diff --git a/src/tint.c b/src/tint.c index 3696911..44b6d9e 100644 --- a/src/tint.c +++ b/src/tint.c @@ -19,10 +19,10 @@ **************************************************************************/ #include -#include #include #include #include +#include #include #include #include @@ -38,7 +38,7 @@ #include "systraybar.h" #include "panel.h" #include "tooltip.h" - +#include "timer.h" void signal_handler(int sig) { @@ -49,31 +49,45 @@ void signal_handler(int sig) void init (int argc, char *argv[]) { - int c; + int i; // read options - while ((c = getopt(argc , argv, "c:j:v")) != -1) { - switch (c) { - case 'c': - config_path = strdup (optarg); - break; - case 'j': - thumbnail_path = strdup (optarg); - break; - case 'v': - printf("tint2 version 0.7-svn\n"); + for (i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { + printf("Usage: tint2 [-c] \n"); exit(0); - break; + } + if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { + printf("tint2 version 0.7.svn\n"); + exit(0); + } + if (!strcmp(argv[i], "-c")) { + i++; + if (i < argc) + config_path = strdup(argv[i]); + } + if (!strcmp(argv[i], "-s")) { + i++; + if (i < argc) + snapshot_path = strdup(argv[i]); } } // Set signal handler - signal(SIGUSR1, signal_handler); - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - signal(SIGHUP, signal_handler); + struct sigaction sa = { .sa_handler = signal_handler }; + sigaction(SIGUSR1, &sa, 0); + sigaction(SIGINT, &sa, 0); + sigaction(SIGTERM, &sa, 0); + sigaction(SIGHUP, &sa, 0); signal(SIGCHLD, SIG_IGN); // don't have to wait() after fork() - signal(SIGALRM, tooltip_sighandler); + // block all signals, such that no race conditions occur before pselect in our main loop + sigset_t block_mask; + sigaddset(&block_mask, SIGINT); + sigaddset(&block_mask, SIGTERM); + sigaddset(&block_mask, SIGHUP); + sigaddset(&block_mask, SIGUSR1); + sigprocmask(SIG_BLOCK, &block_mask, 0); + // set global data memset(&server, 0, sizeof(Server_global)); @@ -91,7 +105,7 @@ void init (int argc, char *argv[]) server.visual = DefaultVisual (server.dsp, server.screen); server.desktop = server_get_current_desktop (); XGCValues gcv; - server.gc = XCreateGC (server.dsp, server.root_win, (unsigned long)0, &gcv) ; + server.gc = XCreateGC (server.dsp, server.root_win, (unsigned long)0, &gcv); XSetErrorHandler ((XErrorHandler) server_catch_error); @@ -105,8 +119,7 @@ void init (int argc, char *argv[]) setlocale (LC_ALL, ""); // load default icon - int i; - char *path; + gchar *path; const gchar * const *data_dirs; data_dirs = g_get_system_data_dirs (); for (i = 0; data_dirs[i] != NULL; i++) { @@ -138,7 +151,7 @@ void cleanup() imlib_free_image(); } if (config_path) g_free(config_path); - if (thumbnail_path) g_free(thumbnail_path); + if (snapshot_path) g_free(snapshot_path); if (server.monitor) free(server.monitor); XFreeGC(server.dsp, server.gc); @@ -146,6 +159,25 @@ void cleanup() } +void get_snapshot(const char *path) +{ + Panel *panel = &panel1[0]; + + 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); + + Imlib_Image img = NULL; + imlib_context_set_drawable(panel->temp_pmap); + img = imlib_create_image_from_drawable(0, 0, 0, panel->area.width, panel->area.height, 0); + + imlib_context_set_image(img); + imlib_save_image(path); + imlib_free_image(); +} + + Taskbar *click_taskbar (Panel *panel, int x, int y) { Taskbar *tskbar; @@ -241,8 +273,10 @@ void window_action (Task *tsk, int action) XIconifyWindow (server.dsp, tsk->win, server.screen); break; case TOGGLE_ICONIFY: - if (tsk == task_active) XIconifyWindow (server.dsp, tsk->win, server.screen); - else set_active (tsk->win); + if (task_active && tsk->win == task_active->win) + XIconifyWindow (server.dsp, tsk->win, server.screen); + else + set_active (tsk->win); break; case SHADE: window_toggle_shade (tsk->win); @@ -454,10 +488,20 @@ void event_property_notify (XEvent *e) else { tsk = task_get_task (win); if (!tsk) { - if ( at != server.atom._NET_WM_STATE) - return; - else if ( !(tsk = add_task(win)) ) + if (at != server.atom._NET_WM_STATE) return; + else { + // xfce4 sends _NET_WM_STATE after minimized to tray, so we need to check if window is mapped + // if it is mapped and not set as skip_taskbar, we must add it to our task list + XWindowAttributes wa; + XGetWindowAttributes(server.dsp, win, &wa); + if (wa.map_state == IsViewable && !window_is_skip_taskbar(win)) { + if ( (tsk = add_task(win)) ) + panel_refresh = 1; + else + return; + } + } } //printf("atom root_win = %s, %s\n", XGetAtomName(server.dsp, at), tsk->title); @@ -483,9 +527,7 @@ void event_property_notify (XEvent *e) // Demand attention else if (at == server.atom._NET_WM_STATE) { if (window_is_urgent (win)) { - task_urgent = tsk; - tick_urgent = 0; - time_precision = 1; + add_urgent(tsk); } if (window_is_skip_taskbar(win)) { remove_task( tsk ); @@ -556,9 +598,7 @@ void event_property_notify (XEvent *e) else if (at == server.atom.WM_HINTS) { XWMHints* wmhints = XGetWMHints(server.dsp, win); if (wmhints && wmhints->flags & XUrgencyHint) { - task_urgent = tsk; - tick_urgent = 0; - time_precision = 1; + add_urgent(tsk); } XFree(wmhints); } @@ -628,39 +668,6 @@ void event_configure_notify (Window win) void event_timer() { - struct timeval stv; - int i; - - if (gettimeofday(&stv, 0)) return; - - if (abs(stv.tv_sec - time_clock.tv_sec) < time_precision) return; - time_clock.tv_sec = stv.tv_sec; - time_clock.tv_sec -= time_clock.tv_sec % time_precision; - - // urgent task - if (task_urgent) { - if (tick_urgent < max_tick_urgent) { - task_urgent->area.is_active = !task_urgent->area.is_active; - task_urgent->area.redraw = 1; - tick_urgent++; - } - } - - // update battery -#ifdef ENABLE_BATTERY - if (battery_enabled) { - update_battery(); - for (i=0 ; i < nb_panel ; i++) - panel1[i].battery.area.resize = 1; - } -#endif - - // update clock - if (time1_format) { - for (i=0 ; i < nb_panel ; i++) - panel1[i].clock.area.resize = 1; - } - panel_refresh = 1; } @@ -697,11 +704,12 @@ void dnd_message(XClientMessageEvent *e) int main (int argc, char *argv[]) { XEvent e; - fd_set fd; + fd_set fdset; int x11_fd, i; - struct timeval tv; Panel *panel; GSList *it; + GSList* timer_iter; + struct timer* timer; init (argc, argv); @@ -718,9 +726,8 @@ int main (int argc, char *argv[]) } init_panel(); cleanup_config(); - if (thumbnail_path) { - // usage: tint2 -j for internal use - printf("file %s\n", thumbnail_path); + if (snapshot_path) { + get_snapshot(snapshot_path); cleanup(); exit(0); } @@ -728,17 +735,25 @@ int main (int argc, char *argv[]) x11_fd = ConnectionNumber(server.dsp); XSync(server.dsp, False); + sigset_t empty_mask; + sigemptyset(&empty_mask); + 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; + // 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 (select(x11_fd+1, &fd, 0, 0, &tv)) { + if (pselect(max_fd+1, &fdset, 0, 0, 0, &empty_mask) > 0) { while (XPending (server.dsp)) { XNextEvent(server.dsp, &e); @@ -810,22 +825,34 @@ int main (int argc, char *argv[]) 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; + } } - event_timer(); 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; + 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; } if (panel_refresh) {