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 **************************************************************************/
20 #include <X11/Xutil.h>
21 #include <X11/Xatom.h>
23 #include <cairo-xlib.h>
24 #include <pango/pangocairo.h>
32 void visual_refresh ()
34 if (!panel
.area
.pix
.pmap
)
35 set_panel_background();
37 if (server
.pmap
) XFreePixmap (server
.dsp
, server
.pmap
);
38 server
.pmap
= XCreatePixmap (server
.dsp
, server
.root_win
, panel
.area
.width
, panel
.area
.height
, server
.depth
);
40 XCopyArea (server
.dsp
, panel
.area
.pix
.pmap
, server
.pmap
, server
.gc
, 0, 0, panel
.area
.width
, panel
.area
.height
, 0, 0);
43 GSList
*l
= panel
.area
.list
;
44 for (; l
; l
= l
->next
)
47 // main_win doesn't include panel.area.paddingx, so we have WM capabilities on left and right.
48 XCopyArea (server
.dsp
, server
.pmap
, window
.main_win
, server
.gc
, panel
.area
.paddingxlr
, 0, panel
.area
.width
-(2*panel
.area
.paddingxlr
), panel
.area
.height
, 0, 0);
54 void set_panel_properties (Window win
)
56 XStoreName (server
.dsp
, win
, "tint2");
58 // TODO: check if the name is really needed for a panel/taskbar ?
60 gchar
*name
= g_locale_to_utf8("tint2", -1, NULL
, &len
, NULL
);
62 XChangeProperty(server
.dsp
, win
, server
.atom
._NET_WM_NAME
, server
.atom
.UTF8_STRING
, 8, PropModeReplace
, (unsigned char *) name
, (int) len
);
67 long val
= server
.atom
._NET_WM_WINDOW_TYPE_DOCK
;
68 XChangeProperty (server
.dsp
, win
, server
.atom
._NET_WM_WINDOW_TYPE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
71 long struts
[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
72 if (panel
.position
& TOP
) {
73 struts
[2] = panel
.area
.height
+ panel
.marginy
;
74 struts
[8] = server
.posx
;
75 struts
[9] = server
.posx
+ panel
.area
.width
;
78 struts
[3] = panel
.area
.height
+ panel
.marginy
;
79 struts
[10] = server
.posx
;
80 struts
[11] = server
.posx
+ panel
.area
.width
;
82 // Old specification : fluxbox need _NET_WM_STRUT.
83 XChangeProperty (server
.dsp
, win
, server
.atom
._NET_WM_STRUT
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 4);
84 XChangeProperty (server
.dsp
, win
, server
.atom
._NET_WM_STRUT_PARTIAL
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 12);
86 // Sticky and below other window
88 XChangeProperty (server
.dsp
, win
, server
.atom
._NET_WM_DESKTOP
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
90 state
[0] = server
.atom
._NET_WM_STATE_SKIP_PAGER
;
91 state
[1] = server
.atom
._NET_WM_STATE_SKIP_TASKBAR
;
92 state
[2] = server
.atom
._NET_WM_STATE_STICKY
;
93 state
[3] = server
.atom
._NET_WM_STATE_BELOW
;
94 XChangeProperty (server
.dsp
, win
, server
.atom
._NET_WM_STATE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) state
, 4);
97 XSizeHints size_hints
;
98 size_hints
.flags
= PPosition
;
99 XChangeProperty (server
.dsp
, win
, XA_WM_NORMAL_HINTS
, XA_WM_SIZE_HINTS
, 32, PropModeReplace
, (unsigned char *) &size_hints
, sizeof (XSizeHints
) / 4);
103 wmhints
.flags
= InputHint
;
104 wmhints
.input
= False
;
105 XChangeProperty (server
.dsp
, win
, XA_WM_HINTS
, XA_WM_HINTS
, 32, PropModeReplace
, (unsigned char *) &wmhints
, sizeof (XWMHints
) / 4);
108 long prop
[5] = { 2, 0, 0, 0, 0 };
109 XChangeProperty(server
.dsp
, win
, server
.atom
._MOTIF_WM_HINTS
, server
.atom
._MOTIF_WM_HINTS
, 32, PropModeReplace
, (unsigned char *) prop
, 5);
113 void window_draw_panel ()
117 /* panel position determined here */
118 if (panel
.position
& LEFT
) server
.posx
= server
.monitor
[panel
.monitor
].x
+ panel
.marginx
;
120 if (panel
.position
& RIGHT
) server
.posx
= server
.monitor
[panel
.monitor
].x
+ server
.monitor
[panel
.monitor
].width
- panel
.area
.width
- panel
.marginx
;
121 else server
.posx
= server
.monitor
[panel
.monitor
].x
+ ((server
.monitor
[panel
.monitor
].width
- panel
.area
.width
) / 2);
123 if (panel
.position
& TOP
) server
.posy
= server
.monitor
[panel
.monitor
].y
+ panel
.marginy
;
124 else server
.posy
= server
.monitor
[panel
.monitor
].y
+ server
.monitor
[panel
.monitor
].height
- panel
.area
.height
- panel
.marginy
;
126 /* Catch some events */
127 XSetWindowAttributes att
= { ParentRelative
, 0L, 0, 0L, 0, 0, Always
, 0L, 0L, False
, ExposureMask
|ButtonPressMask
|ButtonReleaseMask
, NoEventMask
, False
, 0, 0 };
129 // XCreateWindow(display, parent, x, y, w, h, border, depth, class, visual, mask, attrib)
130 // main_win doesn't include panel.area.paddingx, so we have WM capabilities on left and right.
131 if (window
.main_win
) XDestroyWindow(server
.dsp
, window
.main_win
);
132 win
= XCreateWindow (server
.dsp
, server
.root_win
, server
.posx
+panel
.area
.paddingxlr
, server
.posy
, panel
.area
.width
-(2*panel
.area
.paddingxlr
), panel
.area
.height
, 0, server
.depth
, InputOutput
, CopyFromParent
, CWEventMask
, &att
);
134 set_panel_properties (win
);
135 window
.main_win
= win
;
137 // replaced : server.gc = DefaultGC (server.dsp, 0);
138 if (server
.gc
) XFree(server
.gc
);
140 server
.gc
= XCreateGC(server
.dsp
, win
, (unsigned long) 0, &gcValues
);
141 if (server
.gc_root
) XFree(server
.gc_root
);
142 server
.gc_root
= XCreateGC(server
.dsp
, server
.root_win
, (unsigned long) 0, &gcValues
);
144 XMapWindow (server
.dsp
, win
);
149 void visible_object()
151 if (panel
.area
.list
) {
152 g_slist_free(panel
.area
.list
);
156 // list of visible objects
157 // start with clock because draw(clock) can resize others object
158 if (panel
.clock
.time1_format
)
159 panel
.area
.list
= g_slist_append(panel
.area
.list
, &panel
.clock
);
163 for (i
=0 ; i
< panel
.nb_desktop
; i
++) {
164 for (j
=0 ; j
< panel
.nb_monitor
; j
++) {
165 taskbar
= &panel
.taskbar
[index(i
,j
)];
166 if (panel
.mode
!= MULTI_DESKTOP
&& taskbar
->desktop
!= server
.desktop
) continue;
168 panel
.area
.list
= g_slist_append(panel
.area
.list
, taskbar
);
171 set_redraw(&panel
.area
);
176 void set_panel_background()
178 Pixmap wall
= get_root_pixmap();
180 if (panel
.area
.pix
.pmap
) XFreePixmap (server
.dsp
, panel
.area
.pix
.pmap
);
181 panel
.area
.pix
.pmap
= XCreatePixmap (server
.dsp
, server
.root_win
, panel
.area
.width
, panel
.area
.height
, server
.depth
);
183 // add layer of root pixmap
184 XCopyArea (server
.dsp
, wall
, panel
.area
.pix
.pmap
, server
.gc
, server
.posx
, server
.posy
, panel
.area
.width
, panel
.area
.height
, 0, 0);
186 // draw background panel
189 cs
= cairo_xlib_surface_create (server
.dsp
, panel
.area
.pix
.pmap
, server
.visual
, panel
.area
.width
, panel
.area
.height
);
190 c
= cairo_create (cs
);
192 draw_background (&panel
.area
, c
, 0);
195 cairo_surface_destroy (cs
);
197 // copy background panel on desktop window
198 XCopyArea (server
.dsp
, panel
.area
.pix
.pmap
, server
.root_win
, server
.gc_root
, 0, 0, panel
.area
.width
, panel
.area
.height
, server
.posx
, server
.posy
);
200 set_redraw (&panel
.area
);