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 **************************************************************************/
21 #include <X11/Xutil.h>
22 #include <X11/Xatom.h>
24 #include <cairo-xlib.h>
25 #include <pango/pangocairo.h>
33 void visual_refresh ()
35 if (!panel
.area
.pix
.pmap
)
36 set_panel_background();
38 if (server
.pmap
) XFreePixmap (server
.dsp
, server
.pmap
);
39 server
.pmap
= XCreatePixmap (server
.dsp
, server
.root_win
, panel
.area
.width
, panel
.area
.height
, server
.depth
);
41 XCopyArea (server
.dsp
, panel
.area
.pix
.pmap
, server
.pmap
, server
.gc
, 0, 0, panel
.area
.width
, panel
.area
.height
, 0, 0);
44 GSList
*l
= panel
.area
.list
;
45 for (; l
; l
= l
->next
)
48 // main_win doesn't include panel.area.paddingx, so we have WM capabilities on left and right.
49 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);
55 void set_panel_properties (Window win
)
57 XStoreName (server
.dsp
, win
, "tint2");
59 // TODO: check if the name is really needed for a panel/taskbar ?
61 gchar
*name
= g_locale_to_utf8("tint2", -1, NULL
, &len
, NULL
);
63 XChangeProperty(server
.dsp
, win
, server
.atom
._NET_WM_NAME
, server
.atom
.UTF8_STRING
, 8, PropModeReplace
, (unsigned char *) name
, (int) len
);
68 long val
= server
.atom
._NET_WM_WINDOW_TYPE_DOCK
;
69 XChangeProperty (server
.dsp
, win
, server
.atom
._NET_WM_WINDOW_TYPE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
72 long struts
[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
73 if (panel
.position
& TOP
) {
74 struts
[2] = panel
.area
.height
+ panel
.marginy
;
75 struts
[8] = server
.posx
;
76 struts
[9] = server
.posx
+ panel
.area
.width
;
79 struts
[3] = panel
.area
.height
+ panel
.marginy
;
80 struts
[10] = server
.posx
;
81 struts
[11] = server
.posx
+ panel
.area
.width
;
83 // Old specification : fluxbox need _NET_WM_STRUT.
84 XChangeProperty (server
.dsp
, win
, server
.atom
._NET_WM_STRUT
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 4);
85 XChangeProperty (server
.dsp
, win
, server
.atom
._NET_WM_STRUT_PARTIAL
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &struts
, 12);
87 // Sticky and below other window
89 XChangeProperty (server
.dsp
, win
, server
.atom
._NET_WM_DESKTOP
, XA_CARDINAL
, 32, PropModeReplace
, (unsigned char *) &val
, 1);
91 state
[0] = server
.atom
._NET_WM_STATE_SKIP_PAGER
;
92 state
[1] = server
.atom
._NET_WM_STATE_SKIP_TASKBAR
;
93 state
[2] = server
.atom
._NET_WM_STATE_STICKY
;
94 state
[3] = server
.atom
._NET_WM_STATE_BELOW
;
95 XChangeProperty (server
.dsp
, win
, server
.atom
._NET_WM_STATE
, XA_ATOM
, 32, PropModeReplace
, (unsigned char *) state
, 4);
98 XSizeHints size_hints
;
99 size_hints
.flags
= PPosition
;
100 XChangeProperty (server
.dsp
, win
, XA_WM_NORMAL_HINTS
, XA_WM_SIZE_HINTS
, 32, PropModeReplace
, (unsigned char *) &size_hints
, sizeof (XSizeHints
) / 4);
104 wmhints
.flags
= InputHint
;
105 wmhints
.input
= False
;
106 XChangeProperty (server
.dsp
, win
, XA_WM_HINTS
, XA_WM_HINTS
, 32, PropModeReplace
, (unsigned char *) &wmhints
, sizeof (XWMHints
) / 4);
109 long prop
[5] = { 2, 0, 0, 0, 0 };
110 XChangeProperty(server
.dsp
, win
, server
.atom
._MOTIF_WM_HINTS
, server
.atom
._MOTIF_WM_HINTS
, 32, PropModeReplace
, (unsigned char *) prop
, 5);
114 void window_draw_panel ()
118 /* panel position determined here */
119 if (panel
.position
& LEFT
) server
.posx
= server
.monitor
[panel
.monitor
].x
+ panel
.marginleft
;
121 if (panel
.position
& RIGHT
) server
.posx
= server
.monitor
[panel
.monitor
].x
+ server
.monitor
[panel
.monitor
].width
- panel
.area
.width
- panel
.marginright
;
122 else server
.posx
= server
.monitor
[panel
.monitor
].x
+ ((server
.monitor
[panel
.monitor
].width
- panel
.area
.width
) / 2);
124 if (panel
.position
& TOP
) server
.posy
= server
.monitor
[panel
.monitor
].y
+ panel
.marginy
;
125 else server
.posy
= server
.monitor
[panel
.monitor
].y
+ server
.monitor
[panel
.monitor
].height
- panel
.area
.height
- panel
.marginy
;
127 /* Catch some events */
128 XSetWindowAttributes att
= { ParentRelative
, 0L, 0, 0L, 0, 0, Always
, 0L, 0L, False
, ExposureMask
|ButtonPressMask
|ButtonReleaseMask
, NoEventMask
, False
, 0, 0 };
130 // XCreateWindow(display, parent, x, y, w, h, border, depth, class, visual, mask, attrib)
131 // main_win doesn't include panel.area.paddingx, so we have WM capabilities on left and right.
132 if (window
.main_win
) XDestroyWindow(server
.dsp
, window
.main_win
);
133 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
);
135 set_panel_properties (win
);
136 window
.main_win
= win
;
138 // replaced : server.gc = DefaultGC (server.dsp, 0);
139 if (server
.gc
) XFree(server
.gc
);
141 server
.gc
= XCreateGC(server
.dsp
, win
, (unsigned long) 0, &gcValues
);
142 if (server
.gc_root
) XFree(server
.gc_root
);
143 server
.gc_root
= XCreateGC(server
.dsp
, server
.root_win
, (unsigned long) 0, &gcValues
);
145 XMapWindow (server
.dsp
, win
);
150 void visible_object()
152 if (panel
.area
.list
) {
153 g_slist_free(panel
.area
.list
);
157 // list of visible objects
158 // start with clock because draw(clock) can resize others object
159 if (panel
.clock
.time1_format
)
160 panel
.area
.list
= g_slist_append(panel
.area
.list
, &panel
.clock
);
164 for (i
=0 ; i
< panel
.nb_desktop
; i
++) {
165 for (j
=0 ; j
< panel
.nb_monitor
; j
++) {
166 taskbar
= &panel
.taskbar
[index(i
,j
)];
167 if (panel
.mode
!= MULTI_DESKTOP
&& taskbar
->desktop
!= server
.desktop
) continue;
169 panel
.area
.list
= g_slist_append(panel
.area
.list
, taskbar
);
172 set_redraw(&panel
.area
);
177 Pixmap
get_root_pixmap ()
180 Window root
= RootWindow(server
.dsp
, server
.screen
);
183 int act_format
, c
= 2 ;
190 if (XGetWindowProperty(server
.dsp
, root
, server
.atom
._XROOTPMAP_ID
, 0, 1,
191 False
, XA_PIXMAP
, &dummy_id
, &act_format
,
192 &nitems
, &bytes_after
, &prop
) == Success
) {
194 ret
= *((Pixmap
*)prop
);
201 if (ret
== None
) fprintf(stderr
, "unknown background\n");
206 void set_panel_background()
208 Pixmap wall
= get_root_pixmap();
210 if (panel
.area
.pix
.pmap
) XFreePixmap (server
.dsp
, panel
.area
.pix
.pmap
);
211 panel
.area
.pix
.pmap
= XCreatePixmap (server
.dsp
, server
.root_win
, panel
.area
.width
, panel
.area
.height
, server
.depth
);
213 // add layer of root pixmap
214 XCopyArea(server
.dsp
, wall
, panel
.area
.pix
.pmap
, server
.gc
, server
.posx
, server
.posy
, panel
.area
.width
, panel
.area
.height
, 0, 0);
216 // draw background panel
219 cs
= cairo_xlib_surface_create (server
.dsp
, panel
.area
.pix
.pmap
, server
.visual
, panel
.area
.width
, panel
.area
.height
);
220 c
= cairo_create (cs
);
222 draw_background (&panel
.area
, c
, 0);
225 cairo_surface_destroy (cs
);
227 // copy background panel on desktop window
228 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
);
230 set_redraw (&panel
.area
);