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