aboutsummaryrefslogtreecommitdiff
path: root/src/WinButton.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/WinButton.cc')
-rw-r--r--src/WinButton.cc370
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
53void WinButton::exposeEvent(XExposeEvent &event) { 54void WinButton::exposeEvent(XExposeEvent &event) {
@@ -55,39 +56,150 @@ void WinButton::exposeEvent(XExposeEvent &event) {
55 drawType(); 56 drawType();
56} 57}
57 58
58void WinButton::buttonPressEvent(XButtonEvent &event) {
59 FbTk::Button::buttonPressEvent(event);
60 drawType();
61}
62
63void WinButton::buttonReleaseEvent(XButtonEvent &event) { 59void 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
69void WinButton::setBackgroundPixmap(Pixmap pm) { 64void 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
75void WinButton::setBackgroundColor(const FbTk::Color &color) { 77void 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
81void WinButton::setPressedPixmap(Pixmap pm) { 89void 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
87void WinButton::setPressedColor(const FbTk::Color &color) { 102void 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
114Pixmap 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
178Pixmap 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
260void 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
278void WinButton::clear() { 312void 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}