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
;
46 Task
*task_active
= 0;
58 for (i
=0 ; i
< nb_panel
; i
++) {
63 p
->g_taskbar
.parent
= p
;
64 p
->g_taskbar
.panel
= p
;
65 p
->g_task
.area
.panel
= p
;
68 p
->area
.width
= (float)server
.monitor
[p
->monitor
].width
* p
->initial_width
/ 100;
70 p
->area
.width
= p
->initial_width
;
72 p
->area
.height
= (float)server
.monitor
[p
->monitor
].height
* p
->initial_height
/ 100;
74 p
->area
.height
= p
->initial_height
;
78 p
->area
.width
= server
.monitor
[p
->monitor
].width
;
80 if (p
->area
.pix
.border
.rounded
> p
->area
.height
/2)
81 p
->area
.pix
.border
.rounded
= p
->area
.height
/2;
83 /* panel position determined here */
84 if (panel_position
& LEFT
) {
85 p
->posx
= server
.monitor
[p
->monitor
].x
+ p
->marginx
;
88 if (panel_position
& RIGHT
) {
89 p
->posx
= server
.monitor
[p
->monitor
].x
+ server
.monitor
[p
->monitor
].width
- p
->area
.width
- p
->marginx
;
92 p
->posx
= server
.monitor
[p
->monitor
].x
+ ((server
.monitor
[p
->monitor
].width
- p
->area
.width
) / 2);
95 if (panel_position
& TOP
) {
96 p
->posy
= server
.monitor
[p
->monitor
].y
+ p
->marginy
;
99 p
->posy
= server
.monitor
[p
->monitor
].y
+ server
.monitor
[p
->monitor
].height
- p
->area
.height
- p
->marginy
;
103 XSetWindowAttributes att
= { ParentRelative
, 0L, 0, 0L, 0, 0, Always
, 0L, 0L, False
, ExposureMask
|ButtonPressMask
|ButtonReleaseMask
, NoEventMask
, False
, 0, 0 };
105 // XCreateWindow(display, parent, x, y, w, h, border, depth, class, visual, mask, attrib)
106 // main_win doesn't include panel.area.paddingx, so we have WM capabilities on left and right.
107 if (p
->main_win
) XDestroyWindow(server
.dsp
, p
->main_win
);
108 //win = XCreateWindow (server.dsp, server.root_win, p->posx+p->area.paddingxlr, p->posy, p->area.width-(2*p->area.paddingxlr), p->area.height, 0, server.depth, InputOutput, CopyFromParent, CWEventMask, &att);
109 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
);
111 set_panel_properties(p
);
112 set_panel_background(p
);
114 XMapWindow (server
.dsp
, p
->main_win
);
116 init_clock(&p
->clock
, &p
->area
);
130 for (i
=0 ; i
< nb_panel
; i
++) {
133 // no free_area(&p->area) because it's the list of visible objects
135 g_slist_free(p
->area
.list
);
139 free_area(&p
->g_task
.area
);
140 free_area(&p
->g_taskbar
);
141 free_area(&p
->clock
.area
);
142 if (p
->area
.pix
.pmap
) XFreePixmap(server
.dsp
, p
->area
.pix
.pmap
);
143 if (p
->area
.pix_active
.pmap
) XFreePixmap(server
.dsp
, p
->area
.pix_active
.pmap
);
144 if (p
->root_pmap
) XFreePixmap(server
.dsp
, p
->root_pmap
);
145 if (p
->main_win
) XDestroyWindow(server
.dsp
, p
->main_win
);
148 // font allocated once
149 if (panel1
[0].g_task
.font_desc
) pango_font_description_free(panel1
[0].g_task
.font_desc
);
151 if (panel1
) free(panel1
);
156 void visual_refresh (Panel
*p
)
158 if (p
->root_pmap
) XFreePixmap(server
.dsp
, p
->root_pmap
);
159 p
->root_pmap
= XCreatePixmap(server
.dsp
, server
.root_win
, p
->area
.width
, p
->area
.height
, server
.depth
);
161 XCopyArea (server
.dsp
, p
->area
.pix
.pmap
, p
->root_pmap
, server
.gc
, 0, 0, p
->area
.width
, p
->area
.height
, 0, 0);
164 GSList
*l
= p
->area
.list
;
165 for (; l
; l
= l
->next
) {
169 XCopyArea(server
.dsp
, p
->root_pmap
, p
->main_win
, server
.gc
, 0, 0, p
->area
.width
, p
->area
.height
, 0, 0);
171 // main_win doesn't include panel.area.paddingx, so we have WM capabilities on left and right.
172 // this feature is disabled !
173 //XCopyArea (server.dsp, server.pmap, p->main_win, server.gc, p->area.paddingxlr, 0, p->area.width-(2*p->area.paddingxlr), p->area.height, 0, 0);
177 void set_panel_properties(Panel
*p
)
179 XStoreName (server
.dsp
, p
->main_win
, "tint2");
181 // TODO: check if the name is really needed for a panel/taskbar ?
183 gchar
*name
= g_locale_to_utf8("tint2", -1, NULL
, &len
, NULL
);
185 XChangeProperty(server
.dsp
, p
->main_win
, server
.atom
._NET_WM_NAME
, server
.atom
.UTF8_STRING
, 8, PropModeReplace
, (unsigned char *) name
, (int) len
);
190 long val
= server
.atom
._NET_WM_WINDOW_TYPE_DOCK
;
191 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_WINDOW_TYPE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
194 long struts
[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
195 if (panel_position
& TOP
) {
196 struts
[2] = p
->area
.height
+ p
->marginy
;
198 // p->area.width - 1 allowed full screen on monitor 2
199 struts
[9] = p
->posx
+ p
->area
.width
- 1;
202 struts
[3] = p
->area
.height
+ p
->marginy
;
203 struts
[10] = p
->posx
;
204 // p->area.width - 1 allowed full screen on monitor 2
205 struts
[11] = p
->posx
+ p
->area
.width
- 1;
207 // Old specification : fluxbox need _NET_WM_STRUT.
208 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 4);
209 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STRUT_PARTIAL
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 12);
211 // Sticky and below other window
213 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_DESKTOP
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
215 state
[0] = server
.atom
._NET_WM_STATE_SKIP_PAGER
;
216 state
[1] = server
.atom
._NET_WM_STATE_SKIP_TASKBAR
;
217 state
[2] = server
.atom
._NET_WM_STATE_STICKY
;
218 state
[3] = server
.atom
._NET_WM_STATE_BELOW
;
219 XChangeProperty (server
.dsp
, p
->main_win
, server
.atom
._NET_WM_STATE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) state
, 4);
222 XSizeHints size_hints
;
223 size_hints
.flags
= PPosition
;
224 XChangeProperty (server
.dsp
, p
->main_win
, XA_WM_NORMAL_HINTS
, XA_WM_SIZE_HINTS
, 32, PropModeReplace
, (unsigned char *) &size_hints
, sizeof (XSizeHints
) / 4);
228 wmhints
.flags
= InputHint
;
229 wmhints
.input
= False
;
230 XChangeProperty (server
.dsp
, p
->main_win
, XA_WM_HINTS
, XA_WM_HINTS
, 32, PropModeReplace
, (unsigned char *) &wmhints
, sizeof (XWMHints
) / 4);
233 long prop
[5] = { 2, 0, 0, 0, 0 };
234 XChangeProperty(server
.dsp
, p
->main_win
, server
.atom
._MOTIF_WM_HINTS
, server
.atom
._MOTIF_WM_HINTS
, 32, PropModeReplace
, (unsigned char *) prop
, 5);
238 void visible_object()
243 for (i
=0 ; i
< nb_panel
; i
++) {
246 if (panel
->area
.list
) {
247 g_slist_free(panel
->area
.list
);
248 panel
->area
.list
= 0;
251 // list of visible objects
252 // start with clock because draw(clock) can resize others object
254 panel
->area
.list
= g_slist_append(panel
->area
.list
, &panel
->clock
);
256 //panel->area.list = g_slist_append(panel->area.list, &panel->trayer);
259 for (j
=0 ; j
< panel
->nb_desktop
; j
++) {
260 taskbar
= &panel
->taskbar
[j
];
261 if (panel_mode
!= MULTI_DESKTOP
&& taskbar
->desktop
!= server
.desktop
) {
262 // (SINGLE_DESKTOP or SINGLE_MONITOR) and not current desktop
266 panel
->area
.list
= g_slist_append(panel
->area
.list
, taskbar
);
268 set_redraw(&panel
->area
);
274 void set_panel_background(Panel
*p
)
278 if (p
->area
.pix
.pmap
) XFreePixmap (server
.dsp
, p
->area
.pix
.pmap
);
279 p
->area
.pix
.pmap
= XCreatePixmap (server
.dsp
, server
.root_win
, p
->area
.width
, p
->area
.height
, server
.depth
);
281 // copy background (server.root_pmap) in panel
284 XTranslateCoordinates(server
.dsp
, p
->main_win
, server
.root_win
, 0, 0, &x
, &y
, &dummy
);
285 XSetTSOrigin(server
.dsp
, server
.gc
, -x
, -y
) ;
286 XFillRectangle(server
.dsp
, p
->area
.pix
.pmap
, server
.gc
, 0, 0, p
->area
.width
, p
->area
.height
);
288 // draw background panel
291 cs
= cairo_xlib_surface_create (server
.dsp
, p
->area
.pix
.pmap
, server
.visual
, p
->area
.width
, p
->area
.height
);
292 c
= cairo_create (cs
);
294 draw_background(&p
->area
, c
, 0);
297 cairo_surface_destroy (cs
);
300 set_redraw (&p
->area
);
302 // copy background panel on desktop window
303 //XCopyArea (server.dsp, p->area.pix.pmap, server.root_win, server.gc_root, 0, 0, p->area.width, p->area.height, p->posx, p->posy);
307 Panel
*get_panel(Window win
)
310 for (i
=0 ; i
< nb_panel
; i
++) {
311 if (panel1
[i
].main_win
== win
) {