diff options
Diffstat (limited to 'src/WinButton.cc')
-rw-r--r-- | src/WinButton.cc | 370 |
1 files changed, 169 insertions, 201 deletions
diff --git a/src/WinButton.cc b/src/WinButton.cc index f690f93..cf320a9 100644 --- a/src/WinButton.cc +++ b/src/WinButton.cc | |||
@@ -44,11 +44,10 @@ WinButton::WinButton(const FluxboxWindow &listen_to, | |||
44 | FbTk::Button(parent, x, y, width, height), | 44 | FbTk::Button(parent, x, y, width, height), |
45 | 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), | 46 | m_icon_pixmap(0), m_icon_mask(0), |
47 | overrode_bg(false), overrode_pressed(false) { | 47 | m_override_bg(false) { |
48 | theme.reconfigSig().attach(this); | 48 | theme.reconfigSig().attach(this); |
49 | 49 | ||
50 | if (buttontype == MENUICON) | 50 | update(0); |
51 | update(0); | ||
52 | } | 51 | } |
53 | 52 | ||
54 | void WinButton::exposeEvent(XExposeEvent &event) { | 53 | void WinButton::exposeEvent(XExposeEvent &event) { |
@@ -56,150 +55,39 @@ void WinButton::exposeEvent(XExposeEvent &event) { | |||
56 | drawType(); | 55 | drawType(); |
57 | } | 56 | } |
58 | 57 | ||
58 | void WinButton::buttonPressEvent(XButtonEvent &event) { | ||
59 | FbTk::Button::buttonPressEvent(event); | ||
60 | drawType(); | ||
61 | } | ||
62 | |||
59 | void WinButton::buttonReleaseEvent(XButtonEvent &event) { | 63 | void WinButton::buttonReleaseEvent(XButtonEvent &event) { |
60 | FbTk::Button::buttonReleaseEvent(event); | 64 | FbTk::Button::buttonReleaseEvent(event); |
65 | drawType(); | ||
61 | } | 66 | } |
62 | 67 | ||
63 | // when someone else tries to set the background, we may override it | 68 | // when someone else tries to set the background, we may override it |
64 | void WinButton::setBackgroundPixmap(Pixmap pm) { | 69 | void WinButton::setBackgroundPixmap(Pixmap pm) { |
65 | Pixmap my_pm = getBackgroundPixmap(); | 70 | if (m_override_bg) |
66 | 71 | return; | |
67 | if (my_pm != 0) { | ||
68 | overrode_bg = true; | ||
69 | pm = my_pm; | ||
70 | } else { | ||
71 | overrode_bg = false; | ||
72 | } | ||
73 | |||
74 | FbTk::Button::setBackgroundPixmap(pm); | 72 | FbTk::Button::setBackgroundPixmap(pm); |
75 | } | 73 | } |
76 | 74 | ||
77 | void WinButton::setBackgroundColor(const FbTk::Color &color) { | 75 | void WinButton::setBackgroundColor(const FbTk::Color &color) { |
78 | Pixmap my_pm = getBackgroundPixmap(); | 76 | if (m_override_bg) |
79 | 77 | return; | |
80 | if (my_pm != 0) { | 78 | FbTk::Button::setBackgroundColor(color); |
81 | overrode_bg = true; | ||
82 | FbTk::Button::setBackgroundPixmap(my_pm); | ||
83 | } else { | ||
84 | overrode_bg = false; | ||
85 | FbTk::Button::setBackgroundColor(color); | ||
86 | } | ||
87 | } | 79 | } |
88 | 80 | ||
89 | void WinButton::setPressedPixmap(Pixmap pm) { | 81 | void WinButton::setPressedPixmap(Pixmap pm) { |
90 | Pixmap my_pm = getPressedPixmap(); | 82 | if (m_override_bg) |
91 | 83 | return; | |
92 | if (my_pm != 0) { | ||
93 | overrode_pressed = true; | ||
94 | pm = my_pm; | ||
95 | } else { | ||
96 | overrode_pressed = false; | ||
97 | } | ||
98 | |||
99 | FbTk::Button::setPressedPixmap(pm); | 84 | FbTk::Button::setPressedPixmap(pm); |
100 | } | 85 | } |
101 | 86 | ||
102 | void WinButton::setPressedColor(const FbTk::Color &color) { | 87 | void WinButton::setPressedColor(const FbTk::Color &color) { |
103 | Pixmap my_pm = getPressedPixmap(); | 88 | if (m_override_bg) |
104 | 89 | return; | |
105 | if (my_pm != 0) { | 90 | FbTk::Button::setPressedColor(color); |
106 | overrode_pressed = true; | ||
107 | FbTk::Button::setPressedPixmap(my_pm); | ||
108 | } else { | ||
109 | overrode_pressed = false; | ||
110 | FbTk::Button::setPressedColor(color); | ||
111 | } | ||
112 | } | ||
113 | |||
114 | Pixmap WinButton::getBackgroundPixmap() const { | ||
115 | bool focused = m_listen_to.isFocused(); | ||
116 | switch(m_type) { | ||
117 | case MAXIMIZE: | ||
118 | if (focused) | ||
119 | return m_theme.maximizePixmap().pixmap().drawable(); | ||
120 | else | ||
121 | return m_theme.maximizeUnfocusPixmap().pixmap().drawable(); | ||
122 | break; | ||
123 | case MINIMIZE: | ||
124 | if (focused) | ||
125 | return m_theme.iconifyPixmap().pixmap().drawable(); | ||
126 | else | ||
127 | return m_theme.iconifyUnfocusPixmap().pixmap().drawable(); | ||
128 | break; | ||
129 | case STICK: | ||
130 | if (m_listen_to.isStuck()) { | ||
131 | if (focused) | ||
132 | return m_theme.stuckPixmap().pixmap().drawable(); | ||
133 | else | ||
134 | return m_theme.stuckUnfocusPixmap().pixmap().drawable(); | ||
135 | } else { | ||
136 | if (focused) | ||
137 | return m_theme.stickPixmap().pixmap().drawable(); | ||
138 | else | ||
139 | return m_theme.stickUnfocusPixmap().pixmap().drawable(); | ||
140 | } | ||
141 | break; | ||
142 | case CLOSE: | ||
143 | if (focused) | ||
144 | return m_theme.closePixmap().pixmap().drawable(); | ||
145 | else | ||
146 | return m_theme.closeUnfocusPixmap().pixmap().drawable(); | ||
147 | break; | ||
148 | case SHADE: | ||
149 | if (m_listen_to.isShaded()) { | ||
150 | if (focused) | ||
151 | return m_theme.unshadePixmap().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 | } | ||
173 | break; | ||
174 | } | ||
175 | return None; | ||
176 | } | ||
177 | |||
178 | Pixmap WinButton::getPressedPixmap() const { | ||
179 | switch(m_type) { | ||
180 | case MAXIMIZE: | ||
181 | return m_theme.maximizePressedPixmap().pixmap().drawable(); | ||
182 | case MINIMIZE: | ||
183 | return m_theme.iconifyPressedPixmap().pixmap().drawable(); | ||
184 | case STICK: | ||
185 | return m_theme.stickPressedPixmap().pixmap().drawable(); | ||
186 | case CLOSE: | ||
187 | return m_theme.closePressedPixmap().pixmap().drawable(); | ||
188 | case SHADE: | ||
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(); | ||
201 | } | ||
202 | return None; | ||
203 | } | 91 | } |
204 | 92 | ||
205 | // clear is used to force this to clear the window (e.g. called from clear()) | 93 | // clear is used to force this to clear the window (e.g. called from clear()) |
@@ -210,44 +98,88 @@ void WinButton::drawType() { | |||
210 | int oddH = height()%2; | 98 | int oddH = height()%2; |
211 | 99 | ||
212 | bool is_pressed = pressed(); | 100 | bool is_pressed = pressed(); |
213 | if (is_pressed && overrode_pressed && !m_icon_pixmap.drawable()) | 101 | bool focused = m_listen_to.isFocused(); |
214 | return; | ||
215 | if (!is_pressed && overrode_bg && !m_icon_pixmap.drawable()) | ||
216 | return; | ||
217 | if (gc() == 0) | 102 | if (gc() == 0) |
218 | return; | 103 | return; |
219 | 104 | ||
220 | // otherwise draw old style imagery | 105 | // check for pixmap in style, otherwise draw old style imagery |
106 | FbTk::PixmapWithMask style_pixmap; | ||
221 | switch (m_type) { | 107 | switch (m_type) { |
222 | case MAXIMIZE: | 108 | case MAXIMIZE: |
223 | // if no pixmap was used, use old style | 109 | if (is_pressed) |
224 | if (gc() == 0) // must have valid graphic context | 110 | style_pixmap = m_theme.maximizePressedPixmap(); |
225 | return; | 111 | else if (focused) |
112 | style_pixmap = m_theme.maximizePixmap(); | ||
113 | else | ||
114 | style_pixmap = m_theme.maximizeUnfocusPixmap(); | ||
226 | 115 | ||
227 | drawRectangle(gc(), | 116 | if (style_pixmap.pixmap().drawable()) |
228 | 2, 2, width() - 5, height() - 5); | 117 | drawIcon(style_pixmap.pixmap(), style_pixmap.mask()); |
229 | drawLine(gc(), | 118 | else { |
230 | 2, 3, width() - 3, 3); | 119 | // if no pixmap was used, use old style |
120 | drawRectangle(gc(), | ||
121 | 2, 2, width() - 5, height() - 5); | ||
122 | drawLine(gc(), | ||
123 | 2, 3, width() - 3, 3); | ||
124 | } | ||
231 | break; | 125 | break; |
232 | case MINIMIZE: | 126 | case MINIMIZE: |
233 | drawRectangle(gc(), 2, height() - 5, width() - 5, 2); | 127 | if (is_pressed) |
128 | style_pixmap = m_theme.iconifyPressedPixmap(); | ||
129 | else if (focused) | ||
130 | style_pixmap = m_theme.iconifyPixmap(); | ||
131 | else | ||
132 | style_pixmap = m_theme.iconifyUnfocusPixmap(); | ||
133 | |||
134 | if (style_pixmap.pixmap().drawable()) | ||
135 | drawIcon(style_pixmap.pixmap(), style_pixmap.mask()); | ||
136 | else | ||
137 | drawRectangle(gc(), 2, height() - 5, width() - 5, 2); | ||
138 | |||
234 | break; | 139 | break; |
235 | case STICK: | 140 | case STICK: |
236 | // width/4 != width/2, so we use /4*2 so that it's properly centred | 141 | if (is_pressed) |
237 | if (m_listen_to.isStuck()) { | 142 | style_pixmap = m_theme.stickPressedPixmap(); |
238 | fillRectangle(gc(), | 143 | else if (m_listen_to.isStuck()) { |
239 | width()/2 - width()/4, height()/2 - height()/4, | 144 | if (focused) |
240 | width()/4*2 + oddW, height()/4*2 + oddH); | 145 | style_pixmap = m_theme.stuckPixmap(); |
146 | else | ||
147 | style_pixmap = m_theme.stuckUnfocusPixmap(); | ||
241 | } else { | 148 | } else { |
242 | fillRectangle(gc(), | 149 | if (focused) |
243 | width()/2 - width()/10, height()/2 - height()/10, | 150 | style_pixmap = m_theme.stickPixmap(); |
244 | width()/10*2 + oddW, height()/10*2 + oddH); | 151 | else |
152 | style_pixmap = m_theme.stickUnfocusPixmap(); | ||
153 | } | ||
154 | if (style_pixmap.pixmap().drawable()) | ||
155 | drawIcon(style_pixmap.pixmap(), style_pixmap.mask()); | ||
156 | else { | ||
157 | // width/4 != width/2, so we use /4*2 so that it's properly centred | ||
158 | if (m_listen_to.isStuck()) { | ||
159 | fillRectangle(gc(), | ||
160 | width()/2 - width()/4, height()/2 - height()/4, | ||
161 | width()/4*2 + oddW, height()/4*2 + oddH); | ||
162 | } else { | ||
163 | fillRectangle(gc(), | ||
164 | width()/2 - width()/10, height()/2 - height()/10, | ||
165 | width()/10*2 + oddW, height()/10*2 + oddH); | ||
166 | } | ||
245 | } | 167 | } |
246 | break; | 168 | break; |
247 | case CLOSE: | 169 | case CLOSE: |
248 | drawLine(gc(), | 170 | if (is_pressed) |
249 | 2, 2, | 171 | style_pixmap = m_theme.closePressedPixmap(); |
250 | width() - 3, height() - 3); | 172 | else if (focused) |
173 | style_pixmap = m_theme.closePixmap(); | ||
174 | else | ||
175 | style_pixmap = m_theme.closeUnfocusPixmap(); | ||
176 | |||
177 | if (style_pixmap.pixmap().drawable()) | ||
178 | drawIcon(style_pixmap.pixmap(), style_pixmap.mask()); | ||
179 | else { | ||
180 | drawLine(gc(), | ||
181 | 2, 2, | ||
182 | width() - 3, height() - 3); | ||
251 | // I can't figure out why this second one needs a y offset of 1????? | 183 | // I can't figure out why this second one needs a y offset of 1????? |
252 | // but it does - at least on my box: | 184 | // but it does - at least on my box: |
253 | // XFree86 Version 4.2.1.1 (Debian 4.2.1-12.1 20031003005825) | 185 | // XFree86 Version 4.2.1.1 (Debian 4.2.1-12.1 20031003005825) |
@@ -259,46 +191,62 @@ void WinButton::drawType() { | |||
259 | // XFree86 Version 4.3.0.1 (Debian 4.3.0.dfsg.1-1 20040428170728) | 191 | // XFree86 Version 4.3.0.1 (Debian 4.3.0.dfsg.1-1 20040428170728) |
260 | // (X Protocol Version 11, Revision 0, Release 6.6) | 192 | // (X Protocol Version 11, Revision 0, Release 6.6) |
261 | 193 | ||
262 | drawLine(gc(), | 194 | drawLine(gc(), |
263 | 2, height() - 3, | 195 | 2, height() - 3, |
264 | width() - 3, 2); | 196 | width() - 3, 2); |
197 | } | ||
265 | break; | 198 | break; |
266 | case SHADE: | 199 | case SHADE: |
200 | if (is_pressed) { | ||
201 | if (m_listen_to.isShaded()) | ||
202 | style_pixmap = m_theme.unshadePressedPixmap(); | ||
203 | else | ||
204 | style_pixmap = m_theme.shadePressedPixmap(); | ||
205 | } else if (m_listen_to.isShaded()) { | ||
206 | if (focused) | ||
207 | style_pixmap = m_theme.unshadePixmap(); | ||
208 | else | ||
209 | style_pixmap = m_theme.unshadeUnfocusPixmap(); | ||
210 | } else { | ||
211 | if (focused) | ||
212 | style_pixmap = m_theme.shadePixmap(); | ||
213 | else | ||
214 | style_pixmap = m_theme.shadeUnfocusPixmap(); | ||
215 | } | ||
267 | 216 | ||
268 | { | 217 | if (style_pixmap.pixmap().drawable()) |
269 | int size = width() - 5 - oddW; | 218 | drawIcon(style_pixmap.pixmap(), style_pixmap.mask()); |
270 | 219 | else { | |
271 | drawRectangle(gc(), 2, 2, size, 2); | 220 | int size = width() - 5 - oddW; |
272 | 221 | ||
273 | // draw a one-quarter triangle below the rectangle | 222 | drawRectangle(gc(), 2, 2, size, 2); |
274 | drawTriangle(gc(), (m_listen_to.isShaded() ? | 223 | |
275 | FbTk::FbDrawable::DOWN: | 224 | // draw a one-quarter triangle below the rectangle |
276 | FbTk::FbDrawable::UP), | 225 | drawTriangle(gc(), (m_listen_to.isShaded() ? |
277 | 4, 6, | 226 | FbTk::FbDrawable::DOWN: |
278 | size-2, size/2 - 1, | 227 | FbTk::FbDrawable::UP), |
279 | 100); | 228 | 4, 6, |
280 | 229 | size-2, size/2 - 1, | |
230 | 100); | ||
231 | } | ||
281 | break; | 232 | break; |
282 | } | ||
283 | case MENUICON: | 233 | case MENUICON: |
234 | // if we got an icon from the window, use it instead | ||
284 | if (m_icon_pixmap.drawable()) { | 235 | if (m_icon_pixmap.drawable()) { |
236 | drawIcon(m_icon_pixmap, m_icon_mask); | ||
237 | return; | ||
238 | } | ||
285 | 239 | ||
286 | if (m_icon_mask.drawable()) { | 240 | if (is_pressed) |
287 | XSetClipMask(m_listen_to.fbWindow().display(), | 241 | style_pixmap = m_theme.menuiconPressedPixmap(); |
288 | gc(), m_icon_mask.drawable()); | 242 | else if (focused) |
289 | XSetClipOrigin(m_listen_to.fbWindow().display(), | 243 | style_pixmap = m_theme.menuiconPixmap(); |
290 | gc(), 2, 2); | 244 | else |
291 | } | 245 | style_pixmap = m_theme.menuiconUnfocusPixmap(); |
292 | 246 | ||
293 | copyArea(m_icon_pixmap.drawable(), | 247 | if (style_pixmap.pixmap().drawable()) |
294 | gc(), | 248 | drawIcon(style_pixmap.pixmap(), style_pixmap.mask()); |
295 | 0, 0, | 249 | else { |
296 | 2, 2, | ||
297 | m_icon_pixmap.width(), m_icon_pixmap.height()); | ||
298 | |||
299 | if (m_icon_mask.drawable()) | ||
300 | XSetClipMask(m_listen_to.fbWindow().display(), gc(), None); | ||
301 | } else { | ||
302 | for (unsigned int y = height()/3; y <= height() - height()/3; y+=3) { | 250 | for (unsigned int y = height()/3; y <= height() - height()/3; y+=3) { |
303 | drawLine(gc(), width()/4, y, width() - width()/4 - oddW - 1, y); | 251 | drawLine(gc(), width()/4, y, width() - width()/4 - oddW - 1, y); |
304 | } | 252 | } |
@@ -309,6 +257,24 @@ void WinButton::drawType() { | |||
309 | } | 257 | } |
310 | } | 258 | } |
311 | 259 | ||
260 | void WinButton::drawIcon(FbTk::FbPixmap icon, FbTk::FbPixmap mask) { | ||
261 | if (mask.drawable()) { | ||
262 | XSetClipMask(m_listen_to.fbWindow().display(), | ||
263 | gc(), mask.drawable()); | ||
264 | XSetClipOrigin(m_listen_to.fbWindow().display(), | ||
265 | gc(), 0, 0); | ||
266 | } | ||
267 | |||
268 | copyArea(icon.drawable(), | ||
269 | gc(), | ||
270 | 0, 0, | ||
271 | 0, 0, | ||
272 | icon.width(), icon.height()); | ||
273 | |||
274 | if (mask.drawable()) | ||
275 | XSetClipMask(m_listen_to.fbWindow().display(), gc(), None); | ||
276 | } | ||
277 | |||
312 | void WinButton::clear() { | 278 | void WinButton::clear() { |
313 | FbTk::Button::clear(); | 279 | FbTk::Button::clear(); |
314 | drawType(); | 280 | drawType(); |
@@ -324,13 +290,13 @@ void WinButton::update(FbTk::Subject *subj) { | |||
324 | if (m_listen_to.usePixmap()) { | 290 | if (m_listen_to.usePixmap()) { |
325 | m_icon_pixmap.copy(m_listen_to.iconPixmap().drawable(), | 291 | m_icon_pixmap.copy(m_listen_to.iconPixmap().drawable(), |
326 | DefaultDepth(display, screen), screen); | 292 | DefaultDepth(display, screen), screen); |
327 | m_icon_pixmap.scale(width() - 4, height() - 4); | 293 | m_icon_pixmap.scale(width(), height()); |
328 | } else | 294 | } else |
329 | m_icon_pixmap.release(); | 295 | m_icon_pixmap.release(); |
330 | 296 | ||
331 | if (m_listen_to.useMask()) { | 297 | if (m_listen_to.useMask()) { |
332 | m_icon_mask.copy(m_listen_to.iconMask().drawable(), 0, 0); | 298 | m_icon_mask.copy(m_listen_to.iconMask().drawable(), 0, 0); |
333 | m_icon_mask.scale(width() - 4, height() - 4); | 299 | m_icon_mask.scale(width(), height()); |
334 | } else | 300 | } else |
335 | m_icon_mask.release(); | 301 | m_icon_mask.release(); |
336 | 302 | ||
@@ -338,17 +304,19 @@ void WinButton::update(FbTk::Subject *subj) { | |||
338 | 304 | ||
339 | // pressed_pixmap isn't stateful in any current buttons, so no need | 305 | // pressed_pixmap isn't stateful in any current buttons, so no need |
340 | // to potentially override that. Just make sure background pm is ok | 306 | // to potentially override that. Just make sure background pm is ok |
341 | Pixmap my_pm = getBackgroundPixmap(); | 307 | Pixmap my_pm; |
342 | if (my_pm != None) | 308 | if (m_listen_to.isFocused()) |
343 | setBackgroundPixmap(my_pm); | 309 | my_pm = m_theme.titleFocusPixmap().pixmap().drawable(); |
344 | 310 | else | |
345 | // incorrect, pressed_pixmap is stateful in shade, so we'll do oneoff for now | 311 | my_pm = m_theme.titleUnfocusPixmap().pixmap().drawable(); |
346 | if (m_type == SHADE) { | 312 | |
347 | Pixmap p_pm = getPressedPixmap(); | 313 | if (my_pm == None) |
348 | if (p_pm != None) | 314 | m_override_bg = false; |
349 | setPressedPixmap(p_pm); | 315 | else { |
316 | FbTk::Button::setPressedPixmap(my_pm); | ||
317 | FbTk::Button::setBackgroundPixmap(my_pm); | ||
318 | m_override_bg = true; | ||
350 | } | 319 | } |
351 | |||
352 | 320 | ||
353 | clear(); | 321 | clear(); |
354 | } | 322 | } |