diff options
Diffstat (limited to 'src/WinButton.cc')
-rw-r--r-- | src/WinButton.cc | 166 |
1 files changed, 147 insertions, 19 deletions
diff --git a/src/WinButton.cc b/src/WinButton.cc index 4802518..1a28e8f 100644 --- a/src/WinButton.cc +++ b/src/WinButton.cc | |||
@@ -21,22 +21,34 @@ | |||
21 | 21 | ||
22 | /// $Id$ | 22 | /// $Id$ |
23 | 23 | ||
24 | #include <X11/Xlib.h> | ||
25 | |||
24 | #include "WinButton.hh" | 26 | #include "WinButton.hh" |
25 | #include "App.hh" | 27 | #include "App.hh" |
26 | #include "Window.hh" | 28 | #include "Window.hh" |
29 | #include "Screen.hh" | ||
30 | #include "WinClient.hh" | ||
27 | #include "WinButtonTheme.hh" | 31 | #include "WinButtonTheme.hh" |
28 | #include "FbTk/Color.hh" | 32 | #include "FbTk/Color.hh" |
29 | 33 | ||
34 | #ifdef SHAPE | ||
35 | #include <X11/extensions/shape.h> | ||
36 | #endif // SHAPE | ||
37 | |||
38 | |||
30 | WinButton::WinButton(const FluxboxWindow &listen_to, | 39 | WinButton::WinButton(const FluxboxWindow &listen_to, |
31 | WinButtonTheme &theme, | 40 | WinButtonTheme &theme, |
32 | Type buttontype, const FbTk::FbWindow &parent, | 41 | Type buttontype, const FbTk::FbWindow &parent, |
33 | int x, int y, | 42 | int x, int y, |
34 | unsigned int width, unsigned int height): | 43 | unsigned int width, unsigned int height): |
35 | FbTk::Button(parent, x, y, width, height), | 44 | FbTk::Button(parent, x, y, width, height), |
36 | m_type(buttontype), m_listen_to(listen_to), m_theme(theme), | 45 | m_type(buttontype), m_listen_to(listen_to), m_theme(theme), |
46 | m_icon_pixmap(0), m_icon_mask(0), | ||
37 | overrode_bg(false), overrode_pressed(false) { | 47 | overrode_bg(false), overrode_pressed(false) { |
38 | |||
39 | theme.reconfigSig().attach(this); | 48 | theme.reconfigSig().attach(this); |
49 | |||
50 | if (buttontype == MENUICON) | ||
51 | update(0); | ||
40 | } | 52 | } |
41 | 53 | ||
42 | void WinButton::exposeEvent(XExposeEvent &event) { | 54 | void WinButton::exposeEvent(XExposeEvent &event) { |
@@ -51,7 +63,7 @@ void WinButton::buttonReleaseEvent(XButtonEvent &event) { | |||
51 | // when someone else tries to set the background, we may override it | 63 | // when someone else tries to set the background, we may override it |
52 | void WinButton::setBackgroundPixmap(Pixmap pm) { | 64 | void WinButton::setBackgroundPixmap(Pixmap pm) { |
53 | Pixmap my_pm = getBackgroundPixmap(); | 65 | Pixmap my_pm = getBackgroundPixmap(); |
54 | 66 | ||
55 | if (my_pm != 0) { | 67 | if (my_pm != 0) { |
56 | overrode_bg = true; | 68 | overrode_bg = true; |
57 | pm = my_pm; | 69 | pm = my_pm; |
@@ -114,9 +126,8 @@ Pixmap WinButton::getBackgroundPixmap() const { | |||
114 | else | 126 | else |
115 | return m_theme.iconifyUnfocusPixmap().pixmap().drawable(); | 127 | return m_theme.iconifyUnfocusPixmap().pixmap().drawable(); |
116 | break; | 128 | break; |
117 | case STICK: { | 129 | case STICK: |
118 | bool stuck = m_listen_to.isStuck(); | 130 | if (m_listen_to.isStuck()) { |
119 | if (stuck) { | ||
120 | if (focused) | 131 | if (focused) |
121 | return m_theme.stuckPixmap().pixmap().drawable(); | 132 | return m_theme.stuckPixmap().pixmap().drawable(); |
122 | else | 133 | else |
@@ -127,7 +138,6 @@ Pixmap WinButton::getBackgroundPixmap() const { | |||
127 | else | 138 | else |
128 | return m_theme.stickUnfocusPixmap().pixmap().drawable(); | 139 | return m_theme.stickUnfocusPixmap().pixmap().drawable(); |
129 | } | 140 | } |
130 | } | ||
131 | break; | 141 | break; |
132 | case CLOSE: | 142 | case CLOSE: |
133 | if (focused) | 143 | if (focused) |
@@ -135,11 +145,31 @@ Pixmap WinButton::getBackgroundPixmap() const { | |||
135 | else | 145 | else |
136 | return m_theme.closeUnfocusPixmap().pixmap().drawable(); | 146 | return m_theme.closeUnfocusPixmap().pixmap().drawable(); |
137 | break; | 147 | break; |
138 | case SHADE: | 148 | case SHADE: |
139 | if (focused) | 149 | if (m_listen_to.isShaded()) { |
140 | return m_theme.shadePixmap().pixmap().drawable(); | 150 | if (focused) |
141 | else | 151 | return m_theme.unshadePixmap().pixmap().drawable(); |
142 | return m_theme.shadeUnfocusPixmap().pixmap().drawable(); | 152 | else |
153 | return m_theme.unshadeUnfocusPixmap().pixmap().drawable(); | ||
154 | } else { | ||
155 | if (focused) | ||
156 | return m_theme.shadePixmap().pixmap().drawable(); | ||
157 | else | ||
158 | return m_theme.shadeUnfocusPixmap().pixmap().drawable(); | ||
159 | } | ||
160 | break; | ||
161 | case MENUICON: | ||
162 | if (m_icon_pixmap.drawable()) { | ||
163 | if (focused) | ||
164 | return m_theme.titleFocusPixmap().pixmap().drawable(); | ||
165 | else | ||
166 | return m_theme.titleUnfocusPixmap().pixmap().drawable(); | ||
167 | } else { | ||
168 | if (focused) | ||
169 | return m_theme.menuiconPixmap().pixmap().drawable(); | ||
170 | else | ||
171 | return m_theme.menuiconUnfocusPixmap().pixmap().drawable(); | ||
172 | } | ||
143 | break; | 173 | break; |
144 | } | 174 | } |
145 | return None; | 175 | return None; |
@@ -156,23 +186,33 @@ Pixmap WinButton::getPressedPixmap() const { | |||
156 | case CLOSE: | 186 | case CLOSE: |
157 | return m_theme.closePressedPixmap().pixmap().drawable(); | 187 | return m_theme.closePressedPixmap().pixmap().drawable(); |
158 | case SHADE: | 188 | case SHADE: |
159 | return m_theme.shadePressedPixmap().pixmap().drawable(); | 189 | if (m_listen_to.isShaded()) |
190 | return m_theme.unshadePressedPixmap().pixmap().drawable(); | ||
191 | else | ||
192 | return m_theme.shadePressedPixmap().pixmap().drawable(); | ||
193 | case MENUICON: | ||
194 | if (m_icon_pixmap.drawable()) | ||
195 | if (m_listen_to.isFocused()) | ||
196 | return m_theme.titleFocusPixmap().pixmap().drawable(); | ||
197 | else | ||
198 | return m_theme.titleUnfocusPixmap().pixmap().drawable(); | ||
199 | else | ||
200 | return m_theme.menuiconPressedPixmap().pixmap().drawable(); | ||
160 | } | 201 | } |
161 | return None; | 202 | return None; |
162 | } | 203 | } |
163 | 204 | ||
164 | // clear is used to force this to clear the window (e.g. called from clear()) | 205 | // clear is used to force this to clear the window (e.g. called from clear()) |
165 | void WinButton::drawType() { | 206 | void WinButton::drawType() { |
166 | bool used = false; | ||
167 | 207 | ||
168 | // if it's odd and we're centring, we need to add one | 208 | // if it's odd and we're centring, we need to add one |
169 | int oddW = width()%2; | 209 | int oddW = width()%2; |
170 | int oddH = height()%2; | 210 | int oddH = height()%2; |
171 | 211 | ||
172 | bool is_pressed = pressed(); | 212 | bool is_pressed = pressed(); |
173 | if (is_pressed && overrode_pressed) | 213 | if (is_pressed && overrode_pressed && !m_icon_pixmap.drawable()) |
174 | return; | 214 | return; |
175 | if (!is_pressed && overrode_bg) | 215 | if (!is_pressed && overrode_bg && !m_icon_pixmap.drawable()) |
176 | return; | 216 | return; |
177 | if (gc() == 0) | 217 | if (gc() == 0) |
178 | return; | 218 | return; |
@@ -190,8 +230,7 @@ void WinButton::drawType() { | |||
190 | 2, 3, width() - 3, 3); | 230 | 2, 3, width() - 3, 3); |
191 | break; | 231 | break; |
192 | case MINIMIZE: | 232 | case MINIMIZE: |
193 | FbTk::FbWindow::drawRectangle(gc(), | 233 | drawRectangle(gc(), 2, height() - 5, width() - 5, 2); |
194 | 2, height() - 5, width() - 5, 2); | ||
195 | break; | 234 | break; |
196 | case STICK: | 235 | case STICK: |
197 | // width/4 != width/2, so we use /4*2 so that it's properly centred | 236 | // width/4 != width/2, so we use /4*2 so that it's properly centred |
@@ -225,17 +264,106 @@ void WinButton::drawType() { | |||
225 | width() - 3, 2); | 264 | width() - 3, 2); |
226 | break; | 265 | break; |
227 | case SHADE: | 266 | case SHADE: |
228 | // no cute image defined | 267 | |
268 | drawRectangle(gc(), 2, 2, width() - 5 - oddW, 2); | ||
269 | |||
270 | XPoint points[3]; | ||
271 | if (m_listen_to.isShaded()) { | ||
272 | points[1].x = (width() / 2) - 3; points[1].y = 7; | ||
273 | points[2].x = (width() / 2) + 4 - oddW; points[2].y = 7; | ||
274 | points[0].x = (width() / 2); points[0].y = height() / 2 + 2; | ||
275 | } else { | ||
276 | points[0].x = (width() / 2); points[0].y = 6; | ||
277 | points[1].x = (width() / 2) - 4; points[1].y = height() / 2 + 2; | ||
278 | points[2].x = (width() / 2) + 4 - oddW; points[2].y = height() / 2 + 2; | ||
279 | } | ||
280 | fillPolygon(gc(), points, 3, Convex, CoordModeOrigin); | ||
281 | break; | ||
282 | case MENUICON: | ||
283 | if (m_icon_pixmap.drawable()) { | ||
284 | |||
285 | if (m_icon_mask.drawable()) { | ||
286 | XSetClipMask(m_listen_to.fbWindow().display(), | ||
287 | gc(), m_icon_mask.drawable()); | ||
288 | XSetClipOrigin(m_listen_to.fbWindow().display(), | ||
289 | gc(), 2, 2); | ||
290 | } | ||
291 | |||
292 | copyArea(m_icon_pixmap.drawable(), | ||
293 | gc(), | ||
294 | 0, 0, | ||
295 | 2, 2, | ||
296 | m_icon_pixmap.width(), m_icon_pixmap.height()); | ||
297 | |||
298 | if (m_icon_mask.drawable()) | ||
299 | XSetClipMask(m_listen_to.fbWindow().display(), gc(), None); | ||
300 | } else { | ||
301 | for (int y = height()/3; y <= height() - height()/3; y+=3) { | ||
302 | drawLine(gc(), width()/4, y, width() - width()/4 - oddW - 1, y); | ||
303 | } | ||
304 | drawRectangle(gc(), | ||
305 | 2, 2, width() - 5, height() - 5); | ||
306 | } | ||
229 | break; | 307 | break; |
230 | } | 308 | } |
231 | } | 309 | } |
232 | 310 | ||
233 | void WinButton::clear() { | 311 | void WinButton::clear() { |
234 | FbTk::Button::clear(); | 312 | FbTk::Button::clear(); |
313 | |||
314 | if (m_type == MENUICON && ( | ||
315 | !m_icon_pixmap.drawable() || | ||
316 | (m_icon_pixmap.width() != width() - 4 || | ||
317 | m_icon_pixmap.height() != height() - 4))) { | ||
318 | |||
319 | Display* display = m_listen_to.fbWindow().display(); | ||
320 | int screen = m_listen_to.screen().screenNumber(); | ||
321 | XWMHints* hints = XGetWMHints(display, m_listen_to.winClient().window()); | ||
322 | if (hints == 0) { | ||
323 | m_icon_pixmap.release(); | ||
324 | m_icon_mask.release(); | ||
325 | } else { | ||
326 | if ((hints->flags & IconPixmapHint) && hints->icon_pixmap != 0) { | ||
327 | m_icon_pixmap.copy(hints->icon_pixmap, | ||
328 | DefaultDepth(display, screen), screen); | ||
329 | m_icon_pixmap.scale(width() - 4, height() - 4); | ||
330 | } else | ||
331 | m_icon_pixmap.release(); | ||
332 | |||
333 | if ((hints->flags & IconMaskHint)) { | ||
334 | m_icon_mask.copy(hints->icon_mask, 0, 0); | ||
335 | m_icon_mask.scale(width() - 4, height() - 4); | ||
336 | } else | ||
337 | m_icon_mask.release(); | ||
338 | } | ||
339 | |||
340 | XFree(hints); | ||
341 | } | ||
342 | |||
235 | drawType(); | 343 | drawType(); |
236 | } | 344 | } |
237 | 345 | ||
238 | void WinButton::update(FbTk::Subject *subj) { | 346 | void WinButton::update(FbTk::Subject *subj) { |
347 | |||
348 | |||
349 | // just checking, if we the app provides a pixmap. | ||
350 | if (m_type == MENUICON) { | ||
351 | XWMHints* hints = XGetWMHints(m_listen_to.fbWindow().display(), | ||
352 | m_listen_to.winClient().window()); | ||
353 | if (hints == 0) { | ||
354 | m_icon_pixmap.release(); | ||
355 | m_icon_mask.release(); | ||
356 | } else { | ||
357 | if (!((hints->flags & IconPixmapHint) && hints->icon_pixmap != 0)) | ||
358 | m_icon_pixmap.release(); | ||
359 | |||
360 | if (!(hints->flags & IconMaskHint)) | ||
361 | m_icon_mask.release(); | ||
362 | } | ||
363 | |||
364 | XFree(hints); | ||
365 | } | ||
366 | |||
239 | // pressed_pixmap isn't stateful in any current buttons, so no need | 367 | // pressed_pixmap isn't stateful in any current buttons, so no need |
240 | // to potentially override that. Just make sure background pm is ok | 368 | // to potentially override that. Just make sure background pm is ok |
241 | Pixmap my_pm = getBackgroundPixmap(); | 369 | Pixmap my_pm = getBackgroundPixmap(); |