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 **************************************************************************/
22 #include <X11/Xutil.h>
23 #include <X11/Xatom.h>
25 #include <cairo-xlib.h>
26 #include <pango/pangocairo.h>
35 // --------------------------------------------------
40 int mouse_scroll_down
;
64 for (i
=0 ; i
< nb_panel
; i
++) {
69 p
->area
.on_screen
= 1;
71 p
->area
._resize
= resize_panel
;
72 p
->g_taskbar
.parent
= p
;
73 p
->g_taskbar
.panel
= p
;
74 p
->g_task
.area
.panel
= p
;
77 if (p
->clock
.area
.on_screen
)
78 p
->area
.list
= g_slist_append(p
->area
.list
, &p
->clock
);
80 if (p
->battery
.area
.on_screen
)
81 p
->area
.list
= g_slist_append(p
->area
.list
, &p
->battery
);
83 // systray only on first panel
84 if (systray
.area
.on_screen
&& i
== 0)
85 p
->area
.list
= g_slist_append(p
->area
.list
, &systray
);
88 if (!p
->initial_width
) {
89 p
->initial_width
= 100;
94 if (panel_horizontal
) {
96 p
->area
.width
= (float)server
.monitor
[p
->monitor
].width
* p
->initial_width
/ 100;
98 p
->area
.width
= p
->initial_width
;
100 p
->area
.height
= (float)server
.monitor
[p
->monitor
].height
* p
->initial_height
/ 100;
102 p
->area
.height
= p
->initial_height
;
103 if (p
->area
.pix
.border
.rounded
> p
->area
.height
/2)
104 p
->area
.pix
.border
.rounded
= p
->area
.height
/2;
108 p
->area
.height
= (float)server
.monitor
[p
->monitor
].height
* p
->initial_width
/ 100;
110 p
->area
.height
= p
->initial_width
;
112 p
->area
.width
= (float)server
.monitor
[p
->monitor
].width
* p
->initial_height
/ 100;
114 p
->area
.width
= p
->initial_height
;
115 if (p
->area
.pix
.border
.rounded
> p
->area
.width
/2)
116 p
->area
.pix
.border
.rounded
= p
->area
.width
/2;
119 /* panel position determined here */
120 if (panel_position
& LEFT
) {
121 p
->posx
= server
.monitor
[p
->monitor
].x
+ p
->marginx
;
124 if (panel_position
& RIGHT
) {
125 p
->posx
= server
.monitor
[p
->monitor
].x
+ server
.monitor
[p
->monitor
].width
- p
->area
.width
- p
->marginx
;
128 if (panel_horizontal
)
129 p
->posx
= server
.monitor
[p
->monitor
].x
+ ((server
.monitor
[p
->monitor
].width
- p
->area
.width
) / 2);
131 p
->posx
= server
.monitor
[p
->monitor
].x
+ p
->marginx
;
134 if (panel_position
& TOP
) {
135 p
->posy
= server
.monitor
[p
->monitor
].y
+ p
->marginy
;
138 if (panel_position
& BOTTOM
) {
139 p
->posy
= server
.monitor
[p
->monitor
].y
+ server
.monitor
[p
->monitor
].height
- p
->area
.height
- p
->marginy
;
142 p
->posy
= server
.monitor
[p
->monitor
].y
+ ((server
.monitor
[p
->monitor
].height
- p
->area
.height
) / 2);
145 // printf("panel : posx %d, posy %d, width %d, height %d\n", p->posx, p->posy, p->area.width, p->area.height);
148 XSetWindowAttributes att
= { ParentRelative
, 0L, 0, 0L, 0, 0, Always
, 0L, 0L, False
, ExposureMask
|ButtonPressMask
|ButtonReleaseMask
, NoEventMask
, False
, 0, 0 };
149 if (p
->main_win
) XDestroyWindow(server
.dsp
, p
->main_win
);
150 p
->main_win
= XCreateWindow(server
.dsp
, server
.root_win
, p
->posx
, p
->posy
, p
->area
.width
, p
->area
.height
, 0, server
.depth
, InputOutput
, CopyFromParent
, CWEventMask
, &att
);
152 set_panel_properties(p
);
153 set_panel_background(p
);
155 XMapWindow (server
.dsp
, p
->main_win
);
171 // font allocated once
172 if (panel1
[0].g_task
.font_desc
) {
173 pango_font_description_free(panel1
[0].g_task
.font_desc
);
174 panel1
[0].g_task
.font_desc
= 0;
179 for (i
=0 ; i
< nb_panel
; i
++) {
183 free_area(&p
->g_task
.area
);
184 free_area(&p
->g_taskbar
);
187 XFreePixmap(server
.dsp
, p
->temp_pmap
);
191 XDestroyWindow(server
.dsp
, p
->main_win
);
196 if (panel1
) free(panel1
);
201 void resize_panel(void *obj
)
203 Panel
*panel
= (Panel
*)obj
;
204 int taskbar_width
, modulo_width
, taskbar_on_screen
;
206 taskbar_width
= panel
->area
.width
- (2 * panel
->area
.paddingxlr
) - (2 * panel
->area
.pix
.border
.width
);
207 if (panel
->clock
.area
.on_screen
&& panel
->clock
.area
.width
)
208 taskbar_width
-= (panel
->clock
.area
.width
+ panel
->area
.paddingx
);
209 #ifdef ENABLE_BATTERY
210 if (panel
->battery
.area
.on_screen
&& panel
->battery
.area
.width
)
211 taskbar_width
-= (panel
->battery
.area
.width
+ panel
->area
.paddingx
);
213 // TODO : systray only on first panel. search better implementation !
214 if (systray
.area
.on_screen
&& systray
.area
.width
&& panel
== &panel1
[0])
215 taskbar_width
-= (systray
.area
.width
+ panel
->area
.paddingx
);
217 if (panel_mode
== MULTI_DESKTOP
) {
218 taskbar_on_screen
= panel
->nb_desktop
;
219 int width
= taskbar_width
- ((taskbar_on_screen
-1) * panel
->area
.paddingx
);
220 taskbar_width
= width
/ taskbar_on_screen
;
221 modulo_width
= width
% taskbar_on_screen
;
224 taskbar_on_screen
= 1;
228 // change posx and width for all taskbar
230 posx
= panel
->area
.pix
.border
.width
+ panel
->area
.paddingxlr
;
231 for (i
=0 ; i
< panel
->nb_desktop
; i
++) {
232 panel
->taskbar
[i
].area
.posx
= posx
;
233 panel
->taskbar
[i
].area
.width
= taskbar_width
;
234 panel
->taskbar
[i
].area
.resize
= 1;
236 panel
->taskbar
[i
].area
.width
++;
239 //printf("taskbar %d : posx %d, width, %d, posy %d\n", i, posx, panel->taskbar[i].area.width, posx + panel->taskbar[i].area.width);
240 if (panel_mode
== MULTI_DESKTOP
)
241 posx
+= panel
->taskbar
[i
].area
.width
+ panel
->area
.paddingx
;
246 void visible_object()
251 for (i
=0 ; i
< nb_panel
; i
++) {
255 for (j
=0 ; j
< panel
->nb_desktop
; j
++) {
256 taskbar
= &panel
->taskbar
[j
];
257 if (panel_mode
!= MULTI_DESKTOP
&& taskbar
->desktop
!= server
.desktop
) {
258 // SINGLE_DESKTOP and not current desktop
259 taskbar
->area
.on_screen
= 0;
262 taskbar
->area
.on_screen
= 1;
270 void set_panel_properties(Panel
*p
)
272 XStoreName (server
.dsp
, p
->main_win
, "tint2");
274 // TODO: check if the name is really needed for a panel/taskbar ?
276 gchar
*name
= g_locale_to_utf8("tint2", -1, NULL
, &len
, NULL
);
278 XChangeProperty(server
.dsp
, p
->main_win
, server
.atom
._NET_WM_NAME
, server
.atom
.UTF8_STRING
, 8, PropModeReplace
, (unsigned char *) name
, (int) len
);
283 long val
= server
.atom
._NET_WM_WINDOW_TYPE_DOCK
;
284 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_WINDOW_TYPE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
287 long struts
[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
288 if (panel_horizontal
) {
289 if (panel_position
& TOP
) {
290 struts
[2] = p
->area
.height
+ p
->marginy
;
292 // p->area.width - 1 allowed full screen on monitor 2
293 struts
[9] = p
->posx
+ p
->area
.width
- 1;
296 struts
[3] = p
->area
.height
+ p
->marginy
;
297 struts
[10] = p
->posx
;
298 // p->area.width - 1 allowed full screen on monitor 2
299 struts
[11] = p
->posx
+ p
->area
.width
- 1;
303 if (panel_position
& LEFT
) {
304 struts
[0] = p
->area
.width
+ p
->marginx
;
306 // p->area.width - 1 allowed full screen on monitor 2
307 struts
[5] = p
->posy
+ p
->area
.height
- 1;
310 struts
[1] = p
->area
.width
+ p
->marginx
;
312 // p->area.width - 1 allowed full screen on monitor 2
313 struts
[7] = p
->posy
+ p
->area
.height
- 1;
316 // Old specification : fluxbox need _NET_WM_STRUT.
317 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 4);
318 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT_PARTIAL
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 12);
320 // Sticky and below other window
322 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_DESKTOP
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
324 state
[0] = server
.atom
._NET_WM_STATE_SKIP_PAGER
;
325 state
[1] = server
.atom
._NET_WM_STATE_SKIP_TASKBAR
;
326 state
[2] = server
.atom
._NET_WM_STATE_STICKY
;
327 state
[3] = server
.atom
._NET_WM_STATE_BELOW
;
328 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STATE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) state
, 4);
331 XSizeHints size_hints
;
332 size_hints
.flags
= PPosition
;
333 XChangeProperty (server
.dsp
, p
->main_win
, XA_WM_NORMAL_HINTS
, XA_WM_SIZE_HINTS
, 32, PropModeReplace
, (unsigned char *) &size_hints
, sizeof (XSizeHints
) / 4);
337 wmhints
.flags
= InputHint
;
338 wmhints
.input
= False
;
339 XChangeProperty (server
.dsp
, p
->main_win
, XA_WM_HINTS
, XA_WM_HINTS
, 32, PropModeReplace
, (unsigned char *) &wmhints
, sizeof (XWMHints
) / 4);
342 long prop
[5] = { 2, 0, 0, 0, 0 };
343 XChangeProperty(server
.dsp
, p
->main_win
, server
.atom
._MOTIF_WM_HINTS
, server
.atom
._MOTIF_WM_HINTS
, 32, PropModeReplace
, (unsigned char *) prop
, 5);
347 void set_panel_background(Panel
*p
)
351 if (p
->area
.pix
.pmap
) XFreePixmap (server
.dsp
, p
->area
.pix
.pmap
);
352 p
->area
.pix
.pmap
= XCreatePixmap (server
.dsp
, server
.root_win
, p
->area
.width
, p
->area
.height
, server
.depth
);
354 // copy background (server.root_pmap) in panel.area.pix.pmap
357 XTranslateCoordinates(server
.dsp
, p
->main_win
, server
.root_win
, 0, 0, &x
, &y
, &dummy
);
358 XSetTSOrigin(server
.dsp
, server
.gc
, -x
, -y
) ;
359 XFillRectangle(server
.dsp
, p
->area
.pix
.pmap
, server
.gc
, 0, 0, p
->area
.width
, p
->area
.height
);
361 // draw background panel
364 cs
= cairo_xlib_surface_create (server
.dsp
, p
->area
.pix
.pmap
, server
.visual
, p
->area
.width
, p
->area
.height
);
365 c
= cairo_create (cs
);
367 draw_background(&p
->area
, c
, 0);
370 cairo_surface_destroy (cs
);
372 // redraw panel's object
375 for (l0
= p
->area
.list
; l0
; l0
= l0
->next
) {
382 Panel
*get_panel(Window win
)
385 for (i
=0 ; i
< nb_panel
; i
++) {
386 if (panel1
[i
].main_win
== win
) {