not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kwin / clients / kde2 / kde2.cpp
blob03d5730de6bd321d0eb8286b0f2536e76162ecf2
1 /*********************************************************************
3 KDE2 Default KWin client
5 Copyright (C) 1999, 2001 Daniel Duley <mosfet@kde.org>
6 Matthias Ettrich <ettrich@kde.org>
7 Karol Szwed <gallium@kde.org>
9 Draws mini titlebars for tool windows.
10 Many features are now customizable.
12 drawColorBitmaps orignally from kdefx:
13 Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org>
15 This program is free software; you can redistribute it and/or modify
16 it under the terms of the GNU General Public License as published by
17 the Free Software Foundation; either version 2 of the License, or
18 (at your option) any later version.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 *********************************************************************/
29 #include "kde2.h"
31 #include <kconfiggroup.h>
32 #include <kglobal.h>
33 #include <klocale.h>
34 #include <kdebug.h>
36 #include <QLayout>
37 #include <QBitmap>
38 #include <QImage>
39 #include <QApplication>
40 #include <QLabel>
41 #include <QPixmap>
42 #include <QPolygon>
43 #include <QStyle>
44 #include <QPainter>
46 namespace KDE2
49 static const unsigned char iconify_bits[] = {
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78, 0x00,
51 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
53 static const unsigned char close_bits[] = {
54 0x00, 0x00, 0x84, 0x00, 0xce, 0x01, 0xfc, 0x00, 0x78, 0x00, 0x78, 0x00,
55 0xfc, 0x00, 0xce, 0x01, 0x84, 0x00, 0x00, 0x00};
57 static const unsigned char maximize_bits[] = {
58 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01,
59 0x86, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00};
61 static const unsigned char minmax_bits[] = {
62 0x7f, 0x00, 0x7f, 0x00, 0x63, 0x00, 0xfb, 0x03, 0xfb, 0x03, 0x1f, 0x03,
63 0x1f, 0x03, 0x18, 0x03, 0xf8, 0x03, 0xf8, 0x03};
65 static const unsigned char question_bits[] = {
66 0x00, 0x00, 0x78, 0x00, 0xcc, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00,
67 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00};
69 static const unsigned char above_on_bits[] = {
70 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00,
71 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
73 static const unsigned char above_off_bits[] = {
74 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
77 static const unsigned char below_on_bits[] = {
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00,
79 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00 };
81 static const unsigned char below_off_bits[] = {
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01,
83 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00, 0x30, 0x00 };
85 static const unsigned char shade_on_bits[] = {
86 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x02, 0x01, 0x02, 0x01,
87 0x02, 0x01, 0x02, 0x01, 0xfe, 0x01, 0x00, 0x00 };
89 static const unsigned char shade_off_bits[] = {
90 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00,
91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
93 static const unsigned char pindown_white_bits[] = {
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0xa0, 0x03,
95 0xb0, 0x01, 0x30, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
98 static const unsigned char pindown_gray_bits[] = {
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
100 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x80, 0x07, 0xc0, 0x03, 0xe0, 0x01,
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
103 static const unsigned char pindown_dgray_bits[] = {
104 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x10, 0x70, 0x20, 0x50, 0x20,
105 0x48, 0x30, 0xc8, 0x38, 0x08, 0x1f, 0x08, 0x18, 0x10, 0x1c, 0x10, 0x0e,
106 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
108 static const unsigned char pindown_mask_bits[] = {
109 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x1f, 0xf0, 0x3f, 0xf0, 0x3f,
110 0xf8, 0x3f, 0xf8, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0x1f, 0xf0, 0x0f,
111 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
113 static const unsigned char pinup_white_bits[] = {
114 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x11,
115 0x3f, 0x15, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
118 static const unsigned char pinup_gray_bits[] = {
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0x80, 0x0a, 0xbf, 0x0a, 0x80, 0x15, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
121 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
123 static const unsigned char pinup_dgray_bits[] = {
124 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x40, 0x31, 0x40, 0x2e,
125 0x40, 0x20, 0x40, 0x20, 0x7f, 0x2a, 0x40, 0x3f, 0xc0, 0x31, 0xc0, 0x20,
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
128 static const unsigned char pinup_mask_bits[] = {
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0xc0, 0x31, 0xc0, 0x3f,
130 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x3f, 0xc0, 0x3f, 0xc0, 0x31, 0xc0, 0x20,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
133 void drawColorBitmaps(QPainter *p, const QPalette &pal, int x, int y, int w, int h,
134 const uchar *lightColor, const uchar *midColor, const uchar *blackColor)
136 const uchar *data[]={lightColor, midColor, blackColor};
138 QColor colors[]={pal.color(QPalette::Light), pal.color(QPalette::Mid), Qt::black};
140 int i;
141 QSize s(w,h);
142 for(i=0; i < 3; ++i){
143 QBitmap b = QBitmap::fromData(s, data[i], QImage::Format_MonoLSB );
144 b.setMask(b);
145 p->setPen(colors[i]);
146 p->drawPixmap(x, y, b);
150 // ===========================================================================
152 static QPixmap* titlePix;
153 static QPixmap* titleBuffer;
154 static QPixmap* aUpperGradient;
155 static QPixmap* iUpperGradient;
157 static QPixmap* pinDownPix;
158 static QPixmap* pinUpPix;
159 static QPixmap* ipinDownPix;
160 static QPixmap* ipinUpPix;
162 static QPixmap* rightBtnUpPix[2];
163 static QPixmap* rightBtnDownPix[2];
164 static QPixmap* irightBtnUpPix[2];
165 static QPixmap* irightBtnDownPix[2];
167 static QPixmap* leftBtnUpPix[2];
168 static QPixmap* leftBtnDownPix[2];
169 static QPixmap* ileftBtnUpPix[2];
170 static QPixmap* ileftBtnDownPix[2];
172 static KDE2Handler* clientHandler;
173 static int toolTitleHeight;
174 static int normalTitleHeight;
175 static int borderWidth;
176 static int grabBorderWidth;
177 static bool KDE2_initialized = false;
178 static bool useGradients;
179 static bool showGrabBar;
180 static bool showTitleBarStipple;
183 // ===========================================================================
185 KDE2Handler::KDE2Handler()
187 clientHandler = this;
188 readConfig( false );
189 createPixmaps();
190 KDE2_initialized = true;
194 KDE2Handler::~KDE2Handler()
196 KDE2_initialized = false;
197 freePixmaps();
198 clientHandler = NULL;
201 KDecoration* KDE2Handler::createDecoration( KDecorationBridge* b )
203 return ( new KDE2Client( b, this ))->decoration();
206 bool KDE2Handler::reset( unsigned long changed )
208 KDE2_initialized = false;
209 changed |= readConfig( true );
210 if( changed & SettingColors )
211 { // pixmaps need to be recreated
212 freePixmaps();
213 createPixmaps();
215 KDE2_initialized = true;
216 // SettingButtons is handled by KCommonDecoration
217 bool need_recreate = ( changed & ( SettingDecoration | SettingFont | SettingBorder )) != 0;
218 if( need_recreate ) // something else than colors changed
219 return true;
220 resetDecorations( changed );
221 return false;
225 unsigned long KDE2Handler::readConfig( bool update )
227 unsigned long changed = 0;
228 KConfig c("kwinKDE2rc");
229 KConfigGroup conf(&c, "General");
231 bool new_showGrabBar = conf.readEntry("ShowGrabBar", true);
232 bool new_showTitleBarStipple = conf.readEntry("ShowTitleBarStipple", true);
233 bool new_useGradients = conf.readEntry("UseGradients", true);
234 int new_titleHeight = QFontMetrics(options()->font(true)).height() - 2;
235 int new_toolTitleHeight = QFontMetrics(options()->font(true, true)).height() - 4;
237 int new_borderWidth;
238 switch(options()->preferredBorderSize(this)) {
239 case BorderLarge:
240 new_borderWidth = 8;
241 break;
242 case BorderVeryLarge:
243 new_borderWidth = 12;
244 break;
245 case BorderHuge:
246 new_borderWidth = 18;
247 break;
248 case BorderVeryHuge:
249 new_borderWidth = 27;
250 break;
251 case BorderOversized:
252 new_borderWidth = 40;
253 break;
254 case BorderTiny:
255 case BorderNormal:
256 default:
257 new_borderWidth = 4;
260 if (new_titleHeight < 16) new_titleHeight = 16;
261 if (new_titleHeight < new_borderWidth) new_titleHeight = new_borderWidth;
262 if (new_toolTitleHeight < 12) new_toolTitleHeight = 12;
263 if (new_toolTitleHeight < new_borderWidth) new_toolTitleHeight = new_borderWidth;
265 if( update )
267 if( new_showGrabBar != showGrabBar
268 || new_titleHeight != normalTitleHeight
269 || new_toolTitleHeight != toolTitleHeight
270 || new_borderWidth != borderWidth )
271 changed |= SettingDecoration; // need recreating the decoration
272 if( new_showTitleBarStipple != showTitleBarStipple
273 || new_useGradients != useGradients
274 || new_titleHeight != normalTitleHeight
275 || new_toolTitleHeight != toolTitleHeight )
276 changed |= SettingColors; // just recreate the pixmaps and repaint
279 showGrabBar = new_showGrabBar;
280 showTitleBarStipple = new_showTitleBarStipple;
281 useGradients = new_useGradients;
282 normalTitleHeight = new_titleHeight;
283 toolTitleHeight = new_toolTitleHeight;
284 borderWidth = new_borderWidth;
285 grabBorderWidth = (borderWidth > 15) ? borderWidth + 15 : 2*borderWidth;
286 return changed;
289 static void gradientFill(QPixmap *pixmap, const QColor &color1, const QColor &color2)
291 QPainter p(pixmap);
292 QLinearGradient gradient(0, 0, 0, pixmap->height());
293 gradient.setColorAt(0.0, color1);
294 gradient.setColorAt(1.0, color2);
295 QBrush brush(gradient);
296 p.fillRect(pixmap->rect(), brush);
299 // This paints the button pixmaps upon loading the style.
300 void KDE2Handler::createPixmaps()
302 bool highcolor = useGradients && (QPixmap::defaultDepth() > 8);
304 // Make the titlebar stipple optional
305 if (showTitleBarStipple)
307 QPainter p;
308 QPainter maskPainter;
309 int i, x, y;
310 titlePix = new QPixmap(132, normalTitleHeight+2);
311 QBitmap mask(132, normalTitleHeight+2);
312 mask.fill(Qt::color0);
314 p.begin(titlePix);
315 maskPainter.begin(&mask);
316 maskPainter.setPen(Qt::color1);
317 for(i=0, y=2; i < 9; ++i, y+=4)
318 for(x=1; x <= 132; x+=3)
320 p.setPen(options()->color(ColorTitleBar, true).light(150));
321 p.drawPoint(x, y);
322 maskPainter.drawPoint(x, y);
323 p.setPen(options()->color(ColorTitleBar, true).dark(150));
324 p.drawPoint(x+1, y+1);
325 maskPainter.drawPoint(x+1, y+1);
327 maskPainter.end();
328 p.end();
329 titlePix->setMask(mask);
330 } else
331 titlePix = NULL;
333 QColor activeTitleColor1(options()->color(ColorTitleBar, true));
334 QColor activeTitleColor2(options()->color(ColorTitleBlend, true));
336 QColor inactiveTitleColor1(options()->color(ColorTitleBar, false));
337 QColor inactiveTitleColor2(options()->color(ColorTitleBlend, false));
339 // Create titlebar gradient images if required
340 aUpperGradient = NULL;
341 iUpperGradient = NULL;
343 if(highcolor)
345 QSize s(128, normalTitleHeight + 2);
346 // Create the titlebar gradients
347 if (activeTitleColor1 != activeTitleColor2)
350 aUpperGradient = new QPixmap(s);
351 gradientFill(aUpperGradient, activeTitleColor1, activeTitleColor2);
354 if (inactiveTitleColor1 != inactiveTitleColor2)
356 iUpperGradient = new QPixmap(s);
357 gradientFill(iUpperGradient, inactiveTitleColor1, inactiveTitleColor2);
361 // Set the sticky pin pixmaps;
362 QPalette g;
363 QPainter p;
365 // Active pins
366 g = options()->palette( ColorButtonBg, true );
367 QImage pinUpImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied);
368 p.begin( &pinUpImg );
369 drawColorBitmaps( &p, g, 0, 0, 16, 16, pinup_white_bits, pinup_gray_bits, pinup_dgray_bits );
370 p.end();
371 pinUpPix = new QPixmap(QPixmap::fromImage(pinUpImg));
372 pinUpPix->setMask( QBitmap::fromData(QSize( 16, 16 ), pinup_mask_bits) );
374 QImage pinDownImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied);
375 p.begin( &pinDownImg );
376 drawColorBitmaps( &p, g, 0, 0, 16, 16, pindown_white_bits, pindown_gray_bits, pindown_dgray_bits );
377 p.end();
378 pinDownPix = new QPixmap(QPixmap::fromImage(pinDownImg));
379 pinDownPix->setMask( QBitmap::fromData(QSize( 16, 16 ), pindown_mask_bits) );
381 // Inactive pins
382 g = options()->palette( ColorButtonBg, false );
383 QImage ipinUpImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied);
384 p.begin( &ipinUpImg );
385 drawColorBitmaps( &p, g, 0, 0, 16, 16, pinup_white_bits, pinup_gray_bits, pinup_dgray_bits );
386 p.end();
387 ipinUpPix = new QPixmap(QPixmap::fromImage(ipinUpImg));
388 ipinUpPix->setMask( QBitmap::fromData(QSize( 16, 16 ), pinup_mask_bits) );
390 QImage ipinDownImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied);
391 p.begin( &ipinDownImg );
392 drawColorBitmaps( &p, g, 0, 0, 16, 16, pindown_white_bits, pindown_gray_bits, pindown_dgray_bits );
393 p.end();
394 ipinDownPix = new QPixmap(QPixmap::fromImage(ipinDownImg));
395 ipinDownPix->setMask( QBitmap::fromData(QSize( 16, 16 ), pindown_mask_bits) );
397 // Create a title buffer for flicker-free painting
398 titleBuffer = new QPixmap();
400 // Cache all possible button states
401 leftBtnUpPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight);
402 leftBtnDownPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight);
403 ileftBtnUpPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight);
404 ileftBtnDownPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight);
406 rightBtnUpPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight);
407 rightBtnDownPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight);
408 irightBtnUpPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight);
409 irightBtnDownPix[true] = new QPixmap(normalTitleHeight, normalTitleHeight);
411 leftBtnUpPix[false] = new QPixmap(toolTitleHeight, normalTitleHeight);
412 leftBtnDownPix[false] = new QPixmap(toolTitleHeight, normalTitleHeight);
413 ileftBtnUpPix[false] = new QPixmap(normalTitleHeight, normalTitleHeight);
414 ileftBtnDownPix[false] = new QPixmap(normalTitleHeight, normalTitleHeight);
416 rightBtnUpPix[false] = new QPixmap(toolTitleHeight, toolTitleHeight);
417 rightBtnDownPix[false] = new QPixmap(toolTitleHeight, toolTitleHeight);
418 irightBtnUpPix[false] = new QPixmap(toolTitleHeight, toolTitleHeight);
419 irightBtnDownPix[false] = new QPixmap(toolTitleHeight, toolTitleHeight);
421 // Draw the button state pixmaps
422 g = options()->palette( ColorTitleBar, true );
423 drawButtonBackground( leftBtnUpPix[true], g, false );
424 drawButtonBackground( leftBtnDownPix[true], g, true );
425 drawButtonBackground( leftBtnUpPix[false], g, false );
426 drawButtonBackground( leftBtnDownPix[false], g, true );
428 g = options()->palette( ColorButtonBg, true );
429 drawButtonBackground( rightBtnUpPix[true], g, false );
430 drawButtonBackground( rightBtnDownPix[true], g, true );
431 drawButtonBackground( rightBtnUpPix[false], g, false );
432 drawButtonBackground( rightBtnDownPix[false], g, true );
434 g = options()->palette( ColorTitleBar, false );
435 drawButtonBackground( ileftBtnUpPix[true], g, false );
436 drawButtonBackground( ileftBtnDownPix[true], g, true );
437 drawButtonBackground( ileftBtnUpPix[false], g, false );
438 drawButtonBackground( ileftBtnDownPix[false], g, true );
440 g = options()->palette( ColorButtonBg, false );
441 drawButtonBackground( irightBtnUpPix[true], g, false );
442 drawButtonBackground( irightBtnDownPix[true], g, true );
443 drawButtonBackground( irightBtnUpPix[false], g, false );
444 drawButtonBackground( irightBtnDownPix[false], g, true );
448 void KDE2Handler::freePixmaps()
450 // Free button pixmaps
451 if (rightBtnUpPix[true])
452 delete rightBtnUpPix[true];
453 if(rightBtnDownPix[true])
454 delete rightBtnDownPix[true];
455 if (irightBtnUpPix[true])
456 delete irightBtnUpPix[true];
457 if (irightBtnDownPix[true])
458 delete irightBtnDownPix[true];
460 if (leftBtnUpPix[true])
461 delete leftBtnUpPix[true];
462 if(leftBtnDownPix[true])
463 delete leftBtnDownPix[true];
464 if (ileftBtnUpPix[true])
465 delete ileftBtnUpPix[true];
466 if (ileftBtnDownPix[true])
467 delete ileftBtnDownPix[true];
469 if (rightBtnUpPix[false])
470 delete rightBtnUpPix[false];
471 if(rightBtnDownPix[false])
472 delete rightBtnDownPix[false];
473 if (irightBtnUpPix[false])
474 delete irightBtnUpPix[false];
475 if (irightBtnDownPix[false])
476 delete irightBtnDownPix[false];
478 if (leftBtnUpPix[false])
479 delete leftBtnUpPix[false];
480 if(leftBtnDownPix[false])
481 delete leftBtnDownPix[false];
482 if (ileftBtnUpPix[false])
483 delete ileftBtnUpPix[false];
484 if (ileftBtnDownPix[false])
485 delete ileftBtnDownPix[false];
487 // Title images
488 if (titleBuffer)
489 delete titleBuffer;
490 if (titlePix)
491 delete titlePix;
492 if (aUpperGradient)
493 delete aUpperGradient;
494 if (iUpperGradient)
495 delete iUpperGradient;
497 // Sticky pin images
498 if (pinUpPix)
499 delete pinUpPix;
500 if (ipinUpPix)
501 delete ipinUpPix;
502 if (pinDownPix)
503 delete pinDownPix;
504 if (ipinDownPix)
505 delete ipinDownPix;
509 void KDE2Handler::drawButtonBackground(QPixmap *pix,
510 const QPalette &g, bool sunken)
512 QPainter p;
513 int w = pix->width();
514 int h = pix->height();
515 int x2 = w-1;
516 int y2 = h-1;
518 bool highcolor = useGradients && (QPixmap::defaultDepth() > 8);
519 QColor c = g.color( QPalette::Background );
521 // Fill the background with a gradient if possible
522 if (highcolor)
523 gradientFill(pix, c.light(130), c.dark(130));
524 else
525 pix->fill(c);
527 p.begin(pix);
528 // outer frame
529 p.setPen(g.color( QPalette::Mid ));
530 p.drawLine(0, 0, x2, 0);
531 p.drawLine(0, 0, 0, y2);
532 p.setPen(g.color( QPalette::Light ));
533 p.drawLine(x2, 0, x2, y2);
534 p.drawLine(0, x2, y2, x2);
535 p.setPen(g.color( QPalette::Dark ));
536 p.drawRect(1, 1, w-3, h-3);
537 p.setPen(sunken ? g.color( QPalette::Mid ) : g.color( QPalette::Light ));
538 p.drawLine(2, 2, x2-2, 2);
539 p.drawLine(2, 2, 2, y2-2);
540 p.setPen(sunken ? g.color( QPalette::Light ) : g.color( QPalette::Mid ));
541 p.drawLine(x2-2, 2, x2-2, y2-2);
542 p.drawLine(2, x2-2, y2-2, x2-2);
545 QList< KDE2Handler::BorderSize > KDE2Handler::borderSizes() const
546 { // the list must be sorted
547 return QList< BorderSize >() << BorderNormal << BorderLarge <<
548 BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized;
551 bool KDE2Handler::supports( Ability ability ) const
553 switch( ability )
555 // announce
556 case AbilityAnnounceButtons:
557 case AbilityAnnounceColors:
558 // buttons
559 case AbilityButtonMenu:
560 case AbilityButtonOnAllDesktops:
561 case AbilityButtonSpacer:
562 case AbilityButtonHelp:
563 case AbilityButtonMinimize:
564 case AbilityButtonMaximize:
565 case AbilityButtonClose:
566 case AbilityButtonAboveOthers:
567 case AbilityButtonBelowOthers:
568 case AbilityButtonShade:
569 // colors
570 case AbilityColorTitleBack:
571 case AbilityColorTitleBlend:
572 case AbilityColorTitleFore:
573 case AbilityColorFrame:
574 case AbilityColorButtonBack:
575 return true;
576 default:
577 return false;
581 // ===========================================================================
583 KDE2Button::KDE2Button(ButtonType type, KDE2Client *parent, const char *name)
584 : KCommonDecorationButton(type, parent)
586 setObjectName( name );
587 setAttribute( Qt::WA_NoBackground );
589 isMouseOver = false;
590 deco = NULL;
591 large = !decoration()->isToolWindow();
595 KDE2Button::~KDE2Button()
597 if (deco)
598 delete deco;
602 void KDE2Button::reset(unsigned long changed)
604 if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) {
605 switch (type() ) {
606 case CloseButton:
607 setBitmap(close_bits);
608 break;
609 case HelpButton:
610 setBitmap(question_bits);
611 break;
612 case MinButton:
613 setBitmap(iconify_bits);
614 break;
615 case MaxButton:
616 setBitmap( isChecked() ? minmax_bits : maximize_bits );
617 break;
618 case OnAllDesktopsButton:
619 setBitmap(0);
620 break;
621 case ShadeButton:
622 setBitmap( isChecked() ? shade_on_bits : shade_off_bits );
623 break;
624 case AboveButton:
625 setBitmap( isChecked() ? above_on_bits : above_off_bits );
626 break;
627 case BelowButton:
628 setBitmap( isChecked() ? below_on_bits : below_off_bits );
629 break;
630 default:
631 setBitmap(0);
632 break;
635 this->update();
640 void KDE2Button::setBitmap(const unsigned char *bitmap)
642 delete deco;
643 deco = 0;
645 if (bitmap) {
646 deco = new QBitmap( QBitmap::fromData(QSize( 10, 10 ), bitmap) );
647 deco->setMask( *deco );
651 void KDE2Button::paintEvent(QPaintEvent *)
653 QPainter p(this);
654 drawButton(&p);
657 void KDE2Button::drawButton(QPainter *p)
659 if (!KDE2_initialized)
660 return;
662 const bool active = decoration()->isActive();
664 if (deco) {
665 // Fill the button background with an appropriate button image
666 QPixmap btnbg;
668 if (isLeft() ) {
669 if (isDown())
670 btnbg = active ?
671 *leftBtnDownPix[large] : *ileftBtnDownPix[large];
672 else
673 btnbg = active ?
674 *leftBtnUpPix[large] : *ileftBtnUpPix[large];
675 } else {
676 if (isDown())
677 btnbg = active ?
678 *rightBtnDownPix[large] : *irightBtnDownPix[large];
679 else
680 btnbg = active ?
681 *rightBtnUpPix[large] : *irightBtnUpPix[large];
684 p->drawPixmap( 0, 0, btnbg );
686 } else if ( isLeft() ) {
688 // Fill the button background with an appropriate color/gradient
689 // This is for sticky and menu buttons
690 QPixmap* grad = active ? aUpperGradient : iUpperGradient;
691 if (!grad) {
692 QColor c = KDecoration::options()->color(KDecoration::ColorTitleBar, active);
693 p->fillRect(0, 0, width(), height(), c );
694 } else
695 p->drawPixmap( 0, 0, *grad, 0,1, width(), height() );
697 } else {
698 // Draw a plain background for menus or sticky buttons on RHS
699 QColor c = KDecoration::options()->color(KDecoration::ColorFrame, active);
700 p->fillRect(0, 0, width(), height(), c);
704 // If we have a decoration bitmap, then draw that
705 // otherwise we paint a menu button (with mini icon), or a sticky button.
706 if( deco ) {
707 // Select the appropriate button decoration color
708 bool darkDeco = qGray( KDecoration::options()->color(
709 isLeft() ? KDecoration::ColorTitleBar : KDecoration::ColorButtonBg,
710 active).rgb() ) > 127;
712 if (isMouseOver)
713 p->setPen( darkDeco ? Qt::darkGray : Qt::lightGray );
714 else
715 p->setPen( darkDeco ? Qt::black : Qt::white );
717 int xOff = (width()-10)/2;
718 int yOff = (height()-10)/2;
719 p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, *deco);
721 } else {
722 QPixmap btnpix;
724 if (type()==OnAllDesktopsButton) {
725 if (active)
726 btnpix = isChecked() ? *pinDownPix : *pinUpPix;
727 else
728 btnpix = isChecked() ? *ipinDownPix : *ipinUpPix;
729 } else
730 btnpix = decoration()->icon().pixmap( style()->pixelMetric( QStyle::PM_SmallIconSize ), QIcon::Normal );
732 // Intensify the image if required
733 if (isMouseOver) {
734 // XXX Find a suitable substitute for this.
735 // btnpix = KPixmapEffect::intensity(btnpix, 0.8);
738 // Smooth scale the pixmap for small titlebars
739 // This is slow, but we assume this isn't done too often
740 if ( width() < 16 ) {
741 btnpix = btnpix.scaled(12, 12);
742 p->drawPixmap( 0, 0, btnpix );
744 else
745 p->drawPixmap( width()/2-8, height()/2-8, btnpix );
750 void KDE2Button::enterEvent(QEvent *e)
752 isMouseOver=true;
753 repaint();
754 KCommonDecorationButton::enterEvent(e);
758 void KDE2Button::leaveEvent(QEvent *e)
760 isMouseOver=false;
761 repaint();
762 KCommonDecorationButton::leaveEvent(e);
766 // ===========================================================================
768 KDE2Client::KDE2Client( KDecorationBridge* b, KDecorationFactory* f )
769 : KCommonDecoration( b, f )/*,
770 m_closing(false)*/
774 QString KDE2Client::visibleName() const
776 return i18n("KDE 2");
779 bool KDE2Client::decorationBehaviour(DecorationBehaviour behaviour) const
781 switch (behaviour) {
782 case DB_MenuClose:
783 return true;
784 case DB_WindowMask:
785 return true;
786 case DB_ButtonHide:
787 return true;
789 default:
790 return KCommonDecoration::decorationBehaviour(behaviour);
794 int KDE2Client::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const
796 switch (lm) {
797 case LM_BorderLeft:
798 case LM_BorderRight:
799 return borderWidth;
801 case LM_BorderBottom:
802 return mustDrawHandle() ? grabBorderWidth : borderWidth;
804 case LM_TitleEdgeLeft:
805 case LM_TitleEdgeRight:
806 return borderWidth;
808 case LM_TitleEdgeTop:
809 return 3;
811 case LM_TitleEdgeBottom:
812 return 1;
814 case LM_TitleBorderLeft:
815 case LM_TitleBorderRight:
816 return 1;
818 case LM_TitleHeight:
819 return titleHeight;
821 case LM_ButtonWidth:
822 case LM_ButtonHeight:
823 return titleHeight;
825 case LM_ButtonSpacing:
826 return 0;
828 default:
829 return KCommonDecoration::layoutMetric(lm, respectWindowState, btn);
833 KCommonDecorationButton *KDE2Client::createButton(ButtonType type)
835 switch (type) {
836 case MenuButton:
837 return new KDE2Button(MenuButton, this, "menu");
838 case OnAllDesktopsButton:
839 return new KDE2Button(OnAllDesktopsButton, this, "on_all_desktops");
840 case HelpButton:
841 return new KDE2Button(HelpButton, this, "help");
842 case MinButton:
843 return new KDE2Button(MinButton, this, "minimize");
844 case MaxButton:
845 return new KDE2Button(MaxButton, this, "maximize");
846 case CloseButton:
847 return new KDE2Button(CloseButton, this, "close");
848 case AboveButton:
849 return new KDE2Button(AboveButton, this, "above");
850 case BelowButton:
851 return new KDE2Button(BelowButton, this, "below");
852 case ShadeButton:
853 return new KDE2Button(ShadeButton, this, "shade");
855 default:
856 return 0;
860 void KDE2Client::init()
862 // Finally, toolWindows look small
863 if ( isToolWindow() ) {
864 titleHeight = toolTitleHeight;
866 else {
867 titleHeight = normalTitleHeight;
870 KCommonDecoration::init();
873 void KDE2Client::reset( unsigned long changed)
875 widget()->repaint();
877 KCommonDecoration::reset(changed);
880 bool KDE2Client::mustDrawHandle() const
882 bool drawSmallBorders = !options()->moveResizeMaximizedWindows();
883 if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) {
884 return false;
885 } else {
886 return showGrabBar && isResizable();
890 void KDE2Client::paintEvent( QPaintEvent* )
892 if (!KDE2_initialized)
893 return;
895 QPalette g;
896 int offset;
898 QPixmap* upperGradient = isActive() ? aUpperGradient : iUpperGradient;
900 QPainter p(widget());
902 // Obtain widget bounds.
903 QRect r(widget()->rect());
904 int x = r.x();
905 int y = r.y();
906 int x2 = r.width() - 1;
907 int y2 = r.height() - 1;
908 int w = r.width();
909 int h = r.height();
911 // Determine where to place the extended left titlebar
912 int leftFrameStart = (h > 42) ? y+titleHeight+26: y+titleHeight;
914 // Determine where to make the titlebar color transition
915 r = titleRect();
916 int rightOffset = r.x()+r.width()+1;
918 // Create a disposable pixmap buffer for the titlebar
919 // very early before drawing begins so there is no lag
920 // during painting pixels.
921 *titleBuffer = QPixmap( rightOffset-3, titleHeight+1 );
923 // Draw an outer black frame
924 p.setPen(Qt::black);
925 p.drawRect(x,y,w-1,h-1);
927 // Draw part of the frame that is the titlebar color
928 g = options()->palette(ColorTitleBar, isActive());
929 p.setPen(g.color( QPalette::Light ));
930 p.drawLine(x+1, y+1, rightOffset-1, y+1);
931 p.drawLine(x+1, y+1, x+1, leftFrameStart+borderWidth-4);
933 // Draw titlebar colour separator line
934 p.setPen(g.color( QPalette::Dark ));
935 p.drawLine(rightOffset-1, y+1, rightOffset-1, titleHeight+2);
937 p.fillRect(x+2, y+titleHeight+3,
938 borderWidth-4, leftFrameStart+borderWidth-y-titleHeight-8,
939 options()->color(ColorTitleBar, isActive() ));
941 // Finish drawing the titlebar extension
942 p.setPen(Qt::black);
943 p.drawLine(x+1, leftFrameStart+borderWidth-4, x+borderWidth-2, leftFrameStart-1);
944 p.setPen(g.color( QPalette::Mid ));
945 p.drawLine(x+borderWidth-2, y+titleHeight+3, x+borderWidth-2, leftFrameStart-2);
947 // Fill out the border edges
948 g = options()->palette(ColorFrame, isActive());
949 p.setPen(g.color( QPalette::Light ));
950 p.drawLine(rightOffset, y+1, x2-1, y+1);
951 p.drawLine(x+1, leftFrameStart+borderWidth-3, x+1, y2-1);
952 p.setPen(g.color( QPalette::Dark ));
953 p.drawLine(x2-1, y+1, x2-1, y2-1);
954 p.drawLine(x+1, y2-1, x2-1, y2-1);
956 p.setPen(options()->color(ColorFrame, isActive()));
957 QPolygon a;
958 QBrush brush( options()->color(ColorFrame, isActive()), Qt::SolidPattern );
959 p.setBrush( brush ); // use solid, yellow brush
960 a.setPoints( 4, x+2, leftFrameStart+borderWidth-4,
961 x+borderWidth-2, leftFrameStart,
962 x+borderWidth-2, y2-2,
963 x+2, y2-2);
964 p.drawPolygon( a );
965 p.fillRect(x2-borderWidth+2, y+titleHeight+3,
966 borderWidth-3, y2-y-titleHeight-4,
967 options()->color(ColorFrame, isActive() ));
969 // Draw the bottom handle if required
970 if (mustDrawHandle())
972 if(w > 50)
974 qDrawShadePanel(&p, x+1, y2-grabBorderWidth+3, 2*borderWidth+12, grabBorderWidth-3,
975 g, false, 1, &g.brush(QPalette::Mid));
976 qDrawShadePanel(&p, x+2*borderWidth+13, y2-grabBorderWidth+3, w-4*borderWidth-26, grabBorderWidth-3,
977 g, false, 1, isActive() ?
978 &g.brush(QPalette::Background) :
979 &g.brush(QPalette::Mid));
980 qDrawShadePanel(&p, x2-2*borderWidth-12, y2-grabBorderWidth+3, 2*borderWidth+12, grabBorderWidth-3,
981 g, false, 1, &g.brush(QPalette::Mid));
982 } else
983 qDrawShadePanel(&p, x+1, y2-grabBorderWidth+3, w-2, grabBorderWidth-3,
984 g, false, 1, isActive() ?
985 &g.brush(QPalette::Background) :
986 &g.brush(QPalette::Mid));
987 offset = grabBorderWidth;
988 } else
990 p.fillRect(x+2, y2-borderWidth+2, w-4, borderWidth-3,
991 options()->color(ColorFrame, isActive() ));
992 offset = borderWidth;
995 // Draw a frame around the wrapped widget.
996 p.setPen( g.color( QPalette::Dark ) );
997 p.drawRect( x+borderWidth-1, y+titleHeight+3, w-2*borderWidth+1, h-titleHeight-offset-2 );
999 // Draw the title bar.
1000 r = titleRect();
1002 // Obtain titlebar blend colours
1003 QColor c1 = options()->color(ColorTitleBar, isActive() );
1004 QColor c2 = options()->color(ColorFrame, isActive() );
1006 // Fill with frame color behind RHS buttons
1007 p.fillRect( rightOffset, y+2, x2-rightOffset-1, titleHeight+1, c2);
1009 QPainter p2( titleBuffer );
1010 p2.initFrom( widget());
1012 // Draw the titlebar gradient
1013 if (upperGradient)
1014 p2.drawTiledPixmap(0, 0, rightOffset-3, titleHeight+1, *upperGradient);
1015 else
1016 p2.fillRect(0, 0, rightOffset-3, titleHeight+1, c1);
1018 // Draw the title text on the pixmap, and with a smaller font
1019 // for toolwindows than the default.
1020 QFont fnt = options()->font(true);
1022 if ( isToolWindow() )
1023 fnt.setPointSize( fnt.pointSize()-2 ); // Shrink font by 2pt
1025 p2.setFont( fnt );
1027 // Draw the titlebar stipple if active and available
1028 if (isActive() && titlePix)
1030 QFontMetrics fm(fnt);
1031 int captionWidth = fm.width(caption());
1032 if (caption().isRightToLeft())
1033 p2.drawTiledPixmap( r.x(), 0, r.width()-captionWidth-4,
1034 titleHeight+1, *titlePix );
1035 else
1036 p2.drawTiledPixmap( r.x()+captionWidth+3, 0, r.width()-captionWidth-4,
1037 titleHeight+1, *titlePix );
1040 p2.setPen( options()->color(ColorFont, isActive()) );
1041 p2.drawText(r.x(), 1, r.width()-1, r.height(),
1042 (caption().isRightToLeft() ? Qt::AlignRight : Qt::AlignLeft) | Qt::AlignVCenter,
1043 caption() );
1045 p2.end();
1047 p.drawPixmap( 2, 2, *titleBuffer );
1049 // Ensure a shaded window has no unpainted areas
1050 // Is this still needed?
1051 #if 1
1052 p.setPen(c2);
1053 p.drawLine(x+borderWidth, y+titleHeight+4, x2-borderWidth, y+titleHeight+4);
1054 #endif
1057 QRegion KDE2Client::cornerShape(WindowCorner corner)
1059 switch (corner) {
1060 case WC_TopLeft:
1061 return QRect(0, 0, 1, 1);
1063 case WC_TopRight:
1064 return QRect(width()-1, 0, 1, 1);
1066 case WC_BottomLeft:
1067 return QRect(0, height()-1, 1, 1);
1069 case WC_BottomRight:
1070 return QRect(width()-1, height()-1, 1, 1);
1072 default:
1073 return QRegion();
1077 } // namespace
1079 // Extended KWin plugin interface
1080 extern "C" KDE_EXPORT KDecorationFactory* create_factory()
1082 return new KDE2::KDE2Handler();
1085 // vim: ts=4 sw=4
1086 // kate: space-indent off; tab-width 4;