wmclockmon: properly fix allocating and freeing of `command`, `light_color` and the...
[dockapps.git] / wmmenu / buttonbar.c
blob82b2ff9dbc14158d1fb86181311ad8520dfdadf8
1 #include <assert.h>
3 #include <libdockapp/dockapp.h>
5 #include "buttonbar.h"
6 #include "xobjects.h"
7 #include "pixmaps.h"
8 #include "options.h"
9 #include "menu.h"
11 /* item number for last known highlight position */
12 static int OldPos = -1 ;
13 /* Graphic context used to draw highlight */
14 static GC HighlightGC = 0 ;
15 /* position where bar will be shown next time */
16 static int BarX=0, BarY=0 ;
18 extern void ButtonBar_Build (void)
20 int i, n ;
21 int h, j, w ;
22 int width, height ;
23 GC imgOp ;
24 GC maskOp ;
25 XGCValues gc ;
26 Pixmap image, mask ;
27 int x, y ;
28 int x0, y0 ;
29 XSetWindowAttributes wa ;
31 n = Menu_GetNbEntries () ;
32 assert (n > 0) ;
33 h = Menu_GetNbRows () ;
34 w = Menu_GetNbColumns () ;
35 width = TileXSize * w ;
36 height = TileYSize * h ;
39 ButtonBarWindow = XCreateSimpleWindow (
40 DADisplay, DefaultRootWindow (DADisplay), 0, 0, width, height, 0,
41 BlackPixel (DADisplay, DefaultScreen (DADisplay)),
42 BlackPixel (DADisplay, DefaultScreen (DADisplay))) ;
43 ButtonBarImage = XCreatePixmap (DADisplay, ButtonBarWindow,
44 width, height, DADepth) ;
45 imgOp = XCreateGC (DADisplay, ButtonBarWindow, 0, & gc) ;
47 HighlightBehindMask = XCreatePixmap (DADisplay, ButtonBarWindow,
48 width, height, 1) ;
49 maskOp = XCreateGC (DADisplay, HighlightBehindMask, 0, & gc) ;
51 /* first apply tile to whole bar */
52 for (i=0; i<w; i++)
53 for (j=0; j<h; j++)
54 XCopyArea (DADisplay, TileImage, ButtonBarImage, imgOp, 0, 0,
55 TileXSize, TileYSize, TileXSize*i, TileYSize*j) ;
57 /* initialize "behind" mask to all 1's */
58 XSetFunction (DADisplay, maskOp, GXset) ;
59 XFillRectangle (DADisplay, HighlightBehindMask, maskOp,
60 0, 0, width, height) ;
61 /* and copy behind mask cells from highlight mask */
62 if (HighlightMask != 0)
64 XSetFunction (DADisplay, maskOp, GXcopy) ;
65 for (i=0; i<w; i++)
66 for (j=0; j<h; j++)
67 XCopyArea (DADisplay, HighlightMask, HighlightBehindMask,
68 maskOp,
69 0, 0, TileXSize, TileYSize, TileXSize*i, TileYSize*j) ;
72 /* then apply each pixmap of menu entry */
73 /* and build a global invert mask for highlight "behind" */
74 for (i=0; i<n; i++)
76 Pixmaps_FindLoad (Menu_GetEntryPixmap (i),
77 & image, & mask, & width, & height) ;
79 /* center pixmap within its cell */
80 x = (width >= TileXSize ? 0 : (TileXSize-width)/2) ;
81 y = (height >= TileYSize ? 0 : (TileYSize-height)/2) ;
83 /* use GC to draw with pixmap's mask in the right cell */
84 x0 = TileXSize*(i/h) ;
85 y0 = TileYSize*(i%h) ;
86 gc.clip_x_origin = x0 + x ;
87 gc.clip_y_origin = y0 + y ;
88 gc.clip_mask = mask ; /* may be None */
89 XChangeGC (DADisplay, imgOp,
90 GCClipXOrigin | GCClipYOrigin | GCClipMask, & gc) ;
91 XCopyArea (DADisplay, image, ButtonBarImage, imgOp, 0, 0,
92 width, height, gc.clip_x_origin, gc.clip_y_origin) ;
94 /* update highlight behind mask: cell &= ~iconmask */
95 if (HighlightBehind && mask != None)
97 /* use "andInverted" (dst &= ~src) */
98 XSetFunction (DADisplay, maskOp, GXandInverted) ;
99 XCopyArea (DADisplay, mask, HighlightBehindMask, maskOp,
100 0, 0, width, height, gc.clip_x_origin, gc.clip_y_origin) ;
102 /* or highlight behind cell &= 0 if no mask */
103 else
104 if (HighlightBehind && mask == None)
106 XSetFunction (DADisplay, maskOp, GXclear) ;
107 XFillRectangle (DADisplay, HighlightBehindMask, maskOp,
108 gc.clip_x_origin, gc.clip_y_origin, width, height) ;
111 XFreePixmap (DADisplay, image) ;
112 if (mask != 0) XFreePixmap (DADisplay, mask) ;
115 XFreeGC (DADisplay, imgOp) ;
116 XFreeGC (DADisplay, maskOp) ;
118 wa.background_pixmap = ButtonBarImage ;
119 wa.event_mask = ButtonPressMask | ButtonReleaseMask ;
120 if (! ClickOnly) wa.event_mask |= EnterWindowMask | LeaveWindowMask ;
121 if (HighlightImage != 0) wa.event_mask |= PointerMotionMask ;
122 wa.override_redirect = True ;
123 XChangeWindowAttributes (DADisplay, ButtonBarWindow,
124 CWBackPixmap | CWEventMask | CWOverrideRedirect, & wa) ;
127 extern void ButtonBar_SetPositionFromDockApp (int dockx, int docky,
128 int dockw, int dockh)
130 int xMid, scrWidth, h, scrHeight ;
131 int x, y ;
133 (void) dockh;
135 /* compute y */
136 scrHeight = DisplayHeight (DADisplay, DefaultScreen (DADisplay)) ;
137 y = docky ;
138 h = TileYSize * Menu_GetNbRows () ;
139 if (y + h >= scrHeight)
141 y = scrHeight - h ;
144 /* compute x */
145 scrWidth = DisplayWidth (DADisplay, DefaultScreen (DADisplay)) ;
146 xMid = dockx + dockw/2 ;
147 if (xMid*2 < scrWidth)
149 /* we are rather on left, expand to right */
150 x = dockx + dockw ;
152 else
154 /* we are rather on right, expand to left */
155 x = dockx - TileXSize * Menu_GetNbColumns () ;
158 BarX = x ;
159 BarY = y ;
162 extern void ButtonBar_Show (void)
164 XMoveWindow (DADisplay, ButtonBarWindow, BarX, BarY) ;
165 XMapRaised (DADisplay, ButtonBarWindow) ;
168 static void BuildHighlightGC (void)
170 XGCValues gc ;
171 gc.clip_mask = HighlightBehindMask ;
172 HighlightGC = XCreateGC (DADisplay, DAWindow,
173 GCClipMask, & gc) ;
176 extern void ButtonBar_Highlight (int col, int row)
178 int h ;
179 int newPos ;
181 if (HighlightImage == 0) return ;
183 h = Menu_GetNbRows () ;
184 newPos = col*h + row ;
186 if (newPos != OldPos)
188 int x, y ;
189 XGCValues gc ;
191 /* first clear old highlight position */
192 ButtonBar_Unhighlight () ;
194 /* don't draw highlight on empty slots */
195 if (newPos >= Menu_GetNbEntries ()) return ;
197 /* compute new draw position */
198 x = col * TileXSize ;
199 y = row * TileYSize ;
200 /* and draw it */
201 if (HighlightGC == 0) BuildHighlightGC () ;
202 gc.clip_x_origin = HighlightBehind ? 0 : x ;
203 gc.clip_y_origin = HighlightBehind ? 0 : y ;
204 XChangeGC (DADisplay, HighlightGC,
205 GCClipXOrigin | GCClipYOrigin, & gc) ;
206 XCopyArea (DADisplay, HighlightImage, ButtonBarWindow,
207 HighlightGC, 0, 0, TileXSize, TileYSize, x, y) ;
209 OldPos = newPos ;
213 extern void ButtonBar_Unhighlight (void)
215 int x, y, h ;
217 if (HighlightImage == 0 || OldPos < 0) return ;
219 h = Menu_GetNbRows () ;
220 x = (OldPos / h) * TileXSize ;
221 y = (OldPos % h) * TileYSize ;
222 XClearArea (DADisplay, ButtonBarWindow,
223 x, y, TileXSize, TileYSize, False) ;
224 OldPos = -1 ;
227 extern void ButtonBar_Hide (void)
229 XUnmapWindow (DADisplay, ButtonBarWindow) ;
230 OldPos = -1 ;
233 extern void ButtonBar_Rebuild (void)
235 XDestroyWindow (DADisplay, ButtonBarWindow) ;
236 if (HighlightGC != 0)
238 XFreeGC (DADisplay, HighlightGC) ;
239 HighlightGC = 0 ;
241 OldPos = -1 ;
242 ButtonBar_Build () ;