]> Dogcows Code - chaz/tint2/blob - src/tint.c
fixed bug in taskbar drawing
[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.resize = 1;
406 panel->taskbar[server.desktop].area.is_active = 1;
407 panel->taskbar[server.desktop].area.resize = 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_config();
591 config_read_file (config_path);
592 init_panel();
593 cleanup_config();
594 return;
595 }
596
597 // 'win' is a trayer icon
598 TrayWindow *traywin;
599 GSList *l;
600 for (l = systray.list_icons; l ; l = l->next) {
601 traywin = (TrayWindow*)l->data;
602 if (traywin->id == win) {
603 //printf("move tray %d\n", traywin->x);
604 XMoveResizeWindow(server.dsp, traywin->id, traywin->x, traywin->y, traywin->width, traywin->height);
605 panel_refresh = 1;
606 return;
607 }
608 }
609
610 // 'win' move in another monitor
611 if (nb_panel == 1) return;
612 Task *tsk = task_get_task (win);
613 if (!tsk) return;
614
615 Panel *p = tsk->area.panel;
616 if (p->monitor != window_get_monitor (win)) {
617 remove_task (tsk);
618 add_task (win);
619 if (win == window_get_active ()) {
620 Task *tsk = task_get_task (win);
621 tsk->area.is_active = 1;
622 task_active = tsk;
623 }
624 panel_refresh = 1;
625 }
626 }
627
628
629 void event_timer()
630 {
631 struct timeval stv;
632 int i;
633
634 if (gettimeofday(&stv, 0)) return;
635
636 if (abs(stv.tv_sec - time_clock.tv_sec) < time_precision) return;
637 time_clock.tv_sec = stv.tv_sec;
638 time_clock.tv_sec -= time_clock.tv_sec % time_precision;
639
640 // urgent task
641 if (task_urgent) {
642 if (tick_urgent < max_tick_urgent) {
643 task_urgent->area.is_active = !task_urgent->area.is_active;
644 task_urgent->area.redraw = 1;
645 tick_urgent++;
646 }
647 }
648
649 // update battery
650 #ifdef ENABLE_BATTERY
651 if (battery_enabled) {
652 update_battery();
653 for (i=0 ; i < nb_panel ; i++)
654 panel1[i].battery.area.resize = 1;
655 }
656 #endif
657
658 // update clock
659 if (time1_format) {
660 for (i=0 ; i < nb_panel ; i++)
661 panel1[i].clock.area.resize = 1;
662 }
663 panel_refresh = 1;
664 }
665
666
667 void dnd_message(XClientMessageEvent *e)
668 {
669 Panel *panel = get_panel(e->window);
670 int x, y, mapX, mapY;
671 Window child;
672 x = (e->data.l[2] >> 16) & 0xFFFF;
673 y = e->data.l[2] & 0xFFFF;
674 XTranslateCoordinates(server.dsp, server.root_win, e->window, x, y, &mapX, &mapY, &child);
675 Task* task = click_task(panel, mapX, mapY);
676 if (task) {
677 if (task->desktop != server.desktop )
678 set_desktop (task->desktop);
679 window_action(task, TOGGLE);
680 }
681
682 // send XdndStatus event to get more XdndPosition events
683 XClientMessageEvent se;
684 se.type = ClientMessage;
685 se.window = e->data.l[0];
686 se.message_type = server.atom.XdndStatus;
687 se.format = 32;
688 se.data.l[0] = e->window; // XID of the target window
689 se.data.l[1] = 0; // bit 0: accept drop bit 1: send XdndPosition events if inside rectangle
690 se.data.l[2] = 0; // Rectangle x,y for which no more XdndPosition events
691 se.data.l[3] = (1 << 16) | 1; // Rectangle w,h for which no more XdndPosition events
692 se.data.l[4] = None; // None = drop will not be accepted
693 XSendEvent(server.dsp, e->data.l[0], False, NoEventMask, (XEvent*)&se);
694 }
695
696
697 int main (int argc, char *argv[])
698 {
699 XEvent e;
700 fd_set fd;
701 int x11_fd, i;
702 struct timeval tv;
703 Panel *panel;
704 GSList *it;
705
706 init (argc, argv);
707
708 i = 0;
709 init_config();
710 if (config_path)
711 i = config_read_file (config_path);
712 else
713 i = config_read ();
714 if (!i) {
715 fprintf(stderr, "usage: tint2 [-c] <config_file>\n");
716 cleanup();
717 exit(1);
718 }
719 init_panel();
720 cleanup_config();
721 if (thumbnail_path) {
722 // usage: tint2 -j <file> for internal use
723 printf("file %s\n", thumbnail_path);
724 cleanup();
725 exit(0);
726 }
727
728 x11_fd = ConnectionNumber(server.dsp);
729 XSync(server.dsp, False);
730
731 while (1) {
732 // thanks to AngryLlama for the timer
733 // Create a File Description Set containing x11_fd
734 FD_ZERO (&fd);
735 FD_SET (x11_fd, &fd);
736
737 tv.tv_usec = 500000;
738 tv.tv_sec = 0;
739
740 // Wait for X Event or a Timer
741 if (select(x11_fd+1, &fd, 0, 0, &tv)) {
742 while (XPending (server.dsp)) {
743 XNextEvent(server.dsp, &e);
744
745 switch (e.type) {
746 case ButtonPress:
747 tooltip_hide();
748 event_button_press (&e);
749 break;
750
751 case ButtonRelease:
752 event_button_release(&e);
753 break;
754
755 case MotionNotify: {
756 if (!g_tooltip.enabled) break;
757 Panel* panel = get_panel(e.xmotion.window);
758 Task* task = click_task(panel, e.xmotion.x, e.xmotion.y);
759 if (task)
760 tooltip_trigger_show(task, e.xmotion.x_root, e.xmotion.y_root);
761 else
762 tooltip_trigger_hide();
763 break;
764 }
765
766 case LeaveNotify:
767 tooltip_trigger_hide();
768 break;
769
770 case Expose:
771 event_expose(&e);
772 break;
773
774 case PropertyNotify:
775 event_property_notify(&e);
776 break;
777
778 case ConfigureNotify:
779 event_configure_notify (e.xconfigure.window);
780 break;
781
782 case ReparentNotify:
783 if (!systray_enabled)
784 break;
785 panel = (Panel*)systray.area.panel;
786 if (e.xany.window == panel->main_win) // reparented to us
787 break;
788 // FIXME: 'reparent to us' badly detected => disabled
789 break;
790 case UnmapNotify:
791 case DestroyNotify:
792 if (!systray.area.on_screen)
793 break;
794 for (it = systray.list_icons; it; it = g_slist_next(it)) {
795 if (((TrayWindow*)it->data)->id == e.xany.window) {
796 remove_icon((TrayWindow*)it->data);
797 break;
798 }
799 }
800 break;
801
802 case ClientMessage:
803 if (!systray.area.on_screen) break;
804 if (e.xclient.message_type == server.atom._NET_SYSTEM_TRAY_OPCODE && e.xclient.format == 32 && e.xclient.window == net_sel_win) {
805 net_message(&e.xclient);
806 }
807 else if (e.xclient.message_type == server.atom.XdndPosition) {
808 dnd_message(&e.xclient);
809 }
810 break;
811 }
812 }
813 }
814 event_timer();
815
816 switch (signal_pending) {
817 case SIGUSR1: // reload config file
818 signal_pending = 0;
819 init_config();
820 config_read_file (config_path);
821 init_panel();
822 cleanup_config();
823 break;
824 case SIGINT:
825 case SIGTERM:
826 case SIGHUP:
827 cleanup ();
828 return 0;
829 }
830
831 if (panel_refresh) {
832 panel_refresh = 0;
833
834 if (refresh_systray) {
835 panel = (Panel*)systray.area.panel;
836 XSetWindowBackgroundPixmap (server.dsp, panel->main_win, None);
837 }
838 for (i=0 ; i < nb_panel ; i++) {
839 panel = &panel1[i];
840
841 if (panel->temp_pmap) XFreePixmap(server.dsp, panel->temp_pmap);
842 panel->temp_pmap = XCreatePixmap(server.dsp, server.root_win, panel->area.width, panel->area.height, server.depth);
843
844 refresh(&panel->area);
845 XCopyArea(server.dsp, panel->temp_pmap, panel->main_win, server.gc, 0, 0, panel->area.width, panel->area.height, 0, 0);
846 }
847 XFlush (server.dsp);
848
849 if (refresh_systray) {
850 refresh_systray = 0;
851 panel = (Panel*)systray.area.panel;
852 // tint2 doen't draw systray icons. it just redraw background.
853 XSetWindowBackgroundPixmap (server.dsp, panel->main_win, panel->temp_pmap);
854 // force icon's refresh
855 refresh_systray_icon();
856 }
857 }
858 }
859 }
860
861
This page took 0.081326 seconds and 5 git commands to generate.