00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <kconfig.h>
00017 #include <kdrawutil.h>
00018 #include <kglobal.h>
00019 #include <klocale.h>
00020 #include <kpixmapeffect.h>
00021 #include <qbitmap.h>
00022 #include <qcursor.h>
00023 #include <qdrawutil.h>
00024 #include <qimage.h>
00025 #include <qlabel.h>
00026 #include <qlayout.h>
00027 #include <qtooltip.h>
00028 #include <qapplication.h>
00029
00030 #include "quartz.h"
00031
00032
00033 namespace Quartz {
00034
00035 static const unsigned char iconify_bits[] = {
00036 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00,
00037 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
00038
00039 static const unsigned char close_bits[] = {
00040 0x00, 0x00, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x78, 0x00,
00041 0xcc, 0x00, 0x86, 0x01, 0x00, 0x00, 0x00, 0x00};
00042
00043 static const unsigned char maximize_bits[] = {
00044 0xff, 0x01, 0xff, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
00045 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, 0x00, 0x00};
00046
00047 static const unsigned char minmax_bits[] = {
00048 0xfc, 0x00, 0xfc, 0x00, 0x84, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xe1, 0x00,
00049 0x21, 0x00, 0x21, 0x00, 0x3f, 0x00, 0x00, 0x00};
00050
00051 static const unsigned char question_bits[] = {
00052 0x00, 0x00, 0x3c, 0x00, 0x66, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00,
00053 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00};
00054
00055 static const unsigned char pindown_white_bits[] = {
00056 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x1f, 0xa0, 0x03,
00057 0xb0, 0x01, 0x30, 0x01, 0xf0, 0x00, 0x70, 0x00, 0x20, 0x00, 0x00, 0x00,
00058 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00059
00060 static const unsigned char pindown_gray_bits[] = {
00061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
00062 0x00, 0x0e, 0x00, 0x06, 0x00, 0x00, 0x80, 0x07, 0xc0, 0x03, 0xe0, 0x01,
00063 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00064
00065 static const unsigned char pindown_dgray_bits[] = {
00066 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x10, 0x70, 0x20, 0x50, 0x20,
00067 0x48, 0x30, 0xc8, 0x38, 0x08, 0x1f, 0x08, 0x18, 0x10, 0x1c, 0x10, 0x0e,
00068 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00069
00070 static const unsigned char pinup_white_bits[] = {
00071 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x11,
00072 0x3f, 0x15, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00073 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00074
00075 static const unsigned char pinup_gray_bits[] = {
00076 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
00077 0x80, 0x0a, 0xbf, 0x0a, 0x80, 0x15, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
00078 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00079
00080 static const unsigned char pinup_dgray_bits[] = {
00081 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x40, 0x31, 0x40, 0x2e,
00082 0x40, 0x20, 0x40, 0x20, 0x7f, 0x2a, 0x40, 0x3f, 0xc0, 0x31, 0xc0, 0x20,
00083 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00084
00085 static const unsigned char above_on_bits[] = {
00086 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00,
00087 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00088
00089 static const unsigned char above_off_bits[] = {
00090 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00, 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01,
00091 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00092
00093 static const unsigned char below_on_bits[] = {
00094 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0xfc, 0x00,
00095 0x30, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00};
00096
00097 static const unsigned char below_off_bits[] = {
00098 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01,
00099 0x30, 0x00, 0xfc, 0x00, 0x78, 0x00, 0x30, 0x00};
00100
00101 static const unsigned char shade_on_bits[] = {
00102 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x02, 0x01, 0x02, 0x01,
00103 0x02, 0x01, 0x02, 0x01, 0xfe, 0x01, 0x00, 0x00};
00104
00105 static const unsigned char shade_off_bits[] = {
00106 0x00, 0x00, 0xfe, 0x01, 0xfe, 0x01, 0xfe, 0x01, 0x00, 0x00, 0x00, 0x00,
00107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00108
00109
00111
00112
00113 bool onAllDesktopsButtonOnLeft = true;
00114 bool coloredFrame = true;
00115
00116 KPixmap* titleBlocks = NULL;
00117 KPixmap* ititleBlocks = NULL;
00118 KPixmap* pinDownPix = NULL;
00119 KPixmap* pinUpPix = NULL;
00120 KPixmap* ipinDownPix = NULL;
00121 KPixmap* ipinUpPix = NULL;
00122 static int normalTitleHeight;
00123 static int toolTitleHeight;
00124 static int borderWidth;
00125
00126 bool quartz_initialized = false;
00127 QuartzHandler* clientHandler;
00128
00130
00131
00132 QuartzHandler::QuartzHandler()
00133 {
00134 quartz_initialized = false;
00135 readConfig();
00136 createPixmaps();
00137 quartz_initialized = true;
00138 }
00139
00140
00141 QuartzHandler::~QuartzHandler()
00142 {
00143 quartz_initialized = false;
00144 freePixmaps();
00145 }
00146
00147
00148 KDecoration* QuartzHandler::createDecoration( KDecorationBridge* bridge )
00149 {
00150 return new QuartzClient( bridge, this );
00151 }
00152
00153
00154 bool QuartzHandler::reset(unsigned long changed)
00155 {
00156 quartz_initialized = false;
00157 freePixmaps();
00158 readConfig();
00159 createPixmaps();
00160 quartz_initialized = true;
00161
00162
00163 bool needHardReset = true;
00164 if (changed & SettingColors)
00165 {
00166 needHardReset = false;
00167 }
00168
00169 if (needHardReset) {
00170 return true;
00171 } else {
00172 resetDecorations(changed);
00173 return false;
00174 }
00175 return true;
00176 }
00177
00178
00179 void QuartzHandler::readConfig()
00180 {
00181 KConfig conf("kwinquartzrc");
00182 conf.setGroup("General");
00183 coloredFrame = conf.readBoolEntry( "UseTitleBarBorderColors", true );
00184
00185
00186 onAllDesktopsButtonOnLeft = KDecoration::options()->titleButtonsLeft().contains( 'S' );
00187 if ( QApplication::reverseLayout() )
00188 onAllDesktopsButtonOnLeft = !onAllDesktopsButtonOnLeft;
00189 switch(options()->preferredBorderSize(this)) {
00190 case BorderLarge:
00191 borderWidth = 8;
00192 break;
00193 case BorderVeryLarge:
00194 borderWidth = 12;
00195 break;
00196 case BorderHuge:
00197 borderWidth = 18;
00198 break;
00199 case BorderVeryHuge:
00200 borderWidth = 27;
00201 break;
00202 case BorderOversized:
00203 borderWidth = 40;
00204 break;
00205 case BorderTiny:
00206 case BorderNormal:
00207 default:
00208 borderWidth = 4;
00209 }
00210
00211 normalTitleHeight = QFontMetrics(options()->font(true)).height();
00212 if (normalTitleHeight < 18) normalTitleHeight = 18;
00213 if (normalTitleHeight < borderWidth) normalTitleHeight = borderWidth;
00214
00215 toolTitleHeight = QFontMetrics(options()->font(true, true)).height();
00216 if (toolTitleHeight < 12) toolTitleHeight = 12;
00217 if (toolTitleHeight < borderWidth) toolTitleHeight = borderWidth;
00218 }
00219
00220
00221
00222
00223 void QuartzHandler::drawBlocks( KPixmap *pi, KPixmap &p, const QColor &c1, const QColor &c2 )
00224 {
00225 QPainter px;
00226
00227 px.begin( pi );
00228
00229
00230 KPixmapEffect::gradient(p, c1, c2, KPixmapEffect::HorizontalGradient);
00231
00232 int factor = (pi->height()-2)/4;
00233 int square = factor - (factor+2)/4;
00234
00235 int x = pi->width() - 5*factor - square;
00236 int y = (pi->height() - 4*factor)/2;
00237
00238 px.fillRect( x, y, square, square, c1.light(120) );
00239 px.fillRect( x, y+factor, square, square, c1 );
00240 px.fillRect( x, y+2*factor, square, square, c1.light(110) );
00241 px.fillRect( x, y+3*factor, square, square, c1 );
00242
00243 px.fillRect( x+factor, y, square, square, c1.light(110) );
00244 px.fillRect( x+factor, y+factor, square, square, c2.light(110) );
00245 px.fillRect( x+factor, y+2*factor, square, square, c1.light(120) );
00246 px.fillRect( x+factor, y+3*factor, square, square, c2.light(130) );
00247
00248 px.fillRect( x+2*factor, y+factor, square, square, c1.light(110) );
00249 px.fillRect( x+2*factor, y+2*factor, square, square, c2.light(120) );
00250 px.fillRect( x+2*factor, y+3*factor, square, square, c2.light(150) );
00251
00252 px.fillRect( x+3*factor, y, square, square, c1.dark(110) );
00253 px.fillRect( x+3*factor, y+2*factor, square, square, c2.light(120) );
00254 px.fillRect( x+3*factor, y+3*factor, square, square, c1.dark(120) );
00255
00256 px.fillRect( x+4*factor, y+factor, square, square, c1.light(110) );
00257 px.fillRect( x+4*factor, y+3*factor, square, square, c1.dark(110) );
00258
00259 px.fillRect( x+5*factor, y+2*factor, square, square, c2.light(120));
00260 px.fillRect( x+5*factor, y+3*factor, square, square, c2.light(110) );
00261 }
00262
00263
00264
00265 void QuartzHandler::createPixmaps()
00266 {
00267
00268 QColorGroup g2 = options()->colorGroup(ColorTitleBlend, true);
00269 QColor c2 = g2.background();
00270 g2 = options()->colorGroup(ColorTitleBar, true );
00271 QColor c = g2.background().light(130);
00272
00273 titleBlocks = new KPixmap();
00274 titleBlocks->resize( normalTitleHeight*25/18, normalTitleHeight );
00275 drawBlocks( titleBlocks, *titleBlocks, c, c2 );
00276
00277 g2 = options()->colorGroup(ColorTitleBlend, false);
00278 c2 = g2.background();
00279 g2 = options()->colorGroup(ColorTitleBar, false );
00280 c = g2.background().light(130);
00281
00282 ititleBlocks = new KPixmap();
00283 ititleBlocks->resize( normalTitleHeight*25/18, normalTitleHeight );
00284 drawBlocks( ititleBlocks, *ititleBlocks, c, c2 );
00285
00286
00287 QColorGroup g;
00288 QPainter p;
00289
00290 g = options()->colorGroup( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, true );
00291 c = onAllDesktopsButtonOnLeft ? g.background().light(130) : g.background();
00292 g2 = options()->colorGroup( ColorButtonBg, true );
00293
00294 pinUpPix = new KPixmap();
00295 pinUpPix->resize(16, 16);
00296 p.begin( pinUpPix );
00297 p.fillRect( 0, 0, 16, 16, c);
00298 kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pinup_white_bits,
00299 pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL );
00300 p.end();
00301
00302 pinDownPix = new KPixmap();
00303 pinDownPix->resize(16, 16);
00304 p.begin( pinDownPix );
00305 p.fillRect( 0, 0, 16, 16, c);
00306 kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pindown_white_bits,
00307 pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL );
00308 p.end();
00309
00310
00311
00312 g = options()->colorGroup( onAllDesktopsButtonOnLeft ? ColorTitleBar : ColorTitleBlend, false );
00313 c = onAllDesktopsButtonOnLeft ? g.background().light(130) : g.background();
00314 g2 = options()->colorGroup( ColorButtonBg, false );
00315
00316 ipinUpPix = new KPixmap();
00317 ipinUpPix->resize(16, 16);
00318 p.begin( ipinUpPix );
00319 p.fillRect( 0, 0, 16, 16, c);
00320 kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pinup_white_bits,
00321 pinup_gray_bits, NULL, NULL, pinup_dgray_bits, NULL );
00322 p.end();
00323
00324 ipinDownPix = new KPixmap();
00325 ipinDownPix->resize(16, 16);
00326 p.begin( ipinDownPix );
00327 p.fillRect( 0, 0, 16, 16, c);
00328 kColorBitmaps( &p, g2, 0, 1, 16, 16, true, pindown_white_bits,
00329 pindown_gray_bits, NULL, NULL, pindown_dgray_bits, NULL );
00330 p.end();
00331 }
00332
00333
00334 void QuartzHandler::freePixmaps()
00335 {
00336 delete titleBlocks;
00337 delete ititleBlocks;
00338
00339
00340 delete pinUpPix;
00341 delete ipinUpPix;
00342 delete pinDownPix;
00343 delete ipinDownPix;
00344 }
00345
00346
00347 QValueList< QuartzHandler::BorderSize > QuartzHandler::borderSizes() const
00348 {
00349 return QValueList< BorderSize >() << BorderNormal << BorderLarge <<
00350 BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized;
00351 }
00352
00353
00354 QuartzButton::QuartzButton(QuartzClient *parent, const char *name, bool largeButton,
00355 bool isLeftButton, bool isOnAllDesktopsButton, const unsigned char *bitmap,
00356 const QString& tip, const int realizeBtns)
00357 : QButton(parent->widget(), name),
00358 last_button(NoButton)
00359 {
00360 setTipText(tip);
00361 setCursor(ArrowCursor);
00362
00363
00364 setBackgroundMode( QWidget::NoBackground );
00365 setToggleButton( isOnAllDesktopsButton );
00366
00367 realizeButtons = realizeBtns;
00368
00369 deco = NULL;
00370 large = largeButton;
00371 if ( QApplication::reverseLayout() )
00372 isLeft = !isLeftButton;
00373 else
00374 isLeft = isLeftButton;
00375 isOnAllDesktops = isOnAllDesktopsButton;
00376 client = parent;
00377
00378 if ( large )
00379 setFixedSize(normalTitleHeight-2, normalTitleHeight-2);
00380 else
00381 setFixedSize(toolTitleHeight-2, toolTitleHeight-2);
00382
00383 if(bitmap)
00384 setBitmap(bitmap);
00385 }
00386
00387
00388 QuartzButton::~QuartzButton()
00389 {
00390 delete deco;
00391 }
00392
00393
00394 QSize QuartzButton::sizeHint() const
00395 {
00396 if ( large )
00397 return( QSize(normalTitleHeight-2, normalTitleHeight-2) );
00398 else
00399 return( QSize(toolTitleHeight-2, toolTitleHeight-2) );
00400 }
00401
00402
00403 void QuartzButton::setBitmap(const unsigned char *bitmap)
00404 {
00405 delete deco;
00406
00407 deco = new QBitmap(10, 10, bitmap, true);
00408 deco->setMask( *deco );
00409 repaint( false );
00410 }
00411
00412
00413 void QuartzButton::setTipText(const QString &tip) {
00414 if(KDecoration::options()->showTooltips()) {
00415 QToolTip::remove(this );
00416 QToolTip::add(this, tip );
00417 }
00418 }
00419
00420
00421 void QuartzButton::drawButton(QPainter *p)
00422 {
00423
00424 if (!quartz_initialized)
00425 return;
00426
00427 QColor c;
00428
00429 if (isLeft)
00430 c = KDecoration::options()->color(KDecoration::ColorTitleBar, client->isActive()).light(130);
00431 else
00432 c = KDecoration::options()->color(KDecoration::ColorTitleBlend, client->isActive());
00433
00434
00435 p->fillRect(0, 0, width(), height(), c );
00436
00437
00438
00439 if( deco )
00440 {
00441 int xOff = (width()-10)/2;
00442 int yOff = (height()-10)/2;
00443 p->setPen( Qt::black );
00444 p->drawPixmap(isDown() ? xOff+2: xOff+1, isDown() ? yOff+2 : yOff+1, *deco);
00445 p->setPen( KDecoration::options()->color(KDecoration::ColorButtonBg, client->isActive()).light(150) );
00446 p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, *deco);
00447 } else
00448 {
00449 QPixmap btnpix;
00450 int Offset = 0;
00451
00452 if (isOnAllDesktops)
00453 {
00454 if (isDown())
00455 Offset = 1;
00456
00457
00458 if (client->isActive())
00459 btnpix = isOn() ? *pinDownPix : *pinUpPix;
00460 else
00461 btnpix = isOn() ? *ipinDownPix : *ipinUpPix;
00462
00463 } else
00464 btnpix = client->icon().pixmap( QIconSet::Small, QIconSet::Normal);
00465
00466
00467 if ( height() < 16)
00468 {
00469 QPixmap tmpPix;
00470
00471
00472 tmpPix.convertFromImage( btnpix.convertToImage().smoothScale(height(), height()));
00473 p->drawPixmap( 0, 0, tmpPix );
00474 } else {
00475 Offset += (height() - 16)/2;
00476 p->drawPixmap( Offset, Offset, btnpix );
00477 }
00478 }
00479 }
00480
00481
00482
00483 void QuartzButton::turnOn( bool isOn )
00484 {
00485 if ( isToggleButton() )
00486 setOn( isOn );
00487 }
00488
00489
00490 void QuartzButton::mousePressEvent( QMouseEvent* e )
00491 {
00492 last_button = e->button();
00493 QMouseEvent me( e->type(), e->pos(), e->globalPos(),
00494 (e->button()&realizeButtons)?LeftButton:NoButton, e->state() );
00495 QButton::mousePressEvent( &me );
00496 }
00497
00498
00499 void QuartzButton::mouseReleaseEvent( QMouseEvent* e )
00500 {
00501 last_button = e->button();
00502 QMouseEvent me( e->type(), e->pos(), e->globalPos(),
00503 (e->button()&realizeButtons)?LeftButton:NoButton, e->state() );
00504 QButton::mouseReleaseEvent( &me );
00505 }
00506
00507
00509
00510 QuartzClient::QuartzClient(KDecorationBridge* bridge, KDecorationFactory* factory)
00511 : KDecoration (bridge, factory)
00512 {
00513 }
00514
00515
00516 void QuartzClient::init()
00517 {
00518 connect( this, SIGNAL( keepAboveChanged( bool )), SLOT( keepAboveChange( bool )));
00519 connect( this, SIGNAL( keepBelowChanged( bool )), SLOT( keepBelowChange( bool )));
00520
00521 createMainWidget(WNoAutoErase | WStaticContents);
00522
00523 widget()->installEventFilter( this );
00524
00525
00526 widget()->setBackgroundMode( QWidget::NoBackground );
00527
00528
00529 for(int i=0; i < QuartzClient::BtnCount; i++)
00530 button[i] = NULL;
00531
00532
00533 if ( isTool() ) {
00534 titleHeight = toolTitleHeight;
00535 largeButtons = false;
00536 }
00537 else {
00538 titleHeight = normalTitleHeight;
00539 largeButtons = true;
00540 }
00541
00542 borderSize = borderWidth;
00543
00544
00545 QGridLayout* g = new QGridLayout(widget(), 0, 0, 0);
00546 g->setResizeMode(QLayout::FreeResize);
00547 g->addRowSpacing(0, borderSize-1);
00548 if( isPreview())
00549 g->addWidget(new QLabel( i18n( "<center><b>Quartz</b></center>" ), widget()), 3, 1);
00550 else
00551 g->addItem(new QSpacerItem( 0, 0 ), 3, 1);
00552
00553
00554 g->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed,
00555 QSizePolicy::Expanding ) );
00556 g->setRowStretch(3, 10);
00557 g->addRowSpacing(2, 1);
00558 g->addRowSpacing(4, borderSize);
00559 g->addColSpacing(0, borderSize);
00560 g->addColSpacing(2, borderSize);
00561
00562
00563 hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
00564 hb->setResizeMode( QLayout::FreeResize );
00565 g->addLayout ( hb, 1, 1 );
00566
00567 addClientButtons( options()->titleButtonsLeft() );
00568
00569 titlebar = new QSpacerItem( 10, titleHeight, QSizePolicy::Expanding, QSizePolicy::Minimum );
00570 hb->addItem(titlebar);
00571 hb->addSpacing(2);
00572
00573 addClientButtons( options()->titleButtonsRight(), false );
00574
00575 hb->addSpacing(2);
00576 }
00577
00578 void QuartzClient::reset( unsigned long changed )
00579 {
00580 if (changed & SettingColors || changed & SettingFont)
00581 {
00582
00583 widget()->repaint(false);
00584 }
00585 }
00586
00587 const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
00588 | NET::ToolbarMask | NET::MenuMask | NET::DialogMask | NET::OverrideMask | NET::TopMenuMask
00589 | NET::UtilityMask | NET::SplashMask;
00590
00591 bool QuartzClient::isTool()
00592 {
00593 NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK );
00594 return ((type==NET::Toolbar)||(type==NET::Utility)||(type==NET::Menu));
00595 }
00596
00597
00598 void QuartzClient::addClientButtons( const QString& s, bool isLeft )
00599 {
00600 if (s.length() > 0)
00601 for(unsigned int i = 0; i < s.length(); i++)
00602 {
00603 switch( s[i].latin1() )
00604 {
00605
00606 case 'M':
00607 if (!button[BtnMenu])
00608 {
00609 button[BtnMenu] = new QuartzButton(this, "menu",
00610 largeButtons, isLeft, false, NULL, i18n("Menu"), LeftButton|RightButton);
00611 connect( button[BtnMenu], SIGNAL(pressed()),
00612 this, SLOT(menuButtonPressed()) );
00613 hb->addWidget( button[BtnMenu] );
00614 }
00615 break;
00616
00617
00618 case 'S':
00619 if (!button[BtnOnAllDesktops])
00620 {
00621 button[BtnOnAllDesktops] = new QuartzButton(this, "on_all_desktops",
00622 largeButtons, isLeft, true, NULL, isOnAllDesktops()?i18n("Not on all desktops"):i18n("On all desktops"));
00623 button[BtnOnAllDesktops]->turnOn( isOnAllDesktops() );
00624 connect( button[BtnOnAllDesktops], SIGNAL(clicked()),
00625 this, SLOT(toggleOnAllDesktops()) );
00626 hb->addSpacing(1);
00627 hb->addWidget( button[BtnOnAllDesktops] );
00628 hb->addSpacing(1);
00629 }
00630 break;
00631
00632
00633 case 'H':
00634 if( providesContextHelp() && (!button[BtnHelp]) )
00635 {
00636 button[BtnHelp] = new QuartzButton(this, "help",
00637 largeButtons, isLeft, true, question_bits, i18n("Help"));
00638 connect( button[BtnHelp], SIGNAL( clicked() ),
00639 this, SLOT(showContextHelp()));
00640 hb->addWidget( button[BtnHelp] );
00641 }
00642 break;
00643
00644
00645 case 'I':
00646 if ( (!button[BtnIconify]) && isMinimizable())
00647 {
00648 button[BtnIconify] = new QuartzButton(this, "iconify",
00649 largeButtons, isLeft, true, iconify_bits, i18n("Minimize"));
00650 connect( button[BtnIconify], SIGNAL( clicked()),
00651 this, SLOT(minimize()) );
00652 hb->addWidget( button[BtnIconify] );
00653 }
00654 break;
00655
00656
00657 case 'A':
00658 if ( (!button[BtnMax]) && isMaximizable())
00659 {
00660 button[BtnMax] = new QuartzButton(this, "maximize",
00661 largeButtons, isLeft, true, maximize_bits, i18n("Maximize"), LeftButton|MidButton|RightButton);
00662 connect( button[BtnMax], SIGNAL( clicked()),
00663 this, SLOT(slotMaximize()) );
00664 hb->addWidget( button[BtnMax] );
00665 }
00666 break;
00667
00668
00669 case 'X':
00670 if (!button[BtnClose] && isCloseable())
00671 {
00672 button[BtnClose] = new QuartzButton(this, "close",
00673 largeButtons, isLeft, true, close_bits, i18n("Close"));
00674 connect( button[BtnClose], SIGNAL( clicked()),
00675 this, SLOT(closeWindow()) );
00676 hb->addWidget( button[BtnClose] );
00677 }
00678 break;
00679
00680
00681 case 'F':
00682 if ( (!button[BtnAbove]))
00683 {
00684 button[BtnAbove] = new QuartzButton(this, "above",
00685 largeButtons, isLeft, true,
00686 keepAbove() ? above_on_bits : above_off_bits,
00687 i18n("Keep Above Others"));
00688 connect( button[BtnAbove], SIGNAL( clicked()),
00689 this, SLOT(slotAbove()) );
00690 hb->addWidget( button[BtnAbove] );
00691 }
00692 break;
00693
00694
00695 case 'B':
00696 if ( (!button[BtnBelow]))
00697 {
00698 button[BtnBelow] = new QuartzButton(this, "below",
00699 largeButtons, isLeft, true,
00700 keepBelow() ? below_on_bits : below_off_bits,
00701 i18n("Keep Below Others"));
00702 connect( button[BtnBelow], SIGNAL( clicked()),
00703 this, SLOT(slotBelow()) );
00704 hb->addWidget( button[BtnBelow] );
00705 }
00706 break;
00707
00708
00709 case 'L':
00710 if ( (!button[BtnShade]) && isShadeable())
00711 {
00712 button[BtnShade] = new QuartzButton(this, "shade",
00713 largeButtons, isLeft, true,
00714 isSetShade() ? shade_on_bits : shade_off_bits,
00715 isSetShade() ? i18n( "Unshade" ) : i18n("Shade"));
00716 connect( button[BtnShade], SIGNAL( clicked()),
00717 this, SLOT(slotShade()) );
00718 hb->addWidget( button[BtnShade] );
00719 }
00720 break;
00721 }
00722 }
00723 }
00724
00725
00726 void QuartzClient::iconChange()
00727 {
00728 if (button[BtnMenu] && button[BtnMenu]->isVisible())
00729 button[BtnMenu]->repaint(false);
00730 }
00731
00732
00733 void QuartzClient::desktopChange()
00734 {
00735 if (button[BtnOnAllDesktops])
00736 {
00737 button[BtnOnAllDesktops]->turnOn(isOnAllDesktops());
00738 button[BtnOnAllDesktops]->repaint(false);
00739 button[BtnOnAllDesktops]->setTipText(isOnAllDesktops() ? i18n("Not on all desktops") : i18n("On all desktops"));
00740 }
00741 }
00742
00743
00744 void QuartzClient::keepAboveChange( bool above )
00745 {
00746 if (button[BtnAbove]) {
00747 button[BtnAbove]->setBitmap( above ? above_on_bits : above_off_bits );
00748 button[BtnAbove]->repaint(false);
00749 }
00750 }
00751
00752
00753 void QuartzClient::keepBelowChange( bool below )
00754 {
00755 if (button[BtnBelow]) {
00756 button[BtnBelow]->setBitmap( below ? below_on_bits : below_off_bits );
00757 button[BtnBelow]->repaint(false);
00758 }
00759 }
00760
00761 void QuartzClient::shadeChange()
00762 {
00763 if (button[BtnShade]) {
00764 bool on = isSetShade();
00765 button[BtnShade]->turnOn(on);
00766 button[BtnShade]->setBitmap(on ? shade_on_bits : shade_off_bits );
00767 button[BtnShade]->repaint(false);
00768 QToolTip::remove( button[BtnShade] );
00769 QToolTip::add( button[BtnShade], on ? i18n("Unshade") : i18n("Shade"));
00770 }
00771 }
00772
00773
00774 void QuartzClient::slotMaximize()
00775 {
00776 if (button[BtnMax])
00777 {
00778 maximize(button[BtnMax]->last_button);
00779 }
00780 }
00781
00782
00783 void QuartzClient::slotAbove()
00784 {
00785 setKeepAbove( !keepAbove());
00786 button[BtnAbove]->turnOn(keepAbove());
00787 button[BtnAbove]->repaint(true);
00788 }
00789
00790
00791 void QuartzClient::slotBelow()
00792 {
00793 setKeepBelow( !keepBelow());
00794 button[BtnBelow]->turnOn(keepBelow());
00795 button[BtnBelow]->repaint(true);
00796 }
00797
00798
00799 void QuartzClient::slotShade()
00800 {
00801 setShade( !isSetShade());
00802 }
00803
00804
00805 void QuartzClient::resizeEvent( QResizeEvent* e)
00806 {
00807 calcHiddenButtons();
00808
00809 if (widget()->isVisibleToTLW())
00810 {
00811 widget()->update(widget()->rect());
00812 int dx = 0;
00813 int dy = 0;
00814
00815 if ( e->oldSize().width() != width() )
00816 dx = 32 + QABS( e->oldSize().width() - width() );
00817
00818 if ( e->oldSize().height() != height() )
00819 dy = 8 + QABS( e->oldSize().height() - height() );
00820
00821 if ( dy )
00822 widget()->update( 0, height() - dy + 1, width(), dy );
00823
00824 if ( dx )
00825 {
00826 widget()->update( width() - dx + 1, 0, dx, height() );
00827 widget()->update( QRect( QPoint(4,4), titlebar->geometry().bottomLeft() - QPoint(1,0) ) );
00828 widget()->update( QRect( titlebar->geometry().topRight(), QPoint( width() - 4, titlebar->geometry().bottom() ) ) );
00829
00830 widget()->repaint(titlebar->geometry(), false);
00831 }
00832 }
00833 }
00834
00835
00836 void QuartzClient::captionChange()
00837 {
00838 widget()->repaint( titlebar->geometry(), false );
00839 }
00840
00841
00842
00843 void QuartzClient::paintEvent( QPaintEvent* )
00844 {
00845
00846 if (!quartz_initialized)
00847 return;
00848
00849 const bool maxFull = (maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows();
00850
00851 QColorGroup g;
00852 QPainter p(widget());
00853
00854
00855 QRect r(widget()->rect());
00856 int x = r.x();
00857 int y = r.y();
00858 int x2 = r.width() - 1;
00859 int y2 = r.height() - 1;
00860 int w = r.width();
00861 int h = r.height();
00862
00863
00864
00865 if( coloredFrame )
00866 g = options()->colorGroup(ColorTitleBar, isActive());
00867 else
00868 g = options()->colorGroup(ColorFrame, isActive());
00869
00870
00871 p.setPen( g.light().light(120) );
00872 p.drawLine( x, y, x2-1, y );
00873 p.drawLine( x, y+1, x, y2-1 );
00874 p.setPen( g.dark().light(120) );
00875 p.drawLine( x2, y, x2, y2 );
00876 p.drawLine( x, y2, x2, y2 );
00877
00878
00879 QColor frameColor;
00880 if ( coloredFrame)
00881 frameColor = g.background().light(130);
00882 else
00883 frameColor = g.background();
00884 if (borderSize > 2) {
00885 p.fillRect(x+1, y+1, w-2, borderSize-2, frameColor);
00886 if (!maxFull) {
00887 p.fillRect(x+1, y+h-(borderSize-1), w-2, borderSize-2, frameColor);
00888 p.fillRect(x+1, y+borderSize-1, borderSize-1, h-2*(borderSize-1), frameColor);
00889 p.fillRect(x+w-(borderSize), y+borderSize-1, borderSize-1, h-2*(borderSize-1), frameColor);
00890 }
00891 }
00892
00893
00894 p.setPen( g.background() );
00895 if (maxFull) {
00896 p.drawLine(x+1, y+titleHeight+(borderSize-1), w-2, y+titleHeight+(borderSize-1));
00897 } else {
00898 p.drawRect( x+(borderSize-1), y+titleHeight+(borderSize-1), w-2*(borderSize-1), h-titleHeight-2*(borderSize-1) );
00899 }
00900
00901
00902 p.drawLine( x+borderSize, y2-borderSize, x2-borderSize, y2-borderSize);
00903
00904
00905 p.setPen( g.light().light(160) );
00906 p.drawPoint( x, y );
00907 p.setPen( g.light().light(140) );
00908 p.drawPoint( x+1, y );
00909 p.drawPoint( x, y+1 );
00910
00911
00912
00913 r = titlebar->geometry();
00914
00915
00916 QColor c1 = options()->color(ColorTitleBar, isActive() ).light(130);
00917 QColor c2 = options()->color(ColorTitleBlend, isActive() );
00918
00919
00920 KPixmap* titleBuffer = new KPixmap;
00921 titleBuffer->resize( maxFull?w-2:(w-2*(borderSize-1)), titleHeight );
00922
00923 QPainter p2( titleBuffer, this );
00924
00925
00926 int rightoffset = r.x()+r.width()-titleBlocks->width()-borderSize;
00927
00928 p2.fillRect( 0, 0, w, r.height(), c1 );
00929 p2.fillRect( rightoffset, 0, maxFull?w-rightoffset:w-rightoffset-2*(borderSize-1), r.height(), c2 );
00930
00931
00932 if ( isActive() )
00933 p2.drawPixmap( rightoffset, 0, *titleBlocks );
00934 else
00935 p2.drawPixmap( rightoffset, 0, *ititleBlocks );
00936
00937
00938
00939 QFont fnt;
00940 if ( largeButtons ) {
00941 fnt = options()->font(true, false);
00942 } else {
00943 fnt = options()->font(true, true);
00944 fnt.setWeight( QFont::Normal );
00945 }
00946 p2.setFont( fnt );
00947
00948 p2.setPen( options()->color(ColorFont, isActive() ));
00949 p2.drawText(r.x()+4-borderSize, 0, r.width()-3, r.height(),
00950 AlignLeft | AlignVCenter, caption() );
00951 p2.end();
00952
00953 p.drawPixmap( maxFull?1:borderSize-1, borderSize-1, *titleBuffer );
00954
00955 delete titleBuffer;
00956 }
00957
00958
00959 void QuartzClient::showEvent(QShowEvent *)
00960 {
00961 calcHiddenButtons();
00962 widget()->show();
00963 }
00964
00965
00966 void QuartzClient::mouseDoubleClickEvent( QMouseEvent * e )
00967 {
00968 if (titlebar->geometry().contains( e->pos() ) )
00969 titlebarDblClickOperation();
00970 }
00971
00972
00973 void QuartzClient::maximizeChange()
00974 {
00975 if (button[BtnMax]) {
00976 button[BtnMax]->setBitmap((maximizeMode()==MaximizeFull) ? minmax_bits : maximize_bits);
00977 button[BtnMax]->setTipText((maximizeMode()==MaximizeFull) ? i18n("Restore") : i18n("Maximize"));
00978 }
00979 }
00980
00981
00982 void QuartzClient::activeChange()
00983 {
00984 for(int i=QuartzClient::BtnHelp; i < QuartzClient::BtnCount; i++)
00985 if(button[i])
00986 button[i]->repaint(false);
00987
00988 widget()->repaint(false);
00989 }
00990
00991
00992 QuartzClient::Position QuartzClient::mousePosition(const QPoint &point) const
00993 {
00994 const int corner = 3*borderSize/2 + 18;
00995 Position pos = PositionCenter;
00996
00997 QRect r(widget()->rect());
00998
00999 if(point.y() < (borderSize-1)) {
01000 if(point.x() < corner) return PositionTopLeft;
01001 else if(point.x() > (r.right()-corner)) return PositionTopRight;
01002 else return PositionTop;
01003 } else if(point.y() > (r.bottom()-borderSize)) {
01004 if(point.x() < corner) return PositionBottomLeft;
01005 else if(point.x() > (r.right()-corner)) return PositionBottomRight;
01006 else return PositionBottom;
01007 } else if(point.x() < borderSize) {
01008 if(point.y() < corner) return PositionTopLeft;
01009 else if(point.y() > (r.bottom()-corner)) return PositionBottomLeft;
01010 else return PositionLeft;
01011 } else if(point.x() > (r.right()-borderSize)) {
01012 if(point.y() < corner) return PositionTopRight;
01013 else if(point.y() > (r.bottom()-corner)) return PositionBottomRight;
01014 else return PositionRight;
01015 }
01016
01017 return pos;
01018 }
01019
01020
01021 void QuartzClient::borders(int& left, int& right, int& top, int& bottom) const
01022 {
01023 left = borderSize;
01024 right = borderSize;
01025 top = 1 + titleHeight + (borderSize-1);
01026 bottom = borderSize;
01027
01028 if ((maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows()) {
01029 left = right = bottom = 0;
01030 top = 1 + titleHeight + (borderSize-1);
01031 }
01032 }
01033
01034
01035 void QuartzClient::resize( const QSize& s )
01036 {
01037 widget()->resize( s );
01038 }
01039
01040
01041 QSize QuartzClient::minimumSize() const
01042 {
01043 return widget()->minimumSize();
01044 }
01045
01046
01047
01048 void QuartzClient::calcHiddenButtons()
01049 {
01050
01051
01052 QuartzButton* btnArray[] = { button[BtnShade], button[BtnBelow], button[BtnAbove],
01053 button[BtnOnAllDesktops], button[BtnHelp], button[BtnMax],
01054 button[BtnMenu], button[BtnIconify], button[BtnClose] };
01055 const int buttons_cnt = sizeof( btnArray ) / sizeof( btnArray[ 0 ] );
01056
01057 int minwidth = largeButtons ? 180 : 140;
01058 int btn_width = largeButtons ? 16 : 10;
01059 int current_width = width();
01060 int count = 0;
01061 int i;
01062
01063
01064 while (current_width < minwidth)
01065 {
01066 current_width += btn_width;
01067 count++;
01068 }
01069
01070
01071 if (count > buttons_cnt) count = buttons_cnt;
01072
01073
01074 for(i = 0; i < count; i++)
01075 {
01076 if (btnArray[i] && btnArray[i]->isVisible() )
01077 btnArray[i]->hide();
01078 }
01079
01080
01081 for(i = count; i < buttons_cnt; i++)
01082 {
01083 if (btnArray[i] && (!btnArray[i]->isVisible()) )
01084 btnArray[i]->show();
01085 }
01086 }
01087
01088
01089
01090 void QuartzClient::menuButtonPressed()
01091 {
01092 QRect menuRect = button[BtnMenu]->rect();
01093 QPoint menuTop ( menuRect.topLeft() );
01094 QPoint menuBottom ( menuRect.bottomRight() );
01095 menuTop += QPoint(-1, 2);
01096 menuBottom += QPoint(1, 2);
01097 menuTop = button[BtnMenu]->mapToGlobal( menuTop );
01098 menuBottom = button[BtnMenu]->mapToGlobal( menuBottom );
01099 KDecorationFactory* f = factory();
01100 showWindowMenu(QRect(menuTop, menuBottom));
01101 if( !f->exists( this ))
01102 return;
01103 button[BtnMenu]->setDown(false);
01104 }
01105
01106 bool QuartzClient::eventFilter( QObject* o, QEvent* e )
01107 {
01108 if( o != widget())
01109 return false;
01110 switch( e->type())
01111 {
01112 case QEvent::Resize:
01113 resizeEvent(static_cast< QResizeEvent* >( e ) );
01114 return true;
01115 case QEvent::Paint:
01116 paintEvent(static_cast< QPaintEvent* >( e ) );
01117 return true;
01118 case QEvent::MouseButtonDblClick:
01119 mouseDoubleClickEvent(static_cast< QMouseEvent* >( e ) );
01120 return true;
01121 case QEvent::MouseButtonPress:
01122 processMousePressEvent(static_cast< QMouseEvent* >( e ) );
01123 return true;
01124 default:
01125 break;
01126 }
01127 return false;
01128 }
01129
01130 }
01131
01132
01134 extern "C"
01135 {
01136 KDE_EXPORT KDecorationFactory *create_factory()
01137 {
01138 Quartz::clientHandler = new Quartz::QuartzHandler();
01139 return Quartz::clientHandler;
01140 }
01141 }
01142
01143
01144
01145 #include "quartz.moc"
01146