aboutsummaryrefslogtreecommitdiff
path: root/src/WinButton.cc
diff options
context:
space:
mode:
authormarkt <markt>2007-01-21 19:04:01 (GMT)
committermarkt <markt>2007-01-21 19:04:01 (GMT)
commit240ebcb30a0b2a342fe1aad3985654fa54ff36fe (patch)
treeb92376d4ae7774a77f7a964f44e7d06a328fc161 /src/WinButton.cc
parent92537091003a9e259abff98e648e58c63a201bc1 (diff)
downloadfluxbox-240ebcb30a0b2a342fe1aad3985654fa54ff36fe.zip
fluxbox-240ebcb30a0b2a342fe1aad3985654fa54ff36fe.tar.bz2
allow transparency in window buttons
Diffstat (limited to 'src/WinButton.cc')
-rw-r--r--src/WinButton.cc370
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
54void WinButton::exposeEvent(XExposeEvent &event) { 53void WinButton::exposeEvent(XExposeEvent &event) {
@@ -56,150 +55,39 @@ void WinButton::exposeEvent(XExposeEvent &event) {
56 drawType(); 55 drawType();
57} 56}
58 57
58void WinButton::buttonPressEvent(XButtonEvent &event) {
59 FbTk::Button::buttonPressEvent(event);
60 drawType();
61}
62
59void WinButton::buttonReleaseEvent(XButtonEvent &event) { 63void 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
64void WinButton::setBackgroundPixmap(Pixmap pm) { 69void 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
77void WinButton::setBackgroundColor(const FbTk::Color &color) { 75void 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
89void WinButton::setPressedPixmap(Pixmap pm) { 81void 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
102void WinButton::setPressedColor(const FbTk::Color &color) { 87void 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
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;
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
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
312void WinButton::clear() { 278void 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}