]> Dogcows Code - chaz/tint2/blob - src/tint.c
fixed config reload SIGUSR1. added systray = 1 parameter to enable systray
[chaz/tint2] / src / tint.c
1 /**************************************************************************
2 *
3 * Tint2 panel
4 *
5 * Copyright (C) 2007 Pål Staurland (staura@gmail.com)
6 * Modified (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr)
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 **************************************************************************/
20
21 #include <sys/stat.h>
22 #include <sys/time.h>
23 #include <unistd.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <X11/Xutil.h>
28 #include <X11/Xatom.h>
29 #include <X11/Xlocale.h>
30 #include <Imlib2.h>
31 #include <signal.h>
32
33 #include "server.h"
34 #include "window.h"
35 #include "config.h"
36 #include "task.h"
37 #include "taskbar.h"
38 #include "systraybar.h"
39 #include "panel.h"
40 #include "tooltip.h"
41
42
43 void signal_handler(int sig)
44 {
45 // signal handler is light as it should be
46 signal_pending = sig;
47 }
48
49
50 void init (int argc, char *argv[])
51 {
52 int c;
53
54 // read options
55 while ((c = getopt(argc , argv, "c:j:v")) != -1) {
56 switch (c) {
57 case 'c':
58 config_path = strdup (optarg);
59 break;
60 case 'j':
61 thumbnail_path = strdup (optarg);
62 break;
63 case 'v':
64 printf("tint2 version 0.7-svn\n");
65 exit(0);
66 break;
67 }
68 }
69
70 // Set signal handler
71 signal(SIGUSR1, signal_handler);
72 signal(SIGINT, signal_handler);
73 signal(SIGTERM, signal_handler);
74 signal(SIGHUP, signal_handler);
75 signal(SIGCHLD, SIG_IGN); // don't have to wait() after fork()
76 signal(SIGALRM, tooltip_sighandler);
77
78 // set global data
79 memset(&server, 0, sizeof(Server_global));
80 memset(&systray, 0, sizeof(Systraybar));
81
82 server.dsp = XOpenDisplay (NULL);
83 if (!server.dsp) {
84 fprintf(stderr, "tint2 exit : could not open display.\n");
85 exit(0);
86 }
87 server_init_atoms ();
88 server.screen = DefaultScreen (server.dsp);
89 server.root_win = RootWindow(server.dsp, server.screen);
90 server.depth = DefaultDepth (server.dsp, server.screen);
91 server.visual = DefaultVisual (server.dsp, server.screen);
92 server.desktop = server_get_current_desktop ();
93 XGCValues gcv;
94 server.gc = XCreateGC (server.dsp, server.root_win, (unsigned long)0, &gcv) ;
95
96 XSetErrorHandler ((XErrorHandler) server_catch_error);
97
98 imlib_context_set_display (server.dsp);
99 imlib_context_set_visual (server.visual);
100 imlib_context_set_colormap (DefaultColormap (server.dsp, server.screen));
101
102 /* Catch events */
103 XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
104
105 setlocale (LC_ALL, "");
106
107 // load default icon
108 int i;
109 char *path;
110 const gchar * const *data_dirs;
111 data_dirs = g_get_system_data_dirs ();
112 for (i = 0; data_dirs[i] != NULL; i++) {
113 path = g_build_filename(data_dirs[i], "tint2", "default_icon.png", NULL);
114 if (g_file_test (path, G_FILE_TEST_EXISTS))
115 default_icon = imlib_load_image(path);
116 g_free(path);
117 }
118
119 // get monitor and desktop config
120 get_monitors();
121 get_desktops();
122 }
123
124
125 void cleanup()
126 {
127 cleanup_systray();
128 stop_net();
129 cleanup_panel();
130 cleanup_tooltip();
131 cleanup_clock();
132 #ifdef ENABLE_BATTERY
133 cleanup_battery();
134 #endif
135
136 if (default_icon) {
137 imlib_context_set_image(default_icon);
138 imlib_free_image();
139 }
140 if (config_path) g_free(config_path);
141 if (thumbnail_path) g_free(thumbnail_path);
142
143 if (server.monitor) free(server.monitor);
144 XFreeGC(server.dsp, server.gc);
145 XCloseDisplay(server.dsp);
146 }
147
148
149 Taskbar *click_taskbar (Panel *panel, int x, int y)
150 {
151 Taskbar *tskbar;
152 int i;
153
154 if (panel_horizontal) {
155 for (i=0; i < panel->nb_desktop ; i++) {
156 tskbar = &panel->taskbar[i];
157 if (tskbar->area.on_screen && x >= tskbar->area.posx && x <= (tskbar->area.posx + tskbar->area.width))
158 return tskbar;
159 }
160 }
161 else {
162 for (i=0; i < panel->nb_desktop ; i++) {
163 tskbar = &panel->taskbar[i];
164 if (tskbar->area.on_screen && y >= tskbar->area.posy && y <= (tskbar->area.posy + tskbar->area.height))
165 return tskbar;
166 }
167 }
168 return NULL;
169 }
170
171
172 Task *click_task (Panel *panel, int x, int y)
173 {
174 GSList *l0;
175 Taskbar *tskbar;
176
177 if ( (tskbar = click_taskbar(panel, x, y)) ) {
178 if (panel_horizontal) {
179 Task *tsk;
180 for (l0 = tskbar->area.list; l0 ; l0 = l0->next) {
181 tsk = l0->data;
182 if (tsk->area.on_screen && x >= tsk->area.posx && x <= (tsk->area.posx + tsk->area.width)) {
183 return tsk;
184 }
185 }
186 }
187 else {
188 Task *tsk;
189 for (l0 = tskbar->area.list; l0 ; l0 = l0->next) {
190 tsk = l0->data;
191 if (tsk->area.on_screen && y >= tsk->area.posy && y <= (tsk->area.posy + tsk->area.height)) {
192 return tsk;
193 }
194 }
195 }
196 }
197 return NULL;
198 }
199
200
201 int click_padding(Panel *panel, int x, int y)
202 {
203 if (panel_horizontal) {
204 if (x < panel->area.paddingxlr || x > panel->area.width-panel->area.paddingxlr)
205 return 1;
206 }
207 else {
208 if (y < panel->area.paddingxlr || y > panel->area.height-panel->area.paddingxlr)
209 return 1;
210 }
211 return 0;
212 }
213
214
215 int click_clock(Panel *panel, int x, int y)
216 {
217 Clock clk = panel->clock;
218 if (panel_horizontal) {
219 if (clk.area.on_screen && x >= clk.area.posx && x <= (clk.area.posx + clk.area.width))
220 return TRUE;
221 } else {
222 if (clk.area.on_screen && y >= clk.area.posy && y <= (clk.area.posy + clk.area.height))
223 return TRUE;
224 }
225 return FALSE;
226 }
227
228
229 void window_action (Task *tsk, int action)
230 {
231 if (!tsk) return;
232 int desk;
233 switch (action) {
234 case CLOSE:
235 set_close (tsk->win);
236 break;
237 case TOGGLE:
238 set_active(tsk->win);
239 break;
240 case ICONIFY:
241 XIconifyWindow (server.dsp, tsk->win, server.screen);
242 break;
243 case TOGGLE_ICONIFY:
244 if (tsk == task_active) XIconifyWindow (server.dsp, tsk->win, server.screen);
245 else set_active (tsk->win);
246 break;
247 case SHADE:
248 window_toggle_shade (tsk->win);
249 break;
250 case MAXIMIZE_RESTORE:
251 window_maximize_restore (tsk->win);
252 break;
253 case MAXIMIZE:
254 window_maximize_restore (tsk->win);
255 break;
256 case RESTORE:
257 window_maximize_restore (tsk->win);
258 break;
259 case DESKTOP_LEFT:
260 if ( tsk->desktop == 0 ) break;
261 desk = tsk->desktop - 1;
262 windows_set_desktop(tsk->win, desk);
263 if (desk == server.desktop)
264 set_active(tsk->win);
265 break;
266 case DESKTOP_RIGHT:
267 if (tsk->desktop == server.nb_desktop ) break;
268 desk = tsk->desktop + 1;
269 windows_set_desktop(tsk->win, desk);
270 if (desk == server.desktop)
271 set_active(tsk->win);
272 }
273 }
274
275
276 void event_button_press (XEvent *e)
277 {
278 Panel *panel = get_panel(e->xany.window);
279 if (!panel) return;
280
281 task_drag = click_task(panel, e->xbutton.x, e->xbutton.y);
282
283 if (wm_menu && !task_drag && !click_clock(panel, e->xbutton.x, e->xbutton.y) && (e->xbutton.button != 1) ) {
284 // forward the click to the desktop window (thanks conky)
285 XUngrabPointer(server.dsp, e->xbutton.time);
286 e->xbutton.window = server.root_win;
287 // icewm doesn't open under the mouse.
288 // and xfce doesn't open at all.
289 e->xbutton.x = e->xbutton.x_root;
290 e->xbutton.y = e->xbutton.y_root;
291 //printf("**** %d, %d\n", e->xbutton.x, e->xbutton.y);
292 //XSetInputFocus(server.dsp, e->xbutton.window, RevertToParent, e->xbutton.time);
293 XSendEvent(server.dsp, e->xbutton.window, False, ButtonPressMask, e);
294 return;
295 }
296
297 XLowerWindow (server.dsp, panel->main_win);
298 }
299
300
301 void event_button_release (XEvent *e)
302 {
303 Panel *panel = get_panel(e->xany.window);
304 if (!panel) return;
305
306 int action = TOGGLE_ICONIFY;
307 switch (e->xbutton.button) {
308 case 2:
309 action = mouse_middle;
310 break;
311 case 3:
312 action = mouse_right;
313 break;
314 case 4:
315 action = mouse_scroll_up;
316 break;
317 case 5:
318 action = mouse_scroll_down;
319 break;
320 case 6:
321 action = mouse_tilt_left;
322 break;
323 case 7:
324 action = mouse_tilt_right;
325 break;
326 }
327
328 if ( click_clock(panel, e->xbutton.x, e->xbutton.y)) {
329 clock_action(e->xbutton.button);
330 XLowerWindow (server.dsp, panel->main_win);
331 task_drag = 0;
332 return;
333 }
334
335 Taskbar *tskbar;
336 if ( !(tskbar = click_taskbar(panel, e->xbutton.x, e->xbutton.y)) ) {
337 // TODO: check better solution to keep window below
338 XLowerWindow (server.dsp, panel->main_win);
339 task_drag = 0;
340 return;
341 }
342
343 // drag and drop task
344 if (task_drag) {
345 if (tskbar != task_drag->area.parent && action == TOGGLE_ICONIFY) {
346 if (task_drag->desktop != ALLDESKTOP && panel_mode == MULTI_DESKTOP) {
347 windows_set_desktop(task_drag->win, tskbar->desktop);
348 if (tskbar->desktop == server.desktop)
349 set_active(task_drag->win);
350 task_drag = 0;
351 }
352 return;
353 }
354 else task_drag = 0;
355 }
356
357 // switch desktop
358 if (panel_mode == MULTI_DESKTOP) {
359 if (tskbar->desktop != server.desktop && action != CLOSE && action != DESKTOP_LEFT && action != DESKTOP_RIGHT)
360 set_desktop (tskbar->desktop);
361 }
362
363 // action on task
364 window_action( click_task(panel, e->xbutton.x, e->xbutton.y), action);
365
366 // to keep window below
367 XLowerWindow (server.dsp, panel->main_win);
368 }
369
370
371 void event_property_notify (XEvent *e)
372 {
373 int i, j;
374 Task *tsk;
375 Window win = e->xproperty.window;
376 Atom at = e->xproperty.atom;
377
378 if (win == server.root_win) {
379 if (!server.got_root_win) {
380 XSelectInput (server.dsp, server.root_win, PropertyChangeMask|StructureNotifyMask);
381 server.got_root_win = 1;
382 }
383
384 // Change number of desktops
385 else if (at == server.atom._NET_NUMBER_OF_DESKTOPS) {
386 server.nb_desktop = server_get_number_of_desktop ();
387 cleanup_taskbar();
388 init_taskbar();
389 visible_object();
390 for (i=0 ; i < nb_panel ; i++) {
391 panel1[i].area.resize = 1;
392 }
393 task_refresh_tasklist();
394 panel_refresh = 1;
395 }
396 // Change desktop
397 else if (at == server.atom._NET_CURRENT_DESKTOP) {
398 int old_desktop = server.desktop;
399 server.desktop = server_get_current_desktop ();
400 for (i=0 ; i < nb_panel ; i++) {
401 Panel *panel = &panel1[i];
402 if (panel_mode == MULTI_DESKTOP && panel->g_taskbar.use_active) {
403 // redraw both taskbar
404 panel->taskbar[old_desktop].area.is_active = 0;
405 panel->taskbar[old_desktop].area.redraw = 1;
406 panel->taskbar[server.desktop].area.is_active = 1;
407 panel->taskbar[server.desktop].area.redraw = 1;
408 panel_refresh = 1;
409 }
410 // check ALLDESKTOP task => resize taskbar
411 Taskbar *tskbar;
412 Task *tsk;
413 GSList *l;
414 tskbar = &panel->taskbar[old_desktop];
415 for (l = tskbar->area.list; l ; l = l->next) {
416 tsk = l->data;
417 if (tsk->desktop == ALLDESKTOP) {
418 tsk->area.on_screen = 0;
419 tskbar->area.resize = 1;
420 panel_refresh = 1;
421 }
422 }
423 tskbar = &panel->taskbar[server.desktop];
424 for (l = tskbar->area.list; l ; l = l->next) {
425 tsk = l->data;
426 if (tsk->desktop == ALLDESKTOP) {
427 tsk->area.on_screen = 1;
428 tskbar->area.resize = 1;
429 }
430 }
431 }
432 if (panel_mode != MULTI_DESKTOP) {
433 visible_object();
434 }
435 }
436 // Window list
437 else if (at == server.atom._NET_CLIENT_LIST) {
438 task_refresh_tasklist();
439 panel_refresh = 1;
440 }
441 // Change active
442 else if (at == server.atom._NET_ACTIVE_WINDOW) {
443 active_task();
444 panel_refresh = 1;
445 }
446 else if (at == server.atom._XROOTPMAP_ID) {
447 // change Wallpaper
448 for (i=0 ; i < nb_panel ; i++) {
449 set_panel_background(&panel1[i]);
450 }
451 panel_refresh = 1;
452 }
453 }
454 else {
455 tsk = task_get_task (win);
456 if (!tsk) {
457 if ( at != server.atom._NET_WM_STATE)
458 return;
459 else if ( !(tsk = add_task(win)) )
460 return;
461 }
462 //printf("atom root_win = %s, %s\n", XGetAtomName(server.dsp, at), tsk->title);
463
464 // Window title changed
465 if (at == server.atom._NET_WM_VISIBLE_NAME || at == server.atom._NET_WM_NAME || at == server.atom.WM_NAME) {
466 Task *tsk2;
467 GSList *l0;
468 get_title(tsk);
469 // changed other tsk->title
470 for (i=0 ; i < nb_panel ; i++) {
471 for (j=0 ; j < panel1[i].nb_desktop ; j++) {
472 for (l0 = panel1[i].taskbar[j].area.list; l0 ; l0 = l0->next) {
473 tsk2 = l0->data;
474 if (tsk->win == tsk2->win && tsk != tsk2) {
475 tsk2->title = tsk->title;
476 tsk2->area.redraw = 1;
477 }
478 }
479 }
480 }
481 panel_refresh = 1;
482 }
483 // Demand attention
484 else if (at == server.atom._NET_WM_STATE) {
485 if (window_is_urgent (win)) {
486 task_urgent = tsk;
487 tick_urgent = 0;
488 time_precision = 1;
489 }
490 if (window_is_skip_taskbar(win)) {
491 remove_task( tsk );
492 panel_refresh = 1;
493 }
494 }
495 // We do not check for the iconified state, since it only unsets our active window
496 // but in openbox a shaded window is considered iconified. So we would loose the active window
497 // property on unshading it again (commented 01.10.2009)
498 // else if (at == server.atom.WM_STATE) {
499 // // Iconic state
500 // // TODO : try to delete following code
501 // if (window_is_iconified (win)) {
502 // if (task_active) {
503 // if (task_active->win == tsk->win) {
504 // Task *tsk2;
505 // GSList *l0;
506 // for (i=0 ; i < nb_panel ; i++) {
507 // for (j=0 ; j < panel1[i].nb_desktop ; j++) {
508 // for (l0 = panel1[i].taskbar[j].area.list; l0 ; l0 = l0->next) {
509 // tsk2 = l0->data;
510 // tsk2->area.is_active = 0;
511 // }
512 // }
513 // }
514 // task_active = 0;
515 // }
516 // }
517 // }
518 // }
519 // Window icon changed
520 else if (at == server.atom._NET_WM_ICON) {
521 get_icon(tsk);
522 Task *tsk2;
523 GSList *l0;
524 for (i=0 ; i < nb_panel ; i++) {
525 for (j=0 ; j < panel1[i].nb_desktop ; j++) {
526 for (l0 = panel1[i].taskbar[j].area.list; l0 ; l0 = l0->next) {
527 tsk2 = l0->data;
528 if (tsk->win == tsk2->win && tsk != tsk2) {
529 tsk2->icon_width = tsk->icon_width;
530 tsk2->icon_height = tsk->icon_height;
531 tsk2->icon = tsk->icon;
532 tsk2->icon_active = tsk->icon_active;
533 tsk2->area.redraw = 1;
534 }
535 }
536 }
537 }
538 panel_refresh = 1;
539 }
540 // Window desktop changed
541 else if (at == server.atom._NET_WM_DESKTOP) {
542 int desktop = window_get_desktop (win);
543 int active = tsk->area.is_active;
544 //printf(" Window desktop changed %d, %d\n", tsk->desktop, desktop);
545 // bug in windowmaker : send unecessary 'desktop changed' when focus changed
546 if (desktop != tsk->desktop) {
547 remove_task (tsk);
548 tsk = add_task (win);
549 if (tsk && active) {
550 tsk->area.is_active = 1;
551 task_active = tsk;
552 }
553 panel_refresh = 1;
554 }
555 }
556 else if (at == server.atom.WM_HINTS) {
557 XWMHints* wmhints = XGetWMHints(server.dsp, win);
558 if (wmhints && wmhints->flags & XUrgencyHint) {
559 task_urgent = tsk;
560 tick_urgent = 0;
561 time_precision = 1;
562 }
563 XFree(wmhints);
564 }
565
566 if (!server.got_root_win) server.root_win = RootWindow (server.dsp, server.screen);
567 }
568 }
569
570
571 void event_expose (XEvent *e)
572 {
573 if (e->xany.window == g_tooltip.window)
574 tooltip_update();
575 else {
576 Panel *panel;
577 panel = get_panel(e->xany.window);
578 if (!panel) return;
579 // TODO : one panel_refresh per panel ?
580 panel_refresh = 1;
581 }
582 }
583
584
585 void event_configure_notify (Window win)
586 {
587 // change in root window (xrandr)
588 if (win == server.root_win) {
589 get_monitors();
590 init_panel();
591 return;
592 }
593
594 // 'win' is a trayer icon
595 TrayWindow *traywin;
596 GSList *l;
597 for (l = systray.list_icons; l ; l = l->next) {
598 traywin = (TrayWindow*)l->data;
599 if (traywin->id == win) {
600 //printf("move tray %d\n", traywin->x);
601 XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, traywin->width, traywin->height);
602 panel_refresh = 1;
603 return;
604 }
605 }
606
607 // 'win' move in another monitor
608 if (nb_panel == 1) return;
609 Task *tsk = task_get_task (win);
610 if (!tsk) return;
611
612 Panel *p = tsk->area.panel;
613 if (p->monitor != window_get_monitor (win)) {
614 remove_task (tsk);
615 add_task (win);
616 if (win == window_get_active ()) {
617 Task *tsk = task_get_task (win);
618 tsk->area.is_active = 1;
619 task_active = tsk;
620 }
621 panel_refresh = 1;
622 }
623 }
624
625
626 void event_timer()
627 {
628 struct timeval stv;
629 int i;
630
631 if (gettimeofday(&stv, 0)) return;
632
633 if (abs(stv.tv_sec - time_clock.tv_sec) < time_precision) return;
634 time_clock.tv_sec = stv.tv_sec;
635 time_clock.tv_sec -= time_clock.tv_sec % time_precision;
636
637 // urgent task
638 if (task_urgent) {
639 if (tick_urgent < max_tick_urgent) {
640 task_urgent->area.is_active = !task_urgent->area.is_active;
641 task_urgent->area.redraw = 1;
642 tick_urgent++;
643 }
644 }
645
646 // update battery
647 #ifdef ENABLE_BATTERY
648 if (battery_enabled) {
649 update_battery();
650 for (i=0 ; i < nb_panel ; i++)
651 panel1[i].battery.area.resize = 1;
652 }
653 #endif
654
655 // update clock
656 if (time1_format) {
657 for (i=0 ; i < nb_panel ; i++)
658 panel1[i].clock.area.resize = 1;
659 }
660 panel_refresh = 1;
661 }
662
663
664 void dnd_message(XClientMessageEvent *e)
665 {
666 Panel *panel = get_panel(e->window);
667 int x, y, mapX, mapY;
668 Window child;
669 x = (e->data.l[2] >> 16) & 0xFFFF;
670 y = e->data.l[2] & 0xFFFF;
671 XTranslateCoordinates(server.dsp, server.root_win, e->window, x, y, &mapX, &mapY, &child);
672 Task* task = click_task(panel, mapX, mapY);
673 if (task) {
674 if (task->desktop != server.desktop )
675 set_desktop (task->desktop);
676 window_action(task, TOGGLE);
677 }
678
679 // send XdndStatus event to get more XdndPosition events
680 XClientMessageEvent se;
681 se.type = ClientMessage;
682 se.window = e->data.l[0];
683 se.message_type = server.atom.XdndStatus;
684 se.format = 32;
685 se.data.l[0] = e->window; // XID of the target window
686 se.data.l[1] = 0; // bit 0: accept drop bit 1: send XdndPosition events if inside rectangle
687 se.data.l[2] = 0; // Rectangle x,y for which no more XdndPosition events
688 se.data.l[3] = (1 << 16) | 1; // Rectangle w,h for which no more XdndPosition events
689 se.data.l[4] = None; // None = drop will not be accepted
690 XSendEvent(server.dsp, e->data.l[0], False, NoEventMask, (XEvent*)&se);
691 }
692
693
694 int main (int argc, char *argv[])
695 {
696 XEvent e;
697 fd_set fd;
698 int x11_fd, i;
699 struct timeval tv;
700 Panel *panel;
701 GSList *it;
702
703 init (argc, argv);
704
705 i = 0;
706 init_config();
707 if (config_path)
708 i = config_read_file (config_path);
709 else
710 i = config_read ();
711 if (!i) {
712 fprintf(stderr, "usage: tint2 [-c] <config_file>\n");
713 cleanup();
714 exit(1);
715 }
716 init_panel();
717 cleanup_config();
718 if (thumbnail_path) {
719 // usage: tint2 -j <file> for internal use
720 printf("file %s\n", thumbnail_path);
721 cleanup();
722 exit(0);
723 }
724
725 x11_fd = ConnectionNumber(server.dsp);
726 XSync(server.dsp, False);
727
728 while (1) {
729 // thanks to AngryLlama for the timer
730 // Create a File Description Set containing x11_fd
731 FD_ZERO (&fd);
732 FD_SET (x11_fd, &fd);
733
734 tv.tv_usec = 500000;
735 tv.tv_sec = 0;
736
737 // Wait for X Event or a Timer
738 if (select(x11_fd+1, &fd, 0, 0, &tv)) {
739 while (XPending (server.dsp)) {
740 XNextEvent(server.dsp, &e);
741
742 switch (e.type) {
743 case ButtonPress:
744 tooltip_hide();
745 event_button_press (&e);
746 break;
747
748 case ButtonRelease:
749 event_button_release(&e);
750 break;
751
752 case MotionNotify: {
753 Panel* panel = get_panel(e.xmotion.window);
754 Task* task = click_task(panel, e.xmotion.x, e.xmotion.y);
755 if (task)
756 tooltip_trigger_show(task, e.xmotion.x_root, e.xmotion.y_root);
757 else
758 tooltip_trigger_hide();
759 break;
760 }
761
762 case LeaveNotify:
763 tooltip_trigger_hide();
764 break;
765
766 case Expose:
767 event_expose(&e);
768 break;
769
770 case PropertyNotify:
771 event_property_notify(&e);
772 break;
773
774 case ConfigureNotify:
775 event_configure_notify (e.xconfigure.window);
776 break;
777
778 case ReparentNotify:
779 if (!systray.area.on_screen)
780 break;
781 panel = (Panel*)systray.area.panel;
782 if (e.xany.window == panel->main_win) // reparented to us
783 break;
784 // FIXME: 'reparent to us' badly detected => disabled
785 break;
786 case UnmapNotify:
787 case DestroyNotify:
788 if (!systray.area.on_screen)
789 break;
790 for (it = systray.list_icons; it; it = g_slist_next(it)) {
791 if (((TrayWindow*)it->data)->id == e.xany.window) {
792 remove_icon((TrayWindow*)it->data);
793 break;
794 }
795 }
796 break;
797
798 case ClientMessage:
799 if (!systray.area.on_screen) break;
800 if (e.xclient.message_type == server.atom._NET_SYSTEM_TRAY_OPCODE && e.xclient.format == 32 && e.xclient.window == net_sel_win) {
801 net_message(&e.xclient);
802 }
803 else if (e.xclient.message_type == server.atom.XdndPosition) {
804 dnd_message(&e.xclient);
805 }
806 break;
807 }
808 }
809 }
810 event_timer();
811
812 switch (signal_pending) {
813 case SIGUSR1: // reload config file
814 signal_pending = 0;
815 init_config();
816 config_read_file (config_path);
817 init_panel();
818 cleanup_config();
819 break;
820 case SIGINT:
821 case SIGTERM:
822 case SIGHUP:
823 cleanup ();
824 return 0;
825 }
826
827 if (panel_refresh) {
828 panel_refresh = 0;
829
830 if (refresh_systray) {
831 panel = (Panel*)systray.area.panel;
832 XSetWindowBackgroundPixmap (server.dsp, panel->main_win, None);
833 }
834 for (i=0 ; i < nb_panel ; i++) {
835 panel = &panel1[i];
836
837 if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap);
838 panel->temp_pmap = XCreatePixmap(server.dsp, server.root_win, panel->area.width, panel->area.height, server.depth);
839
840 refresh(&panel->area);
841 XCopyArea(server.dsp, panel->temp_pmap, panel->main_win, server.gc, 0, 0, panel->area.width, panel->area.height, 0, 0);
842 }
843 XFlush (server.dsp);
844
845 if (refresh_systray) {
846 refresh_systray = 0;
847 panel = (Panel*)systray.area.panel;
848 // tint2 doen't draw systray icons. it just redraw background.
849 XSetWindowBackgroundPixmap (server.dsp, panel->main_win, panel->temp_pmap);
850 // force icon's refresh
851 refresh_systray_icon();
852 }
853 }
854 }
855 }
856
857
This page took 0.081524 seconds and 5 git commands to generate.