add more spacing
[personal-kdebase.git] / workspace / kwin / clients / quartz / quartz.cpp
blob3f9aa5c5397e38ff2a13b3664d76eab95603bf06
1 /********************************************************************
3 Gallium-Quartz KWin client
5 Copyright (C) 2005 Sandro Giessl <sandro@giessl.com>
6 Copyright 2001
7 Karol Szwed <gallium@kde.org>
8 http://gallium.n3.net/
10 Based on the KDE default client.
12 Includes mini titlebars for ToolWindow Support.
13 Button positions are now customizable.
15 drawColorBitmaps orignally from kdefx:
16 Copyright (C) 1999 Daniel M. Duley <mosfet@kde.org>
18 This program is free software; you can redistribute it and/or modify
19 it under the terms of the GNU General Public License as published by
20 the Free Software Foundation; either version 2 of the License, or
21 (at your option) any later version.
23 This program is distributed in the hope that it will be useful,
24 but WITHOUT ANY WARRANTY; without even the implied warranty of
25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 GNU General Public License for more details.
28 You should have received a copy of the GNU General Public License
29 along with this program. If not, see <http://www.gnu.org/licenses/>.
30 *********************************************************************/
32 #include <kconfiggroup.h>
33 #include <kglobal.h>
34 #include <klocale.h>
35 #include <QBitmap>
36 #include <QImage>
37 #include <QPixmap>
38 #include <QApplication>
39 #include <QPaintEvent>
40 #include <QPainter>
42 #include "quartz.h"
45 namespace Quartz {
47 static const unsigned char iconify_bits[] = {
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00, 0x00 };
51 static const unsigned char close_bits[] = {
52 0x00, 0x00, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x78, 0x00,
53 0xcc, 0x00, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00};
55 static const unsigned char maximize_bits[] = {
56 0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
57 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, 0x00, 0x00};
59 static const unsigned char minmax_bits[] = {
60 0xfc, 0x00, 0xfc, 0x00, 0x84, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xe1, 0x00,
61 0x21, 0x00, 0x21, 0x00, 0x3f, 0x00, 0x00, 0x00};
63 static const unsigned char question_bits[] = {
64 0x00, 0x00, 0x3c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00,
65 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00};
67 static const unsigned char pindown_white_bits[] = {
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0xa0, 0x03,
69 0xb0, 0x01, 0x30, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
72 static const unsigned char pindown_gray_bits[] = {
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
74 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x80, 0x07, 0xc0, 0x03, 0xe0, 0x01,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
77 static const unsigned char pindown_dgray_bits[] = {
78 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x10, 0x70, 0x20, 0x50, 0x20,
79 0x48, 0x30, 0xc8, 0x38, 0x08, 0x1f, 0x08, 0x18, 0x10, 0x1c, 0x10, 0x0e,
80 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
82 static const unsigned char pinup_white_bits[] = {
83 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x11,
84 0x3f, 0x15, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
87 static const unsigned char pinup_gray_bits[] = {
88 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89 0x80, 0x0a, 0xbf, 0x0a, 0x80, 0x15, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
90 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
92 static const unsigned char pinup_dgray_bits[] = {
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x40, 0x31, 0x40, 0x2e,
94 0x40, 0x20, 0x40, 0x20, 0x7f, 0x2a, 0x40, 0x3f, 0xc0, 0x31, 0xc0, 0x20,
95 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
97 static const unsigned char above_on_bits[] = {
98 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00,
99 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
101 static const unsigned char above_off_bits[] = {
102 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01,
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
105 static const unsigned char below_on_bits[] = {
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00,
107 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00};
109 static const unsigned char below_off_bits[] = {
110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01,
111 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00, 0x30, 0x00};
113 static const unsigned char shade_on_bits[] = {
114 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x02, 0x01, 0x02, 0x01,
115 0x02, 0x01, 0x02, 0x01, 0xfe, 0x01, 0x00, 0x00};
117 static const unsigned char shade_off_bits[] = {
118 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00,
119 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
121 void drawColorBitmaps(QPainter *p, const QPalette &pal, int x, int y, int w, int h,
122 const uchar *lightColor, const uchar *midColor, const uchar *blackColor)
124 const uchar *data[]={lightColor, midColor, blackColor};
126 QColor colors[]={pal.color(QPalette::Light), pal.color(QPalette::Mid), Qt::black};
128 int i;
129 QSize s(w,h);
130 for(i=0; i < 3; ++i){
131 QBitmap b = QBitmap::fromData(s, data[i], QImage::Format_MonoLSB );
132 b.setMask(b);
133 p->setPen(colors[i]);
134 p->drawPixmap(x, y, b);
138 ///////////////////////////////////////////////////////////////////////////
140 // Titlebar button positions
141 bool onAllDesktopsButtonOnLeft = true;
142 bool coloredFrame = true;
143 bool extraSlim = false;
145 QPixmap* titleBlocks = NULL;
146 QPixmap* ititleBlocks = NULL;
147 QPixmap* pinDownPix = NULL;
148 QPixmap* pinUpPix = NULL;
149 QPixmap* ipinDownPix = NULL;
150 QPixmap* ipinUpPix = NULL;
151 static int normalTitleHeight;
152 static int toolTitleHeight;
153 static int borderWidth;
155 bool quartz_initialized = false;
156 QuartzHandler* clientHandler;
158 ///////////////////////////////////////////////////////////////////////////
161 QuartzHandler::QuartzHandler()
163 quartz_initialized = false;
164 readConfig();
165 createPixmaps();
166 quartz_initialized = true;
170 QuartzHandler::~QuartzHandler()
172 quartz_initialized = false;
173 freePixmaps();
177 KDecoration* QuartzHandler::createDecoration( KDecorationBridge* bridge )
179 return ( new QuartzClient( bridge, this ))->decoration();
183 bool QuartzHandler::reset(unsigned long changed)
185 quartz_initialized = false;
186 freePixmaps();
187 readConfig();
188 createPixmaps();
189 quartz_initialized = true;
191 // Do we need to "hit the wooden hammer" ?
192 bool needHardReset = true;
193 if ((changed & ~(SettingColors | SettingButtons)) == 0)
195 needHardReset = false;
198 if (needHardReset) {
199 return true;
200 } else {
201 resetDecorations(changed);
202 return false;
204 return true;
208 bool QuartzHandler::supports( Ability ability ) const
210 switch( ability )
212 // announce
213 case AbilityAnnounceButtons:
214 case AbilityAnnounceColors:
215 // buttons
216 case AbilityButtonMenu:
217 case AbilityButtonOnAllDesktops:
218 case AbilityButtonHelp:
219 case AbilityButtonMinimize:
220 case AbilityButtonMaximize:
221 case AbilityButtonClose:
222 case AbilityButtonAboveOthers:
223 case AbilityButtonBelowOthers:
224 case AbilityButtonShade:
225 case AbilityButtonSpacer:
226 // colors
227 case AbilityColorTitleBack:
228 case AbilityColorTitleBlend:
229 case AbilityColorTitleFore:
230 case AbilityColorButtonBack:
231 return true;
232 default:
233 return false;
238 void QuartzHandler::readConfig()
240 KConfig configFile("kwinquartzrc");
241 KConfigGroup conf( &configFile, "General");
242 coloredFrame = conf.readEntry( "UseTitleBarBorderColors", true);
243 extraSlim = conf.readEntry( "UseQuartzExtraSlim", false);
245 // A small hack to make the on all desktops button look nicer
246 onAllDesktopsButtonOnLeft = KDecoration::options()->titleButtonsLeft().contains( 'S' );
247 if ( QApplication::isRightToLeft() )
248 onAllDesktopsButtonOnLeft = !onAllDesktopsButtonOnLeft;
249 switch(options()->preferredBorderSize(this)) {
250 case BorderLarge:
251 borderWidth = 8;
252 break;
253 case BorderVeryLarge:
254 borderWidth = 12;
255 break;
256 case BorderHuge:
257 borderWidth = 18;
258 break;
259 case BorderVeryHuge:
260 borderWidth = 27;
261 break;
262 case BorderOversized:
263 borderWidth = 40;
264 break;
265 case BorderTiny:
266 case BorderNormal:
267 default:
268 borderWidth = extraSlim?2:4;
271 normalTitleHeight = QFontMetrics(options()->font(true)).height() - 2;
272 int nTH_limit=extraSlim?14:18;
273 normalTitleHeight = QFontMetrics(options()->font(true)).height()-(extraSlim?1:0);
274 if (normalTitleHeight < nTH_limit) normalTitleHeight = nTH_limit;
275 if (normalTitleHeight < borderWidth) normalTitleHeight = borderWidth;
277 toolTitleHeight = QFontMetrics(options()->font(true, true)).height() - 2;
278 if (toolTitleHeight < 12) toolTitleHeight = 12;
279 if (toolTitleHeight < borderWidth) toolTitleHeight = borderWidth;
283 // This does the colour transition magic. (You say "Oh, is that it?")
284 // This may be made configurable at a later stage
285 void QuartzHandler::drawBlocks( QPixmap *pi, QPixmap &p, const QColor &c1, const QColor &c2 )
287 // Draw a background gradient first
288 QPainter gp;
289 gp.begin(&p);
290 QLinearGradient grad(0, 0, p.width(), 0);
291 grad.setColorAt(0.0, c1);
292 grad.setColorAt(1.0, c2);
293 gp.setPen(Qt::NoPen);
294 gp.setBrush(grad);
295 gp.drawRect(p.rect());
296 gp.end();
298 QPainter px;
300 px.begin( pi );
302 int factor = (pi->height()-2)/4;
303 int square = factor - (factor+2)/4;
305 int x = pi->width() - 5*factor - square;
306 int y = (pi->height() - 4*factor)/2;
308 px.fillRect( x, y, square, square, c1.light(120) );
309 px.fillRect( x, y+factor, square, square, c1 );
310 px.fillRect( x, y+2*factor, square, square, c1.light(110) );
311 px.fillRect( x, y+3*factor, square, square, c1 );
313 px.fillRect( x+factor, y, square, square, c1.light(110) );
314 px.fillRect( x+factor, y+factor, square, square, c2.light(110) );
315 px.fillRect( x+factor, y+2*factor, square, square, c1.light(120) );
316 px.fillRect( x+factor, y+3*factor, square, square, c2.light(130) );
318 px.fillRect( x+2*factor, y+factor, square, square, c1.light(110) );
319 px.fillRect( x+2*factor, y+2*factor, square, square, c2.light(120) );
320 px.fillRect( x+2*factor, y+3*factor, square, square, c2.light(150) );
322 px.fillRect( x+3*factor, y, square, square, c1.dark(110) );
323 px.fillRect( x+3*factor, y+2*factor, square, square, c2.light(120) );
324 px.fillRect( x+3*factor, y+3*factor, square, square, c1.dark(120) );
326 px.fillRect( x+4*factor, y+factor, square, square, c1.light(110) );
327 px.fillRect( x+4*factor, y+3*factor, square, square, c1.dark(110) );
329 px.fillRect( x+5*factor, y+2*factor, square, square, c2.light(120));
330 px.fillRect( x+5*factor, y+3*factor, square, square, c2.light(110) );
334 // This paints the button pixmaps upon loading the style.
335 void QuartzHandler::createPixmaps()
337 // Obtain titlebar blend colours, and create the block stuff on pixmaps.
338 QPalette g2 = options()->palette(ColorTitleBlend, true);
339 g2.setCurrentColorGroup( QPalette::Active );
340 QColor c2 = g2.color( QPalette::Background );
341 g2 = options()->palette(ColorTitleBar, true );
342 g2.setCurrentColorGroup( QPalette::Active );
343 QColor c = g2.color(QPalette::Background).light(130);
345 titleBlocks = new QPixmap( normalTitleHeight*25/18, normalTitleHeight );
346 drawBlocks( titleBlocks, *titleBlocks, c, c2 );
348 g2 = options()->palette(ColorTitleBlend, false);
349 g2.setCurrentColorGroup( QPalette::Active );
350 c2 = g2.color( QPalette::Background );
351 g2 = options()->palette(ColorTitleBar, false );
352 g2.setCurrentColorGroup( QPalette::Active );
353 c = g2.color(QPalette::Background).light(130);
355 ititleBlocks = new QPixmap( normalTitleHeight*25/18, normalTitleHeight );
356 drawBlocks( ititleBlocks, *ititleBlocks, c, c2 );
358 // Set the on all desktops pin pixmaps;
359 QPalette g;
360 QPainter p;
362 g = options()->palette( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, true );
363 g.setCurrentColorGroup( QPalette::Active );
364 c = onAllDesktopsButtonOnLeft ? g.color(QPalette::Background).light(130) : g.color(QPalette::Background);
365 g2 = options()->palette( ColorButtonBg, true );
366 g2.setCurrentColorGroup( QPalette::Active );
368 QImage pinImg = QImage(16, 16, QImage::Format_ARGB32_Premultiplied);
369 p.begin(&pinImg);
370 p.fillRect( 0, 0, 16, 16, c);
371 drawColorBitmaps( &p, g2, 0, 1, 16, 16, pinup_white_bits, pinup_gray_bits, pinup_dgray_bits );
372 p.end();
373 pinUpPix = new QPixmap(QPixmap::fromImage(pinImg));
375 p.begin(&pinImg);
376 p.fillRect( 0, 0, 16, 16, c);
377 drawColorBitmaps( &p, g2, 0, 1, 16, 16, pindown_white_bits, pindown_gray_bits, pindown_dgray_bits );
378 p.end();
379 pinDownPix = new QPixmap(QPixmap::fromImage(pinImg));
381 // Inactive pins
382 g = options()->palette( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, false );
383 g.setCurrentColorGroup( QPalette::Active );
384 c = onAllDesktopsButtonOnLeft ? g.color(QPalette::Background).light(130) : g.color( QPalette::Background );
385 g2 = options()->palette( ColorButtonBg, false );
386 g2.setCurrentColorGroup( QPalette::Active );
388 p.begin(&pinImg);
389 p.fillRect( 0, 0, 16, 16, c);
390 drawColorBitmaps( &p, g2, 0, 1, 16, 16, pinup_white_bits, pinup_gray_bits, pinup_dgray_bits );
391 p.end();
392 ipinUpPix = new QPixmap(QPixmap::fromImage(pinImg));
394 p.begin(&pinImg);
395 p.fillRect( 0, 0, 16, 16, c);
396 drawColorBitmaps( &p, g2, 0, 1, 16, 16, pindown_white_bits, pindown_gray_bits, pindown_dgray_bits );
397 p.end();
398 ipinDownPix = new QPixmap(QPixmap::fromImage(pinImg));
402 void QuartzHandler::freePixmaps()
404 delete titleBlocks;
405 delete ititleBlocks;
407 // On all desktops pin images
408 delete pinUpPix;
409 delete ipinUpPix;
410 delete pinDownPix;
411 delete ipinDownPix;
415 QList< QuartzHandler::BorderSize > QuartzHandler::borderSizes() const
416 { // the list must be sorted
417 return QList< BorderSize >() << BorderNormal << BorderLarge <<
418 BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized;
422 QuartzButton::QuartzButton(ButtonType type, QuartzClient *parent, const char *name)
423 : KCommonDecorationButton(type, parent)
425 setObjectName( name );
426 // Eliminate any possible background flicker
427 setAttribute(Qt::WA_NoSystemBackground, false);
429 deco = 0;
433 QuartzButton::~QuartzButton()
435 delete deco;
438 void QuartzButton::reset(unsigned long changed)
440 if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) {
441 switch (type() ) {
442 case CloseButton:
443 setBitmap(close_bits);
444 break;
445 case HelpButton:
446 setBitmap(question_bits);
447 break;
448 case MinButton:
449 setBitmap(iconify_bits);
450 break;
451 case MaxButton:
452 setBitmap( isChecked() ? minmax_bits : maximize_bits );
453 break;
454 case OnAllDesktopsButton:
455 setBitmap(0);
456 break;
457 case ShadeButton:
458 setBitmap( isChecked() ? shade_on_bits : shade_off_bits );
459 break;
460 case AboveButton:
461 setBitmap( isChecked() ? above_on_bits : above_off_bits );
462 break;
463 case BelowButton:
464 setBitmap( isChecked() ? below_on_bits : below_off_bits );
465 break;
466 default:
467 setBitmap(0);
468 break;
471 this->update();
475 void QuartzButton::setBitmap(const unsigned char *bitmap)
477 delete deco;
478 deco = 0;
480 if (bitmap) {
481 deco = new QBitmap(QBitmap::fromData(QSize(10, 10), bitmap));
482 deco->setMask( *deco );
483 repaint( );
487 void QuartzButton::paintEvent(QPaintEvent *)
489 QPainter p(this);
490 drawButton(&p);
493 void QuartzButton::drawButton(QPainter *p)
495 // Never paint if the pixmaps have not been created
496 if (!quartz_initialized)
497 return;
499 QColor c;
501 if (isLeft() )
502 c = KDecoration::options()->color(KDecoration::ColorTitleBar, decoration()->isActive()).light(130);
503 else
504 c = KDecoration::options()->color(KDecoration::ColorTitleBlend, decoration()->isActive());
506 // Fill the button background with an appropriate color
507 p->fillRect(0, 0, width(), height(), c );
509 // If we have a decoration bitmap, then draw that
510 // otherwise we paint a menu button (with mini icon), or a onAllDesktops button.
511 if( deco )
513 int xOff = (width()-10)/2;
514 int yOff = (height()-10)/2;
515 p->setPen( Qt::black );
516 p->drawPixmap(isDown() ? xOff+2: xOff+1, isDown() ? yOff+2 : yOff+1, *deco);
517 p->setPen( KDecoration::options()->color(KDecoration::ColorButtonBg, decoration()->isActive()).light(150) );
518 p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, *deco);
519 } else
521 QPixmap btnpix;
522 int Offset = 0;
524 if (type() == OnAllDesktopsButton)
526 if (isDown())
527 Offset = 1;
529 // Select the right onAllDesktops button to paint
530 if (decoration()->isActive())
531 btnpix = isChecked() ? *pinDownPix : *pinUpPix;
532 else
533 btnpix = isChecked() ? *ipinDownPix : *ipinUpPix;
535 } else
536 btnpix = decoration()->icon().pixmap( QSize(10,10), QIcon::Normal);
538 // Shrink the miniIcon for tiny titlebars.
539 if ( height() < 16)
541 // Smooth scale the image
542 QPixmap tmpPix = btnpix.scaled(height(), height(), Qt::IgnoreAspectRatio,Qt::SmoothTransformation);
543 p->drawPixmap( 0, 0, tmpPix );
544 } else {
545 Offset += (height() - 16)/2;
546 p->drawPixmap( Offset, Offset, btnpix );
551 ///////////////////////////////////////////////////////////////////////////
553 QuartzClient::QuartzClient(KDecorationBridge* bridge, KDecorationFactory* factory)
554 : KCommonDecoration (bridge, factory)
558 QString QuartzClient::visibleName() const
560 return i18n("Quartz");
563 QString QuartzClient::defaultButtonsLeft() const
565 return "M";
568 QString QuartzClient::defaultButtonsRight() const
570 return "HIA__X";
573 bool QuartzClient::decorationBehaviour(DecorationBehaviour behaviour) const
575 switch (behaviour) {
576 case DB_MenuClose:
577 return false;
579 case DB_WindowMask:
580 return false;
582 case DB_ButtonHide:
583 return true;
585 default:
586 return KCommonDecoration::decorationBehaviour(behaviour);
590 int QuartzClient::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *btn) const
592 bool maximized = maximizeMode()==MaximizeFull && !options()->moveResizeMaximizedWindows();
594 switch (lm) {
595 case LM_BorderLeft:
596 case LM_BorderRight:
597 case LM_BorderBottom:
598 case LM_TitleEdgeLeft:
599 case LM_TitleEdgeRight:
601 if (respectWindowState && maximized) {
602 return 0;
603 } else {
604 return borderSize;
608 case LM_TitleEdgeTop:
609 return borderSize-1;
611 case LM_TitleEdgeBottom:
612 return 1;
614 case LM_TitleBorderLeft:
615 case LM_TitleBorderRight:
616 return 5;
618 case LM_TitleHeight:
619 return titleHeight;
621 case LM_ButtonWidth:
622 case LM_ButtonHeight:
623 return titleHeight-2;
625 case LM_ButtonSpacing:
626 return 1;
628 default:
629 return KCommonDecoration::layoutMetric(lm, respectWindowState, btn);
633 KCommonDecorationButton *QuartzClient::createButton(ButtonType type)
635 switch (type) {
636 case MenuButton:
637 return new QuartzButton(MenuButton, this, "menu");
639 case OnAllDesktopsButton:
640 return new QuartzButton(OnAllDesktopsButton, this, "on_all_desktops");
642 case HelpButton:
643 return new QuartzButton(HelpButton, this, "help");
645 case MinButton:
646 return new QuartzButton(MinButton, this, "minimize");
648 case MaxButton:
649 return new QuartzButton(MaxButton, this, "maximize");
651 case CloseButton:
652 return new QuartzButton(CloseButton, this, "close");
654 case AboveButton:
655 return new QuartzButton(AboveButton, this, "above");
657 case BelowButton:
658 return new QuartzButton(BelowButton, this, "below");
660 case ShadeButton:
661 return new QuartzButton(ShadeButton, this, "shade");
663 default:
664 return 0;
669 void QuartzClient::init()
671 // Finally, toolWindows look small
672 if ( isToolWindow() ) {
673 titleHeight = toolTitleHeight;
674 largeButtons = false;
676 else {
677 titleHeight = normalTitleHeight;
678 largeButtons = true;
681 borderSize = borderWidth;
683 KCommonDecoration::init();
686 void QuartzClient::reset( unsigned long changed )
688 if (changed & SettingColors || changed & SettingFont)
690 // repaint the whole thing
691 widget()->repaint();
694 KCommonDecoration::reset(changed);
698 // Quartz Paint magic goes here.
699 void QuartzClient::paintEvent( QPaintEvent* )
701 // Never paint if the pixmaps have not been created
702 if (!quartz_initialized)
703 return;
705 const bool maxFull = (maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows();
707 QPalette g;
708 QPainter p(widget());
710 // Obtain widget bounds.
711 QRect r(widget()->rect());
712 int x = r.x();
713 int y = r.y();
714 int x2 = r.width() - 1;
715 int y2 = r.height() - 1;
716 int w = r.width();
717 int h = r.height();
719 // Draw part of the frame that is the title color
721 if( coloredFrame )
722 g = options()->palette(ColorTitleBar, isActive());
723 else
724 g = options()->palette(ColorFrame, isActive());
725 g.setCurrentColorGroup( QPalette::Active );
727 // Draw outer highlights and lowlights
728 p.setPen( g.color(QPalette::Light).light(120) );
729 p.drawLine( x, y, x2-1, y );
730 p.drawLine( x, y+1, x, y2-1 );
731 p.setPen( g.color(QPalette::Dark).light(120) );
732 p.drawLine( x2, y, x2, y2 );
733 p.drawLine( x, y2, x2, y2 );
735 // Fill out the border edges
736 QColor frameColor;
737 if ( coloredFrame)
738 frameColor = g.color(QPalette::Background).light(130);
739 else
740 frameColor = g.color( QPalette::Background );
741 if (borderSize > 2) {
742 p.fillRect(x+1, y+1, w-2, borderSize-2, frameColor); // top
743 if (!maxFull) {
744 p.fillRect(x+1, y+h-(borderSize), w-2, borderSize-1, frameColor); // bottom
745 p.fillRect(x+1, y+borderSize-1, borderSize-1, h-2*(borderSize-1), frameColor); // left
746 p.fillRect(x+w-(borderSize), y+borderSize-1, borderSize-1, h-2*(borderSize-1), frameColor); // right
750 // Draw a frame around the wrapped widget.
751 p.setPen( g.color(QPalette::Background) );
752 if (maxFull) {
753 p.drawLine(x+1, y+titleHeight+(borderSize-1), w-2, y+titleHeight+(borderSize-1));
754 } else {
755 p.drawRect( x+(borderSize-1), y+titleHeight+(borderSize-1), w-2*(borderSize-1)-1, h-titleHeight-2*(borderSize-1)-1 );
758 // Drawing this extra line removes non-drawn areas when shaded
759 p.drawLine( x+borderSize, y2-borderSize, x2-borderSize, y2-borderSize);
761 // Highlight top corner
762 p.setPen( g.color(QPalette::Light).light(160) );
763 p.drawPoint( x, y );
764 p.setPen( g.color(QPalette::Light).light(140) );
765 p.drawPoint( x+1, y );
766 p.drawPoint( x, y+1 );
768 // Draw the title bar.
769 // ===================
770 int r_x, r_y, r_x2, r_y2;
771 widget()->rect().getCoords(&r_x, &r_y, &r_x2, &r_y2);
772 const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
773 const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
774 const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);
775 const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
776 const int ttlHeight = layoutMetric(LM_TitleHeight);
777 const int titleEdgeBottomBottom = r_y+titleEdgeTop+ttlHeight+titleEdgeBottom-1;
778 r = QRect(r_x+titleEdgeLeft+buttonsLeftWidth(), r_y+titleEdgeTop,
779 r_x2-titleEdgeRight-buttonsRightWidth()-(r_x+titleEdgeLeft+buttonsLeftWidth()),
780 titleEdgeBottomBottom-(r_y+titleEdgeTop) );
782 // Obtain titlebar blend colours
783 QColor c1 = options()->color(ColorTitleBar, isActive() ).light(130);
784 QColor c2 = options()->color(ColorTitleBlend, isActive() );
786 // Create a disposable pixmap buffer for the titlebar
787 QPixmap* titleBuffer = new QPixmap( maxFull?w-2:(w-2*(borderSize-1)), titleHeight );
789 QPainter p2( titleBuffer );
791 // subtract titleBlocks pixmap width and some
792 int rightoffset = r.x()+r.width()-titleBlocks->width()-borderSize;
794 p2.fillRect( 0, 0, w, r.height(), c1 );
795 p2.fillRect( rightoffset, 0, maxFull?w-rightoffset:w-rightoffset-2*(borderSize-1), r.height(), c2 );
797 // 8 bit displays will be a bit dithered, but they still look ok.
798 if ( isActive() )
799 p2.drawPixmap( rightoffset, 0, *titleBlocks );
800 else
801 p2.drawPixmap( rightoffset, 0, *ititleBlocks );
803 // Draw the title text on the pixmap, and with a smaller font
804 // for toolwindows than the default.
805 QFont fnt;
806 if ( largeButtons ) {
807 fnt = options()->font(true, false); // font not small
808 } else {
809 fnt = options()->font(true, true); // font small
810 fnt.setWeight( QFont::Normal ); // and disable bold
812 p2.setFont( fnt );
814 p2.setPen( options()->color(ColorFont, isActive() ));
815 p2.drawText(r.x()+4-borderSize, 0, r.width()-3, r.height(),
816 Qt::AlignLeft | Qt::AlignVCenter, caption() );
817 p2.end();
819 p.drawPixmap( maxFull?1:borderSize-1, borderSize-1, *titleBuffer );
821 delete titleBuffer;
826 // Extended KWin plugin interface
827 /////////////////////////////////
828 extern "C"
830 KDE_EXPORT KDecorationFactory *create_factory()
832 Quartz::clientHandler = new Quartz::QuartzHandler();
833 return Quartz::clientHandler;
839 #include "quartz.moc"
840 // vim: ts=4
841 // kate: space-indent off; tab-width 4;