1 /**************************************************************************
3 * Copyright (C) 2008 Pål Staurland (staura@gmail.com)
4 * Modified (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr) from Omega distribution
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
;
57 int panel_autohide_show_timeout
;
58 int panel_autohide_hide_timeout
;
59 int panel_autohide_height
;
60 int panel_strut_policy
;
61 char *panel_items_order
;
65 // panel's initial config
67 // panels (one panel per monitor)
73 Imlib_Image default_icon
;
82 panel_position
= CENTER
;
83 panel_items_order
= 0;
85 panel_autohide_show_timeout
= 0;
86 panel_autohide_hide_timeout
= 0;
87 panel_autohide_height
= 5; // for vertical panels this is of course the width
88 panel_strut_policy
= STRUT_FOLLOW_SIZE
;
89 panel_dock
= 0; // default not in the dock
90 panel_layer
= BOTTOM_LAYER
; // default is bottom layer
93 backgrounds
= g_array_new(0, 0, sizeof(Background
));
95 memset(&panel_config
, 0, sizeof(Panel
));
97 // append full transparency background
98 Background transparent_bg
;
99 memset(&transparent_bg
, 0, sizeof(Background
));
100 g_array_append_val(backgrounds
, transparent_bg
);
108 // taskbarname_font_desc freed here because cleanup_taskbarname() called on _NET_NUMBER_OF_DESKTOPS
109 if (taskbarname_font_desc
) pango_font_description_free(taskbarname_font_desc
);
113 for (i
=0 ; i
< nb_panel
; i
++) {
117 if (p
->temp_pmap
) XFreePixmap(server
.dsp
, p
->temp_pmap
);
118 if (p
->hidden_pixmap
) XFreePixmap(server
.dsp
, p
->hidden_pixmap
);
119 if (p
->main_win
) XDestroyWindow(server
.dsp
, p
->main_win
);
122 if (panel_items_order
) g_free(panel_items_order
);
123 if (panel1
) free(panel1
);
125 g_array_free(backgrounds
, 1);
126 if (panel_config
.g_task
.font_desc
) pango_font_description_free(panel_config
.g_task
.font_desc
);
134 if (panel_config
.monitor
> (server
.nb_monitor
-1)) {
135 // server.nb_monitor minimum value is 1 (see get_monitors())
136 fprintf(stderr
, "warning : monitor not found. tint2 default to all monitors.\n");
137 panel_config
.monitor
= 0;
144 #ifdef ENABLE_BATTERY
149 // number of panels (one monitor or 'all' monitors)
150 if (panel_config
.monitor
>= 0)
153 nb_panel
= server
.nb_monitor
;
155 panel1
= malloc(nb_panel
* sizeof(Panel
));
156 for (i
=0 ; i
< nb_panel
; i
++) {
157 memcpy(&panel1
[i
], &panel_config
, sizeof(Panel
));
160 fprintf(stderr
, "tint2 : nb monitor %d, nb monitor used %d, nb desktop %d\n", server
.nb_monitor
, nb_panel
, server
.nb_desktop
);
161 for (i
=0 ; i
< nb_panel
; i
++) {
164 if (panel_config
.monitor
< 0)
166 if ( p
->area
.bg
== 0 )
167 p
->area
.bg
= &g_array_index(backgrounds
, Background
, 0);
170 p
->area
.on_screen
= 1;
172 p
->area
.size_mode
= SIZE_BY_LAYOUT
;
173 p
->area
._resize
= resize_panel
;
174 init_panel_size_and_position(p
);
175 // add childs according to panel_items
176 for (k
=0 ; k
< strlen(panel_items_order
) ; k
++) {
177 if (panel_items_order
[k
] == 'L')
178 init_launcher_panel(p
);
179 if (panel_items_order
[k
] == 'T')
180 init_taskbar_panel(p
);
181 #ifdef ENABLE_BATTERY
182 if (panel_items_order
[k
] == 'B')
183 init_battery_panel(p
);
185 if (panel_items_order
[k
] == 'S' && i
==0) {
186 // TODO : check systray is only on 1 panel
187 // at the moment only on panel1[0] allowed
188 init_systray_panel(p
);
191 if (panel_items_order
[k
] == 'C')
194 if (panel_items_order
[k
] == 'F')
195 init_freespace_panel(p
);
197 set_panel_items_order(p
);
200 XSetWindowAttributes att
= { .colormap
=server
.colormap
, .background_pixel
=0, .border_pixel
=0 };
201 unsigned long mask
= CWEventMask
|CWColormap
|CWBackPixel
|CWBorderPixel
;
202 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
);
204 long event_mask
= ExposureMask
|ButtonPressMask
|ButtonReleaseMask
|ButtonMotionMask
;
205 if (p
->g_task
.tooltip_enabled
|| p
->clock
.area
._get_tooltip_text
|| (launcher_enabled
&& launcher_tooltip_enabled
))
206 event_mask
|= PointerMotionMask
|LeaveWindowMask
;
208 event_mask
|= LeaveWindowMask
|EnterWindowMask
;
209 XChangeWindowAttributes(server
.dsp
, p
->main_win
, CWEventMask
, &(XSetWindowAttributes
){.event_mask
=event_mask
});
213 server
.gc
= XCreateGC(server
.dsp
, p
->main_win
, 0, &gcv
);
215 //printf("panel %d : %d, %d, %d, %d\n", i, p->posx, p->posy, p->area.width, p->area.height);
216 set_panel_properties(p
);
217 set_panel_background(p
);
218 if (snapshot_path
== 0) {
219 // if we are not in 'snapshot' mode then map new panel
220 XMapWindow (server
.dsp
, p
->main_win
);
224 add_timeout(panel_autohide_hide_timeout
, 0, autohide_hide
, p
);
229 task_refresh_tasklist();
234 void init_panel_size_and_position(Panel
*panel
)
237 if (panel_horizontal
) {
238 if (panel
->pourcentx
)
239 panel
->area
.width
= (float)server
.monitor
[panel
->monitor
].width
* panel
->area
.width
/ 100;
240 if (panel
->pourcenty
)
241 panel
->area
.height
= (float)server
.monitor
[panel
->monitor
].height
* panel
->area
.height
/ 100;
242 if (panel
->area
.width
+ panel
->marginx
> server
.monitor
[panel
->monitor
].width
)
243 panel
->area
.width
= server
.monitor
[panel
->monitor
].width
- panel
->marginx
;
244 if (panel
->area
.bg
->border
.rounded
> panel
->area
.height
/2) {
245 printf("panel_background_id rounded is too big... please fix your tint2rc\n");
246 g_array_append_val(backgrounds
, *panel
->area
.bg
);
247 panel
->area
.bg
= &g_array_index(backgrounds
, Background
, backgrounds
->len
-1);
248 panel
->area
.bg
->border
.rounded
= panel
->area
.height
/2;
252 int old_panel_height
= panel
->area
.height
;
253 if (panel
->pourcentx
)
254 panel
->area
.height
= (float)server
.monitor
[panel
->monitor
].height
* panel
->area
.width
/ 100;
256 panel
->area
.height
= panel
->area
.width
;
257 if (panel
->pourcenty
)
258 panel
->area
.width
= (float)server
.monitor
[panel
->monitor
].width
* old_panel_height
/ 100;
260 panel
->area
.width
= old_panel_height
;
261 if (panel
->area
.height
+ panel
->marginy
> server
.monitor
[panel
->monitor
].height
)
262 panel
->area
.height
= server
.monitor
[panel
->monitor
].height
- panel
->marginy
;
263 if (panel
->area
.bg
->border
.rounded
> panel
->area
.width
/2) {
264 printf("panel_background_id rounded is too big... please fix your tint2rc\n");
265 g_array_append_val(backgrounds
, *panel
->area
.bg
);
266 panel
->area
.bg
= &g_array_index(backgrounds
, Background
, backgrounds
->len
-1);
267 panel
->area
.bg
->border
.rounded
= panel
->area
.width
/2;
271 // panel position determined here
272 if (panel_position
& LEFT
) {
273 panel
->posx
= server
.monitor
[panel
->monitor
].x
+ panel
->marginx
;
276 if (panel_position
& RIGHT
) {
277 panel
->posx
= server
.monitor
[panel
->monitor
].x
+ server
.monitor
[panel
->monitor
].width
- panel
->area
.width
- panel
->marginx
;
280 if (panel_horizontal
)
281 panel
->posx
= server
.monitor
[panel
->monitor
].x
+ ((server
.monitor
[panel
->monitor
].width
- panel
->area
.width
) / 2);
283 panel
->posx
= server
.monitor
[panel
->monitor
].x
+ panel
->marginx
;
286 if (panel_position
& TOP
) {
287 panel
->posy
= server
.monitor
[panel
->monitor
].y
+ panel
->marginy
;
290 if (panel_position
& BOTTOM
) {
291 panel
->posy
= server
.monitor
[panel
->monitor
].y
+ server
.monitor
[panel
->monitor
].height
- panel
->area
.height
- panel
->marginy
;
294 panel
->posy
= server
.monitor
[panel
->monitor
].y
+ ((server
.monitor
[panel
->monitor
].height
- panel
->area
.height
) / 2);
298 // autohide or strut_policy=minimum
299 int diff
= (panel_horizontal
? panel
->area
.height
: panel
->area
.width
) - panel_autohide_height
;
300 if (panel_horizontal
) {
301 panel
->hidden_width
= panel
->area
.width
;
302 panel
->hidden_height
= panel
->area
.height
- diff
;
305 panel
->hidden_width
= panel
->area
.width
- diff
;
306 panel
->hidden_height
= panel
->area
.height
;
308 // printf("panel : posx %d, posy %d, width %d, height %d\n", panel->posx, panel->posy, panel->area.width, panel->area.height);
312 int resize_panel(void *obj
)
314 resize_by_layout(obj
, 0);
316 //printf("resize_panel\n");
317 if (panel_mode
!= MULTI_DESKTOP
&& taskbar_enabled
) {
318 // propagate width/height on hidden taskbar
319 int i
, width
, height
;
320 Panel
*panel
= (Panel
*)obj
;
321 width
= panel
->taskbar
[server
.desktop
].area
.width
;
322 height
= panel
->taskbar
[server
.desktop
].area
.height
;
323 for (i
=0 ; i
< panel
->nb_desktop
; i
++) {
324 panel
->taskbar
[i
].area
.width
= width
;
325 panel
->taskbar
[i
].area
.height
= height
;
326 panel
->taskbar
[i
].area
.resize
= 1;
333 void update_strut(Panel
* p
)
335 if (panel_strut_policy
== STRUT_NONE
) {
336 XDeleteProperty(server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT
);
337 XDeleteProperty(server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT_PARTIAL
);
342 unsigned int d1
, screen_width
, screen_height
;
345 XGetGeometry(server
.dsp
, server
.root_win
, &d2
, &d3
, &d3
, &screen_width
, &screen_height
, &d1
, &d1
);
346 Monitor monitor
= server
.monitor
[p
->monitor
];
347 long struts
[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
348 if (panel_horizontal
) {
349 int height
= p
->area
.height
+ p
->marginy
;
350 if (panel_strut_policy
== STRUT_MINIMUM
|| (panel_strut_policy
== STRUT_FOLLOW_SIZE
&& p
->is_hidden
))
351 height
= p
->hidden_height
;
352 if (panel_position
& TOP
) {
353 struts
[2] = height
+ monitor
.y
;
355 // p->area.width - 1 allowed full screen on monitor 2
356 struts
[9] = p
->posx
+ p
->area
.width
- 1;
359 struts
[3] = height
+ screen_height
- monitor
.y
- monitor
.height
;
360 struts
[10] = p
->posx
;
361 // p->area.width - 1 allowed full screen on monitor 2
362 struts
[11] = p
->posx
+ p
->area
.width
- 1;
366 int width
= p
->area
.width
+ p
->marginx
;
367 if (panel_strut_policy
== STRUT_MINIMUM
|| (panel_strut_policy
== STRUT_FOLLOW_SIZE
&& p
->is_hidden
))
368 width
= p
->hidden_width
;
369 if (panel_position
& LEFT
) {
370 struts
[0] = width
+ monitor
.x
;
372 // p->area.width - 1 allowed full screen on monitor 2
373 struts
[5] = p
->posy
+ p
->area
.height
- 1;
376 struts
[1] = width
+ screen_width
- monitor
.x
- monitor
.width
;
378 // p->area.width - 1 allowed full screen on monitor 2
379 struts
[7] = p
->posy
+ p
->area
.height
- 1;
382 // Old specification : fluxbox need _NET_WM_STRUT.
383 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 4);
384 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT_PARTIAL
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 12);
388 void set_panel_items_order(Panel
*p
)
393 g_slist_free(p
->area
.list
);
397 for (k
=0 ; k
< strlen(panel_items_order
) ; k
++) {
398 if (panel_items_order
[k
] == 'L')
399 p
->area
.list
= g_slist_append(p
->area
.list
, &p
->launcher
);
400 if (panel_items_order
[k
] == 'T') {
401 for (j
=0 ; j
< p
->nb_desktop
; j
++)
402 p
->area
.list
= g_slist_append(p
->area
.list
, &p
->taskbar
[j
]);
404 #ifdef ENABLE_BATTERY
405 if (panel_items_order
[k
] == 'B')
406 p
->area
.list
= g_slist_append(p
->area
.list
, &p
->battery
);
408 if (panel_items_order
[k
] == 'S' && p
== panel1
) {
409 // TODO : check systray is only on 1 panel
410 // at the moment only on panel1[0] allowed
411 p
->area
.list
= g_slist_append(p
->area
.list
, &systray
);
413 if (panel_items_order
[k
] == 'C')
414 p
->area
.list
= g_slist_append(p
->area
.list
, &p
->clock
);
416 if (panel_items_order
[k
] == 'F')
417 p
->area
.list
= g_slist_append(p
->area
.list
, &p
->freespace
);
419 init_rendering(&p
->area
, 0);
423 void set_panel_properties(Panel
*p
)
425 XStoreName (server
.dsp
, p
->main_win
, "tint2");
428 gchar
*name
= g_locale_to_utf8("tint2", -1, NULL
, &len
, NULL
);
430 XChangeProperty(server
.dsp
, p
->main_win
, server
.atom
._NET_WM_NAME
, server
.atom
.UTF8_STRING
, 8, PropModeReplace
, (unsigned char *) name
, (int) len
);
435 long val
= server
.atom
._NET_WM_WINDOW_TYPE_DOCK
;
436 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_WINDOW_TYPE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
438 // Sticky and below other window
440 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_DESKTOP
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
442 state
[0] = server
.atom
._NET_WM_STATE_SKIP_PAGER
;
443 state
[1] = server
.atom
._NET_WM_STATE_SKIP_TASKBAR
;
444 state
[2] = server
.atom
._NET_WM_STATE_STICKY
;
445 state
[3] = panel_layer
== BOTTOM_LAYER
? server
.atom
._NET_WM_STATE_BELOW
: server
.atom
._NET_WM_STATE_ABOVE
;
446 int nb_atoms
= panel_layer
== NORMAL_LAYER
? 3 : 4;
447 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STATE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) state
, nb_atoms
);
452 wmhints
.icon_window
= wmhints
.window_group
= p
->main_win
;
453 wmhints
.flags
= StateHint
| IconWindowHint
;
454 wmhints
.initial_state
= WithdrawnState
;
457 wmhints
.flags
= InputHint
;
458 wmhints
.input
= False
;
460 XSetWMHints(server
.dsp
, p
->main_win
, &wmhints
);
463 long prop
[5] = { 2, 0, 0, 0, 0 };
464 XChangeProperty(server
.dsp
, p
->main_win
, server
.atom
._MOTIF_WM_HINTS
, server
.atom
._MOTIF_WM_HINTS
, 32, PropModeReplace
, (unsigned char *) prop
, 5);
466 // XdndAware - Register for Xdnd events
468 XChangeProperty(server
.dsp
, p
->main_win
, server
.atom
.XdndAware
, XA_ATOM
, 32, PropModeReplace
, (unsigned char*)&version
, 1);
472 // Fixed position and non-resizable window
473 // Allow panel move and resize when tint2 reload config file
474 int minwidth
= panel_autohide
? p
->hidden_width
: p
->area
.width
;
475 int minheight
= panel_autohide
? p
->hidden_height
: p
->area
.height
;
476 XSizeHints size_hints
;
477 size_hints
.flags
= PPosition
|PMinSize
|PMaxSize
;
478 size_hints
.min_width
= minwidth
;
479 size_hints
.max_width
= p
->area
.width
;
480 size_hints
.min_height
= minheight
;
481 size_hints
.max_height
= p
->area
.height
;
482 XSetWMNormalHints(server
.dsp
, p
->main_win
, &size_hints
);
485 XClassHint
* classhint
= XAllocClassHint();
486 classhint
->res_name
= "tint2";
487 classhint
->res_class
= "Tint2";
488 XSetClassHint(server
.dsp
, p
->main_win
, classhint
);
493 void set_panel_background(Panel
*p
)
495 if (p
->area
.pix
) XFreePixmap (server
.dsp
, p
->area
.pix
);
496 p
->area
.pix
= XCreatePixmap (server
.dsp
, server
.root_win
, p
->area
.width
, p
->area
.height
, server
.depth
);
499 if (panel_horizontal
&& panel_position
& BOTTOM
)
500 yoff
= p
->area
.height
-p
->hidden_height
;
501 else if (!panel_horizontal
&& panel_position
& RIGHT
)
502 xoff
= p
->area
.width
-p
->hidden_width
;
504 if (server
.real_transparency
) {
505 clear_pixmap(p
->area
.pix
, 0, 0, p
->area
.width
, p
->area
.height
);
509 // copy background (server.root_pmap) in panel.area.pix
512 XTranslateCoordinates(server
.dsp
, p
->main_win
, server
.root_win
, 0, 0, &x
, &y
, &dummy
);
513 if (panel_autohide
&& p
->is_hidden
) {
517 XSetTSOrigin(server
.dsp
, server
.gc
, -x
, -y
);
518 XFillRectangle(server
.dsp
, p
->area
.pix
, server
.gc
, 0, 0, p
->area
.width
, p
->area
.height
);
521 // draw background panel
524 cs
= cairo_xlib_surface_create (server
.dsp
, p
->area
.pix
, server
.visual
, p
->area
.width
, p
->area
.height
);
525 c
= cairo_create (cs
);
526 draw_background(&p
->area
, c
);
528 cairo_surface_destroy (cs
);
530 if (panel_autohide
) {
531 if (p
->hidden_pixmap
) XFreePixmap(server
.dsp
, p
->hidden_pixmap
);
532 p
->hidden_pixmap
= XCreatePixmap(server
.dsp
, server
.root_win
, p
->hidden_width
, p
->hidden_height
, server
.depth
);
533 XCopyArea(server
.dsp
, p
->area
.pix
, p
->hidden_pixmap
, server
.gc
, xoff
, yoff
, p
->hidden_width
, p
->hidden_height
, 0, 0);
536 // redraw panel's object
539 for (l0
= p
->area
.list
; l0
; l0
= l0
->next
) {
544 // reset task/taskbar 'state_pix'
547 for (i
=0 ; i
< p
->nb_desktop
; i
++) {
548 tskbar
= &p
->taskbar
[i
];
549 for (k
=0; k
<TASKBAR_STATE_COUNT
; ++k
) {
550 if (tskbar
->state_pix
[k
]) XFreePixmap(server
.dsp
, tskbar
->state_pix
[k
]);
551 tskbar
->state_pix
[k
] = 0;
552 if (tskbar
->bar_name
.state_pix
[k
]) XFreePixmap(server
.dsp
, tskbar
->bar_name
.state_pix
[k
]);
553 tskbar
->bar_name
.state_pix
[k
] = 0;
555 tskbar
->area
.pix
= 0;
556 tskbar
->bar_name
.area
.pix
= 0;
557 l0
= tskbar
->area
.list
;
558 if (taskbarname_enabled
) l0
= l0
->next
;
559 for (; l0
; l0
= l0
->next
) {
560 set_task_redraw((Task
*)l0
->data
);
566 Panel
*get_panel(Window win
)
569 for (i
=0 ; i
< nb_panel
; i
++) {
570 if (panel1
[i
].main_win
== win
) {
578 Taskbar
*click_taskbar (Panel
*panel
, int x
, int y
)
583 if (panel_horizontal
) {
584 for (i
=0; i
< panel
->nb_desktop
; i
++) {
585 tskbar
= &panel
->taskbar
[i
];
586 if (tskbar
->area
.on_screen
&& x
>= tskbar
->area
.posx
&& x
<= (tskbar
->area
.posx
+ tskbar
->area
.width
))
591 for (i
=0; i
< panel
->nb_desktop
; i
++) {
592 tskbar
= &panel
->taskbar
[i
];
593 if (tskbar
->area
.on_screen
&& y
>= tskbar
->area
.posy
&& y
<= (tskbar
->area
.posy
+ tskbar
->area
.height
))
601 Task
*click_task (Panel
*panel
, int x
, int y
)
606 if ( (tskbar
= click_taskbar(panel
, x
, y
)) ) {
607 if (panel_horizontal
) {
609 l0
= tskbar
->area
.list
;
610 if (taskbarname_enabled
) l0
= l0
->next
;
611 for (; l0
; l0
= l0
->next
) {
613 if (tsk
->area
.on_screen
&& x
>= tsk
->area
.posx
&& x
<= (tsk
->area
.posx
+ tsk
->area
.width
)) {
620 l0
= tskbar
->area
.list
;
621 if (taskbarname_enabled
) l0
= l0
->next
;
622 for (; l0
; l0
= l0
->next
) {
624 if (tsk
->area
.on_screen
&& y
>= tsk
->area
.posy
&& y
<= (tsk
->area
.posy
+ tsk
->area
.height
)) {
634 Launcher
*click_launcher (Panel
*panel
, int x
, int y
)
636 Launcher
*launcher
= &panel
->launcher
;
638 if (panel_horizontal
) {
639 if (launcher
->area
.on_screen
&& x
>= launcher
->area
.posx
&& x
<= (launcher
->area
.posx
+ launcher
->area
.width
))
643 if (launcher
->area
.on_screen
&& y
>= launcher
->area
.posy
&& y
<= (launcher
->area
.posy
+ launcher
->area
.height
))
650 LauncherIcon
*click_launcher_icon (Panel
*panel
, int x
, int y
)
655 //printf("Click x=%d y=%d\n", x, y);
656 if ( (launcher
= click_launcher(panel
, x
, y
)) ) {
658 for (l0
= launcher
->list_icons
; l0
; l0
= l0
->next
) {
660 if (x
>= (launcher
->area
.posx
+ icon
->x
) && x
<= (launcher
->area
.posx
+ icon
->x
+ icon
->icon_size
) &&
661 y
>= (launcher
->area
.posy
+ icon
->y
) && y
<= (launcher
->area
.posy
+ icon
->y
+ icon
->icon_size
)) {
662 //printf("Hit rect x=%d y=%d xmax=%d ymax=%d\n", launcher->area.posx + icon->x, launcher->area.posy + icon->y, launcher->area.posx + icon->x + icon->width, launcher->area.posy + icon->y + icon->height);
671 int click_padding(Panel
*panel
, int x
, int y
)
673 if (panel_horizontal
) {
674 if (x
< panel
->area
.paddingxlr
|| x
> panel
->area
.width
-panel
->area
.paddingxlr
)
678 if (y
< panel
->area
.paddingxlr
|| y
> panel
->area
.height
-panel
->area
.paddingxlr
)
685 int click_clock(Panel
*panel
, int x
, int y
)
687 Clock clk
= panel
->clock
;
688 if (panel_horizontal
) {
689 if (clk
.area
.on_screen
&& x
>= clk
.area
.posx
&& x
<= (clk
.area
.posx
+ clk
.area
.width
))
692 if (clk
.area
.on_screen
&& y
>= clk
.area
.posy
&& y
<= (clk
.area
.posy
+ clk
.area
.height
))
699 Area
* click_area(Panel
*panel
, int x
, int y
)
701 Area
* result
= &panel
->area
;
702 Area
* new_result
= result
;
705 GSList
* it
= result
->list
;
708 if (a
->on_screen
&& x
>= a
->posx
&& x
<= (a
->posx
+ a
->width
)
709 && y
>= a
->posy
&& y
<= (a
->posy
+ a
->height
)) {
715 } while (new_result
!= result
);
720 void stop_autohide_timeout(Panel
* p
)
722 if (p
->autohide_timeout
) {
723 stop_timeout(p
->autohide_timeout
);
724 p
->autohide_timeout
= 0;
729 void autohide_show(void* p
)
732 stop_autohide_timeout(panel
);
733 panel
->is_hidden
= 0;
734 if (panel_strut_policy
== STRUT_FOLLOW_SIZE
)
737 XMapSubwindows(server
.dsp
, panel
->main_win
); // systray windows
738 if (panel_horizontal
) {
739 if (panel_position
& TOP
)
740 XResizeWindow(server
.dsp
, panel
->main_win
, panel
->area
.width
, panel
->area
.height
);
742 XMoveResizeWindow(server
.dsp
, panel
->main_win
, panel
->posx
, panel
->posy
, panel
->area
.width
, panel
->area
.height
);
745 if (panel_position
& LEFT
)
746 XResizeWindow(server
.dsp
, panel
->main_win
, panel
->area
.width
, panel
->area
.height
);
748 XMoveResizeWindow(server
.dsp
, panel
->main_win
, panel
->posx
, panel
->posy
, panel
->area
.width
, panel
->area
.height
);
750 refresh_systray
= 1; // ugly hack, because we actually only need to call XSetBackgroundPixmap
755 void autohide_hide(void* p
)
758 stop_autohide_timeout(panel
);
759 panel
->is_hidden
= 1;
760 if (panel_strut_policy
== STRUT_FOLLOW_SIZE
)
763 XUnmapSubwindows(server
.dsp
, panel
->main_win
); // systray windows
764 int diff
= (panel_horizontal
? panel
->area
.height
: panel
->area
.width
) - panel_autohide_height
;
765 //printf("autohide_hide : diff %d, w %d, h %d\n", diff, panel->hidden_width, panel->hidden_height);
766 if (panel_horizontal
) {
767 if (panel_position
& TOP
)
768 XResizeWindow(server
.dsp
, panel
->main_win
, panel
->hidden_width
, panel
->hidden_height
);
770 XMoveResizeWindow(server
.dsp
, panel
->main_win
, panel
->posx
, panel
->posy
+diff
, panel
->hidden_width
, panel
->hidden_height
);
773 if (panel_position
& LEFT
)
774 XResizeWindow(server
.dsp
, panel
->main_win
, panel
->hidden_width
, panel
->hidden_height
);
776 XMoveResizeWindow(server
.dsp
, panel
->main_win
, panel
->posx
+diff
, panel
->posy
, panel
->hidden_width
, panel
->hidden_height
);
782 void autohide_trigger_show(Panel
* p
)
786 if (p
->autohide_timeout
)
787 change_timeout(p
->autohide_timeout
, panel_autohide_show_timeout
, 0, autohide_show
, p
);
789 p
->autohide_timeout
= add_timeout(panel_autohide_show_timeout
, 0, autohide_show
, p
);
793 void autohide_trigger_hide(Panel
* p
)
801 if (XQueryPointer(server
.dsp
, p
->main_win
, &root
, &child
, &xr
, &yr
, &xw
, &yw
, &mask
))
802 if (child
) return; // mouse over one of the system tray icons
804 if (p
->autohide_timeout
)
805 change_timeout(p
->autohide_timeout
, panel_autohide_hide_timeout
, 0, autohide_hide
, p
);
807 p
->autohide_timeout
= add_timeout(panel_autohide_hide_timeout
, 0, autohide_hide
, p
);