1 /**************************************************************************
3 * Copyright (C) 2008 Pål Staurland (staura@gmail.com)
4 * Modified (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 **************************************************************************/
23 #include <X11/Xutil.h>
24 #include <X11/Xatom.h>
26 #include <cairo-xlib.h>
27 #include <pango/pangocairo.h>
38 // --------------------------------------------------
43 int mouse_scroll_down
;
49 int panel_dock
=0; // default not in the dock
50 int panel_layer
=BOTTOM_LAYER
; // default is bottom layer
56 int panel_autohide
= 0;
57 int panel_autohide_show_timeout
= 0;
58 int panel_autohide_hide_timeout
= 0;
59 int panel_autohide_height
= 5; // for vertical panels this is of course the width
60 int panel_strut_policy
= STRUT_MINIMUM
;
66 // panel's initial config
68 // panels (one panel per monitor)
72 GArray
* backgrounds
= 0;
74 Imlib_Image default_icon
= NULL
;
77 void autohide_hide(void* p
);
78 void autohide_show(void* p
);
86 if (panel_config
.monitor
> (server
.nb_monitor
-1)) {
87 // server.nb_monitor minimum value is 1 (see get_monitors())
88 fprintf(stderr
, "warning : monitor not found. tint2 default to all monitors.\n");
89 panel_config
.monitor
= 0;
100 for (i
=0 ; i
< nb_panel
; i
++) {
101 autohide_show(&panel1
[i
]);
102 free_area(&panel1
[i
].area
);
103 if (panel1
[i
].temp_pmap
) {
104 XFreePixmap(server
.dsp
, panel1
[i
].temp_pmap
);
105 panel1
[i
].temp_pmap
= 0;
110 old_nb_panel
= nb_panel
;
111 if (panel_config
.monitor
>= 0)
114 nb_panel
= server
.nb_monitor
;
117 for (i
=nb_panel
; i
< old_nb_panel
; i
++) {
118 if (panel1
[i
].main_win
) {
119 XDestroyWindow(server
.dsp
, panel1
[i
].main_win
);
120 panel1
[i
].main_win
= 0;
124 // alloc & init new panel
126 if (nb_panel
!= old_nb_panel
)
127 new_panel
= realloc(panel1
, nb_panel
* sizeof(Panel
));
130 for (i
=0 ; i
< nb_panel
; i
++) {
131 old_win
= new_panel
[i
].main_win
;
132 memcpy(&new_panel
[i
], &panel_config
, sizeof(Panel
));
133 new_panel
[i
].main_win
= old_win
;
136 fprintf(stderr
, "tint2 : nb monitor %d, nb monitor used %d, nb desktop %d\n", server
.nb_monitor
, nb_panel
, server
.nb_desktop
);
137 for (i
=0 ; i
< nb_panel
; i
++) {
140 if (panel_config
.monitor
< 0)
144 p
->area
.on_screen
= 1;
146 p
->area
._resize
= resize_panel
;
147 p
->g_taskbar
.area
.parent
= p
;
148 p
->g_taskbar
.area
.panel
= p
;
149 p
->g_task
.area
.panel
= p
;
150 init_panel_size_and_position(p
);
154 p
->area
.list
= g_slist_append(p
->area
.list
, &p
->clock
);
156 #ifdef ENABLE_BATTERY
157 if (battery_enabled
) {
158 init_battery_panel(p
);
159 p
->area
.list
= g_slist_append(p
->area
.list
, &p
->battery
);
162 // systray only on first panel
163 if (systray
.area
.on_screen
&& i
== 0) {
164 init_systray_panel(p
);
165 p
->area
.list
= g_slist_append(p
->area
.list
, &systray
);
169 if (i
>= old_nb_panel
) {
170 // new panel : catch some events
171 XSetWindowAttributes att
= { .colormap
=server
.colormap
, .background_pixel
=0, .border_pixel
=0 };
172 unsigned long mask
= CWEventMask
|CWColormap
|CWBackPixel
|CWBorderPixel
;
173 p
->main_win
= XCreateWindow(server
.dsp
, server
.root_win
, p
->posx
, p
->posy
, p
->area
.width
, p
->area
.height
, 0, server
.depth
, InputOutput
, server
.visual
, mask
, &att
);
177 XMoveResizeWindow(server
.dsp
, p
->main_win
, p
->posx
, p
->posy
, p
->area
.width
, p
->area
.height
);
180 long event_mask
= ExposureMask
|ButtonPressMask
|ButtonReleaseMask
|ButtonMotionMask
;
181 if (g_tooltip
.enabled
)
182 event_mask
|= PointerMotionMask
|LeaveWindowMask
;
184 event_mask
|= LeaveWindowMask
|EnterWindowMask
;
185 XChangeWindowAttributes(server
.dsp
, p
->main_win
, CWEventMask
, &(XSetWindowAttributes
){.event_mask
=event_mask
});
189 server
.gc
= XCreateGC(server
.dsp
, p
->main_win
, 0, &gcv
);
191 //printf("panel %d : %d, %d, %d, %d\n", i, p->posx, p->posy, p->area.width, p->area.height);
192 set_panel_properties(p
);
193 set_panel_background(p
);
194 if (i
>= old_nb_panel
&& snapshot_path
== 0) {
195 // if we are not in 'snapshot' mode then map new panel
196 XMapWindow (server
.dsp
, p
->main_win
);
200 add_timeout(panel_autohide_hide_timeout
, 0, autohide_hide
, p
);
207 task_refresh_tasklist();
212 void init_panel_size_and_position(Panel
*panel
)
215 if (panel_horizontal
) {
216 if (panel
->pourcentx
)
217 panel
->area
.width
= (float)server
.monitor
[panel
->monitor
].width
* panel
->area
.width
/ 100;
218 if (panel
->pourcenty
)
219 panel
->area
.height
= (float)server
.monitor
[panel
->monitor
].height
* panel
->area
.height
/ 100;
220 if (panel
->area
.bg
->border
.rounded
> panel
->area
.height
/2) {
221 printf("panel_background_id rounded is too big... please fix your tint2rc\n");
222 g_array_append_val(backgrounds
, *panel
->area
.bg
);
223 panel
->area
.bg
= &g_array_index(backgrounds
, Background
, backgrounds
->len
-1);
224 panel
->area
.bg
->border
.rounded
= panel
->area
.height
/2;
228 int old_panel_height
= panel
->area
.height
;
229 if (panel
->pourcentx
)
230 panel
->area
.height
= (float)server
.monitor
[panel
->monitor
].height
* panel
->area
.width
/ 100;
232 panel
->area
.height
= panel
->area
.width
;
233 if (panel
->pourcenty
)
234 panel
->area
.width
= (float)server
.monitor
[panel
->monitor
].width
* old_panel_height
/ 100;
236 panel
->area
.width
= old_panel_height
;
237 if (panel
->area
.bg
->border
.rounded
> panel
->area
.width
/2) {
238 printf("panel_background_id rounded is too big... please fix your tint2rc\n");
239 g_array_append_val(backgrounds
, *panel
->area
.bg
);
240 panel
->area
.bg
= &g_array_index(backgrounds
, Background
, backgrounds
->len
-1);
241 panel
->area
.bg
->border
.rounded
= panel
->area
.width
/2;
245 // panel position determined here
246 if (panel_position
& LEFT
) {
247 panel
->posx
= server
.monitor
[panel
->monitor
].x
+ panel
->marginx
;
250 if (panel_position
& RIGHT
) {
251 panel
->posx
= server
.monitor
[panel
->monitor
].x
+ server
.monitor
[panel
->monitor
].width
- panel
->area
.width
- panel
->marginx
;
254 if (panel_horizontal
)
255 panel
->posx
= server
.monitor
[panel
->monitor
].x
+ ((server
.monitor
[panel
->monitor
].width
- panel
->area
.width
) / 2);
257 panel
->posx
= server
.monitor
[panel
->monitor
].x
+ panel
->marginx
;
260 if (panel_position
& TOP
) {
261 panel
->posy
= server
.monitor
[panel
->monitor
].y
+ panel
->marginy
;
264 if (panel_position
& BOTTOM
) {
265 panel
->posy
= server
.monitor
[panel
->monitor
].y
+ server
.monitor
[panel
->monitor
].height
- panel
->area
.height
- panel
->marginy
;
268 panel
->posy
= server
.monitor
[panel
->monitor
].y
+ ((server
.monitor
[panel
->monitor
].height
- panel
->area
.height
) / 2);
272 if (panel_autohide
) {
273 int diff
= (panel_horizontal
? panel
->area
.height
: panel
->area
.width
) - panel_autohide_height
;
274 if (panel_horizontal
) {
275 panel
->hidden_width
= panel
->area
.width
;
276 panel
->hidden_height
= panel
->area
.height
- diff
;
279 panel
->hidden_width
= panel
->area
.width
- diff
;
280 panel
->hidden_height
= panel
->area
.height
;
283 // printf("panel : posx %d, posy %d, width %d, height %d\n", panel->posx, panel->posy, panel->area.width, panel->area.height);
298 for (i
=0 ; i
< nb_panel
; i
++) {
304 XFreePixmap(server
.dsp
, p
->temp_pmap
);
307 if (p
->hidden_pixmap
)
308 XFreePixmap(server
.dsp
, p
->hidden_pixmap
);
309 p
->hidden_pixmap
= 0;
311 XDestroyWindow(server
.dsp
, p
->main_win
);
322 if (panel_config
.g_task
.font_desc
) {
323 pango_font_description_free(panel_config
.g_task
.font_desc
);
324 panel_config
.g_task
.font_desc
= 0;
328 g_array_free(backgrounds
, 1);
334 void resize_panel(void *obj
)
336 Panel
*panel
= (Panel
*)obj
;
338 if (panel_horizontal
) {
339 int taskbar_width
, modulo_width
= 0;
341 taskbar_width
= panel
->area
.width
- (2 * panel
->area
.paddingxlr
) - (2 * panel
->area
.bg
->border
.width
);
342 if (panel
->clock
.area
.on_screen
&& panel
->clock
.area
.width
)
343 taskbar_width
-= (panel
->clock
.area
.width
+ panel
->area
.paddingx
);
344 #ifdef ENABLE_BATTERY
345 if (panel
->battery
.area
.on_screen
&& panel
->battery
.area
.width
)
346 taskbar_width
-= (panel
->battery
.area
.width
+ panel
->area
.paddingx
);
348 // TODO : systray only on first panel. search better implementation !
349 if (systray
.area
.on_screen
&& systray
.area
.width
&& panel
== &panel1
[0])
350 taskbar_width
-= (systray
.area
.width
+ panel
->area
.paddingx
);
352 if (panel_mode
== MULTI_DESKTOP
) {
353 int width
= taskbar_width
- ((panel
->nb_desktop
-1) * panel
->area
.paddingx
);
354 taskbar_width
= width
/ panel
->nb_desktop
;
355 modulo_width
= width
% panel
->nb_desktop
;
358 // change posx and width for all taskbar
360 posx
= panel
->area
.bg
->border
.width
+ panel
->area
.paddingxlr
;
361 for (i
=0 ; i
< panel
->nb_desktop
; i
++) {
362 panel
->taskbar
[i
].area
.posx
= posx
;
363 panel
->taskbar
[i
].area
.width
= taskbar_width
;
364 panel
->taskbar
[i
].area
.resize
= 1;
366 panel
->taskbar
[i
].area
.width
++;
369 //printf("taskbar %d : posx %d, width, %d, posy %d\n", i, posx, panel->taskbar[i].area.width, posx + panel->taskbar[i].area.width);
370 if (panel_mode
== MULTI_DESKTOP
)
371 posx
+= panel
->taskbar
[i
].area
.width
+ panel
->area
.paddingx
;
375 int taskbar_height
, modulo_height
= 0;
378 taskbar_height
= panel
->area
.height
- (2 * panel
->area
.paddingxlr
) - (2 * panel
->area
.bg
->border
.width
);
379 if (panel
->clock
.area
.on_screen
&& panel
->clock
.area
.height
)
380 taskbar_height
-= (panel
->clock
.area
.height
+ panel
->area
.paddingx
);
381 #ifdef ENABLE_BATTERY
382 if (panel
->battery
.area
.on_screen
&& panel
->battery
.area
.height
)
383 taskbar_height
-= (panel
->battery
.area
.height
+ panel
->area
.paddingx
);
385 // TODO : systray only on first panel. search better implementation !
386 if (systray
.area
.on_screen
&& systray
.area
.height
&& panel
== &panel1
[0])
387 taskbar_height
-= (systray
.area
.height
+ panel
->area
.paddingx
);
389 posy
= panel
->area
.height
- panel
->area
.bg
->border
.width
- panel
->area
.paddingxlr
- taskbar_height
;
390 if (panel_mode
== MULTI_DESKTOP
) {
391 int height
= taskbar_height
- ((panel
->nb_desktop
-1) * panel
->area
.paddingx
);
392 taskbar_height
= height
/ panel
->nb_desktop
;
393 modulo_height
= height
% panel
->nb_desktop
;
396 // change posy and height for all taskbar
397 for (i
=0 ; i
< panel
->nb_desktop
; i
++) {
398 panel
->taskbar
[i
].area
.posy
= posy
;
399 panel
->taskbar
[i
].area
.height
= taskbar_height
;
400 panel
->taskbar
[i
].area
.resize
= 1;
402 panel
->taskbar
[i
].area
.height
++;
405 if (panel_mode
== MULTI_DESKTOP
)
406 posy
+= panel
->taskbar
[i
].area
.height
+ panel
->area
.paddingx
;
412 void visible_object()
417 for (i
=0 ; i
< nb_panel
; i
++) {
421 for (j
=0 ; j
< panel
->nb_desktop
; j
++) {
422 taskbar
= &panel
->taskbar
[j
];
423 if (panel_mode
!= MULTI_DESKTOP
&& taskbar
->desktop
!= server
.desktop
) {
424 // SINGLE_DESKTOP and not current desktop
425 taskbar
->area
.on_screen
= 0;
428 taskbar
->area
.on_screen
= 1;
435 void update_strut(Panel
* p
)
437 if (panel_strut_policy
== STRUT_NONE
) {
438 XDeleteProperty(server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT
);
439 XDeleteProperty(server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT_PARTIAL
);
444 unsigned int d1
, screen_width
, screen_height
;
447 XGetGeometry(server
.dsp
, server
.root_win
, &d2
, &d3
, &d3
, &screen_width
, &screen_height
, &d1
, &d1
);
448 Monitor monitor
= server
.monitor
[p
->monitor
];
449 long struts
[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
450 if (panel_horizontal
) {
451 int height
= p
->area
.height
+ p
->marginy
;
452 if (panel_autohide
&& (panel_strut_policy
== STRUT_MINIMUM
|| (panel_strut_policy
== STRUT_FOLLOW_SIZE
&& p
->is_hidden
)) )
453 height
= p
->hidden_height
;
454 if (panel_position
& TOP
) {
455 struts
[2] = height
+ monitor
.y
;
457 // p->area.width - 1 allowed full screen on monitor 2
458 struts
[9] = p
->posx
+ p
->area
.width
- 1;
461 struts
[3] = height
+ screen_height
- monitor
.y
- monitor
.height
;
462 struts
[10] = p
->posx
;
463 // p->area.width - 1 allowed full screen on monitor 2
464 struts
[11] = p
->posx
+ p
->area
.width
- 1;
468 int width
= p
->area
.width
+ p
->marginx
;
469 if (panel_autohide
&& (panel_strut_policy
== STRUT_MINIMUM
|| (panel_strut_policy
== STRUT_FOLLOW_SIZE
&& p
->is_hidden
)) )
470 width
= p
->hidden_width
;
471 if (panel_position
& LEFT
) {
472 struts
[0] = width
+ monitor
.x
;
474 // p->area.width - 1 allowed full screen on monitor 2
475 struts
[5] = p
->posy
+ p
->area
.height
- 1;
478 struts
[1] = width
+ screen_width
- monitor
.x
- monitor
.width
;
480 // p->area.width - 1 allowed full screen on monitor 2
481 struts
[7] = p
->posy
+ p
->area
.height
- 1;
484 // Old specification : fluxbox need _NET_WM_STRUT.
485 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 4);
486 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT_PARTIAL
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 12);
490 void set_panel_properties(Panel
*p
)
492 XStoreName (server
.dsp
, p
->main_win
, "tint2");
495 gchar
*name
= g_locale_to_utf8("tint2", -1, NULL
, &len
, NULL
);
497 XChangeProperty(server
.dsp
, p
->main_win
, server
.atom
._NET_WM_NAME
, server
.atom
.UTF8_STRING
, 8, PropModeReplace
, (unsigned char *) name
, (int) len
);
502 long val
= server
.atom
._NET_WM_WINDOW_TYPE_DOCK
;
503 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_WINDOW_TYPE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
505 // Sticky and below other window
507 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_DESKTOP
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
509 state
[0] = server
.atom
._NET_WM_STATE_SKIP_PAGER
;
510 state
[1] = server
.atom
._NET_WM_STATE_SKIP_TASKBAR
;
511 state
[2] = server
.atom
._NET_WM_STATE_STICKY
;
512 state
[3] = panel_layer
== BOTTOM_LAYER
? server
.atom
._NET_WM_STATE_BELOW
: server
.atom
._NET_WM_STATE_ABOVE
;
513 int nb_atoms
= panel_layer
== NORMAL_LAYER
? 3 : 4;
514 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STATE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) state
, nb_atoms
);
519 wmhints
.icon_window
= wmhints
.window_group
= p
->main_win
;
520 wmhints
.flags
= StateHint
| IconWindowHint
;
521 wmhints
.initial_state
= WithdrawnState
;
524 wmhints
.flags
= InputHint
;
525 wmhints
.input
= False
;
527 XSetWMHints(server
.dsp
, p
->main_win
, &wmhints
);
530 long prop
[5] = { 2, 0, 0, 0, 0 };
531 XChangeProperty(server
.dsp
, p
->main_win
, server
.atom
._MOTIF_WM_HINTS
, server
.atom
._MOTIF_WM_HINTS
, 32, PropModeReplace
, (unsigned char *) prop
, 5);
533 // XdndAware - Register for Xdnd events
535 XChangeProperty(server
.dsp
, p
->main_win
, server
.atom
.XdndAware
, XA_ATOM
, 32, PropModeReplace
, (unsigned char*)&version
, 1);
539 // Fixed position and non-resizable window
540 // Allow panel move and resize when tint2 reload config file
541 int minwidth
= panel_autohide
? p
->hidden_width
: p
->area
.width
;
542 int minheight
= panel_autohide
? p
->hidden_height
: p
->area
.height
;
543 XSizeHints size_hints
;
544 size_hints
.flags
= PPosition
|PMinSize
|PMaxSize
;
545 size_hints
.min_width
= minwidth
;
546 size_hints
.max_width
= p
->area
.width
;
547 size_hints
.min_height
= minheight
;
548 size_hints
.max_height
= p
->area
.height
;
549 XSetWMNormalHints(server
.dsp
, p
->main_win
, &size_hints
);
552 XClassHint
* classhint
= XAllocClassHint();
553 classhint
->res_name
= "tint2";
554 classhint
->res_class
= "Tint2";
555 XSetClassHint(server
.dsp
, p
->main_win
, classhint
);
560 void set_panel_background(Panel
*p
)
562 if (p
->area
.pix
) XFreePixmap (server
.dsp
, p
->area
.pix
);
563 p
->area
.pix
= XCreatePixmap (server
.dsp
, server
.root_win
, p
->area
.width
, p
->area
.height
, server
.depth
);
566 if (panel_horizontal
&& panel_position
& BOTTOM
)
567 yoff
= p
->area
.height
-p
->hidden_height
;
568 else if (!panel_horizontal
&& panel_position
& RIGHT
)
569 xoff
= p
->area
.width
-p
->hidden_width
;
571 if (real_transparency
) {
572 clear_pixmap(p
->area
.pix
, 0, 0, p
->area
.width
, p
->area
.height
);
576 // copy background (server.root_pmap) in panel.area.pix
579 XTranslateCoordinates(server
.dsp
, p
->main_win
, server
.root_win
, 0, 0, &x
, &y
, &dummy
);
580 if (panel_autohide
&& p
->is_hidden
) {
584 XSetTSOrigin(server
.dsp
, server
.gc
, -x
, -y
);
585 XFillRectangle(server
.dsp
, p
->area
.pix
, server
.gc
, 0, 0, p
->area
.width
, p
->area
.height
);
588 // draw background panel
591 cs
= cairo_xlib_surface_create (server
.dsp
, p
->area
.pix
, server
.visual
, p
->area
.width
, p
->area
.height
);
592 c
= cairo_create (cs
);
593 draw_background(&p
->area
, c
);
595 cairo_surface_destroy (cs
);
597 if (panel_autohide
) {
598 if (p
->hidden_pixmap
) XFreePixmap(server
.dsp
, p
->hidden_pixmap
);
599 p
->hidden_pixmap
= XCreatePixmap(server
.dsp
, server
.root_win
, p
->hidden_width
, p
->hidden_height
, server
.depth
);
600 XCopyArea(server
.dsp
, p
->area
.pix
, p
->hidden_pixmap
, server
.gc
, xoff
, yoff
, p
->hidden_width
, p
->hidden_height
, 0, 0);
603 // redraw panel's object
606 for (l0
= p
->area
.list
; l0
; l0
= l0
->next
) {
610 // reset task 'state_pix'
613 for (i
=0 ; i
< p
->nb_desktop
; i
++) {
614 tskbar
= &p
->taskbar
[i
];
615 for (l0
= tskbar
->area
.list
; l0
; l0
= l0
->next
) {
616 set_task_redraw((Task
*)l0
->data
);
622 Panel
*get_panel(Window win
)
625 for (i
=0 ; i
< nb_panel
; i
++) {
626 if (panel1
[i
].main_win
== win
) {
634 Taskbar
*click_taskbar (Panel
*panel
, int x
, int y
)
639 if (panel_horizontal
) {
640 for (i
=0; i
< panel
->nb_desktop
; i
++) {
641 tskbar
= &panel
->taskbar
[i
];
642 if (tskbar
->area
.on_screen
&& x
>= tskbar
->area
.posx
&& x
<= (tskbar
->area
.posx
+ tskbar
->area
.width
))
647 for (i
=0; i
< panel
->nb_desktop
; i
++) {
648 tskbar
= &panel
->taskbar
[i
];
649 if (tskbar
->area
.on_screen
&& y
>= tskbar
->area
.posy
&& y
<= (tskbar
->area
.posy
+ tskbar
->area
.height
))
657 Task
*click_task (Panel
*panel
, int x
, int y
)
662 if ( (tskbar
= click_taskbar(panel
, x
, y
)) ) {
663 if (panel_horizontal
) {
665 for (l0
= tskbar
->area
.list
; l0
; l0
= l0
->next
) {
667 if (tsk
->area
.on_screen
&& x
>= tsk
->area
.posx
&& x
<= (tsk
->area
.posx
+ tsk
->area
.width
)) {
674 for (l0
= tskbar
->area
.list
; l0
; l0
= l0
->next
) {
676 if (tsk
->area
.on_screen
&& y
>= tsk
->area
.posy
&& y
<= (tsk
->area
.posy
+ tsk
->area
.height
)) {
686 int click_padding(Panel
*panel
, int x
, int y
)
688 if (panel_horizontal
) {
689 if (x
< panel
->area
.paddingxlr
|| x
> panel
->area
.width
-panel
->area
.paddingxlr
)
693 if (y
< panel
->area
.paddingxlr
|| y
> panel
->area
.height
-panel
->area
.paddingxlr
)
700 int click_clock(Panel
*panel
, int x
, int y
)
702 Clock clk
= panel
->clock
;
703 if (panel_horizontal
) {
704 if (clk
.area
.on_screen
&& x
>= clk
.area
.posx
&& x
<= (clk
.area
.posx
+ clk
.area
.width
))
707 if (clk
.area
.on_screen
&& y
>= clk
.area
.posy
&& y
<= (clk
.area
.posy
+ clk
.area
.height
))
714 Area
* click_area(Panel
*panel
, int x
, int y
)
716 Area
* result
= &panel
->area
;
717 Area
* new_result
= result
;
720 GSList
* it
= result
->list
;
723 if (panel_horizontal
) {
724 if (a
->on_screen
&& x
>= a
->posx
&& x
<= (a
->posx
+ a
->width
)) {
729 if (a
->on_screen
&& y
>= a
->posy
&& y
<= (a
->posy
+ a
->height
)) {
736 } while (new_result
!= result
);
741 void stop_autohide_timeout(Panel
* p
)
743 if (p
->autohide_timeout
) {
744 stop_timeout(p
->autohide_timeout
);
745 p
->autohide_timeout
= 0;
750 void autohide_show(void* p
)
753 stop_autohide_timeout(panel
);
754 panel
->is_hidden
= 0;
755 if (panel_strut_policy
== STRUT_FOLLOW_SIZE
)
758 XMapSubwindows(server
.dsp
, panel
->main_win
); // systray windows
759 if (panel_horizontal
) {
760 if (panel_position
& TOP
)
761 XResizeWindow(server
.dsp
, panel
->main_win
, panel
->area
.width
, panel
->area
.height
);
763 XMoveResizeWindow(server
.dsp
, panel
->main_win
, panel
->posx
, panel
->posy
, panel
->area
.width
, panel
->area
.height
);
766 if (panel_position
& LEFT
)
767 XResizeWindow(server
.dsp
, panel
->main_win
, panel
->area
.width
, panel
->area
.height
);
769 XMoveResizeWindow(server
.dsp
, panel
->main_win
, panel
->posx
, panel
->posy
, panel
->area
.width
, panel
->area
.height
);
771 refresh_systray
= 1; // ugly hack, because we actually only need to call XSetBackgroundPixmap
776 void autohide_hide(void* p
)
779 stop_autohide_timeout(panel
);
780 panel
->is_hidden
= 1;
781 if (panel_strut_policy
== STRUT_FOLLOW_SIZE
)
784 XUnmapSubwindows(server
.dsp
, panel
->main_win
); // systray windows
785 int diff
= (panel_horizontal
? panel
->area
.height
: panel
->area
.width
) - panel_autohide_height
;
786 if (panel_horizontal
) {
787 if (panel_position
& TOP
)
788 XResizeWindow(server
.dsp
, panel
->main_win
, panel
->hidden_width
, panel
->hidden_height
);
790 XMoveResizeWindow(server
.dsp
, panel
->main_win
, panel
->posx
, panel
->posy
+diff
, panel
->hidden_width
, panel
->hidden_height
);
793 if (panel_position
& LEFT
)
794 XResizeWindow(server
.dsp
, panel
->main_win
, panel
->hidden_width
, panel
->hidden_height
);
796 XMoveResizeWindow(server
.dsp
, panel
->main_win
, panel
->posx
+diff
, panel
->posy
, panel
->hidden_width
, panel
->hidden_height
);
802 void autohide_trigger_show(Panel
* p
)
806 if (p
->autohide_timeout
)
807 change_timeout(p
->autohide_timeout
, panel_autohide_show_timeout
, 0, autohide_show
, p
);
809 p
->autohide_timeout
= add_timeout(panel_autohide_show_timeout
, 0, autohide_show
, p
);
813 void autohide_trigger_hide(Panel
* p
)
821 if (XQueryPointer(server
.dsp
, p
->main_win
, &root
, &child
, &xr
, &yr
, &xw
, &yw
, &mask
))
822 if (child
) return; // mouse over one of the system tray icons
824 if (p
->autohide_timeout
)
825 change_timeout(p
->autohide_timeout
, panel_autohide_hide_timeout
, 0, autohide_hide
, p
);
827 p
->autohide_timeout
= add_timeout(panel_autohide_hide_timeout
, 0, autohide_hide
, p
);