00001
00002
00003
00004
00005
00006
00007
00008 #include <kconfig.h>
00009 #include "laptopclient.h"
00010 #include <qlayout.h>
00011 #include <qdrawutil.h>
00012 #include <kpixmapeffect.h>
00013 #include <kdrawutil.h>
00014 #include <kglobal.h>
00015 #include <kapplication.h>
00016 #include <klocale.h>
00017 #include <qbitmap.h>
00018 #include <qtooltip.h>
00019 #include <qlabel.h>
00020
00021
00022 const char default_left[] = "X";
00023 const char default_right[] = "HSIA";
00024
00025 namespace Laptop {
00026
00027 static const unsigned char iconify_bits[] = {
00028 0xff, 0xff, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18};
00029
00030 static const unsigned char close_bits[] = {
00031 0x42, 0xe7, 0x7e, 0x3c, 0x3c, 0x7e, 0xe7, 0x42};
00032
00033 static const unsigned char maximize_bits[] = {
00034 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0xff, 0xff };
00035
00036 static const unsigned char r_minmax_bits[] = {
00037 0x0c, 0x18, 0x33, 0x67, 0xcf, 0x9f, 0x3f, 0x3f};
00038
00039 static const unsigned char l_minmax_bits[] = {
00040 0x30, 0x18, 0xcc, 0xe6, 0xf3, 0xf9, 0xfc, 0xfc};
00041
00042 static const unsigned char question_bits[] = {
00043 0x3c, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18};
00044
00045 static const unsigned char unsticky_bits[] = {
00046 0x3c, 0x42, 0x99, 0xbd, 0xbd, 0x99, 0x42, 0x3c};
00047
00048 static const unsigned char sticky_bits[] = {
00049 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
00050
00051 static QPixmap *titlePix;
00052 static KPixmap *aUpperGradient;
00053 static KPixmap *iUpperGradient;
00054
00055 static KPixmap *btnPix1;
00056 static KPixmap *iBtnPix1;
00057 static KPixmap *btnDownPix1;
00058 static KPixmap *iBtnDownPix1;
00059 static KPixmap *btnPix2;
00060 static KPixmap *btnDownPix2;
00061 static KPixmap *iBtnPix2;
00062 static KPixmap *iBtnDownPix2;
00063 static QColor btnForeground;
00064
00065 static int titleHeight = 14;
00066 static int btnWidth1 = 17;
00067 static int btnWidth2 = 27;
00068
00069 static int handleSize = 8;
00070
00071 static bool pixmaps_created = false;
00072
00073
00074
00075 extern "C" KDE_EXPORT KDecorationFactory* create_factory()
00076 {
00077 return new Laptop::LaptopClientFactory();
00078 }
00079
00080
00081
00082 static inline const KDecorationOptions* options()
00083 {
00084 return KDecoration::options();
00085 }
00086
00087 static void drawButtonFrame(KPixmap *pix, const QColorGroup &g, bool sunken)
00088 {
00089 QPainter p;
00090 int w = pix->width();
00091 int h = pix->height();
00092 int x2 = w-1;
00093 int y2 = h-1;
00094 p.begin(pix);
00095
00096 if(sunken){
00097 qDrawShadePanel(&p, 0, 0, w, h, g, true, 2);
00098 }
00099 else{
00100 p.setPen(g.dark());
00101 p.drawRect(0, 0, w-1, h-1);
00102 p.setPen(g.light());
00103 p.drawLine(x2, 0, x2, y2);
00104 p.drawLine(0, y2, x2, y2);
00105 p.drawLine(1, 1, x2-2, 1);
00106 p.drawLine(1, 1, 1, y2-2);
00107 p.end();
00108 }
00109 }
00110
00111 static void create_pixmaps()
00112 {
00113 if(pixmaps_created)
00114 return;
00115 pixmaps_created = true;
00116
00117 titleHeight = QFontMetrics(options()->font(true)).height() + 2;
00118 if (titleHeight < handleSize) titleHeight = handleSize;
00119 titleHeight &= ~1;
00120 if (titleHeight < 14) titleHeight = 14;
00121
00122 btnWidth1 = titleHeight + 3;
00123 btnWidth2 = 3*titleHeight/2 + 6;
00124
00125
00126 QPainter p;
00127 QPainter maskPainter;
00128 int i, x, y;
00129 titlePix = new QPixmap(33, 12);
00130 QBitmap mask(33, 12);
00131 mask.fill(Qt::color0);
00132
00133 p.begin(titlePix);
00134 maskPainter.begin(&mask);
00135 maskPainter.setPen(Qt::color1);
00136 for(i=0, y=2; i < 3; ++i, y+=4){
00137 for(x=1; x <= 33; x+=3){
00138 p.setPen(options()->color(KDecoration::ColorTitleBar, true).light(150));
00139 p.drawPoint(x, y);
00140 maskPainter.drawPoint(x, y);
00141 p.setPen(options()->color(KDecoration::ColorTitleBar, true).dark(150));
00142 p.drawPoint(x+1, y+1);
00143 maskPainter.drawPoint(x+1, y+1);
00144 }
00145 }
00146 p.end();
00147 maskPainter.end();
00148 titlePix->setMask(mask);
00149
00150 if(QPixmap::defaultDepth() > 8){
00151 aUpperGradient = new KPixmap;
00152 aUpperGradient->resize(32, titleHeight+2);
00153 iUpperGradient = new KPixmap;
00154 iUpperGradient->resize(32, titleHeight+2);
00155 QColor bgColor = options()->color(KDecoration::ColorTitleBar, true);
00156 KPixmapEffect::gradient(*aUpperGradient,
00157 bgColor.light(120),
00158 bgColor.dark(120),
00159 KPixmapEffect::VerticalGradient);
00160 bgColor = options()->color(KDecoration::ColorTitleBar, false);
00161 KPixmapEffect::gradient(*iUpperGradient,
00162 bgColor.light(120),
00163 bgColor.dark(120),
00164 KPixmapEffect::VerticalGradient);
00165 }
00166
00167 QColorGroup g = options()->colorGroup(KDecoration::ColorButtonBg, true);
00168 QColor c = g.background();
00169 btnPix1 = new KPixmap;
00170 btnPix1->resize(btnWidth1, titleHeight);
00171 btnDownPix1 = new KPixmap;
00172 btnDownPix1->resize(btnWidth1, titleHeight);
00173 btnPix2 = new KPixmap;
00174 btnPix2->resize(btnWidth2, titleHeight);
00175 btnDownPix2 = new KPixmap;
00176 btnDownPix2->resize(btnWidth2, titleHeight);
00177 iBtnPix1 = new KPixmap;
00178 iBtnPix1->resize(btnWidth1, titleHeight);
00179 iBtnDownPix1 = new KPixmap;
00180 iBtnDownPix1->resize(btnWidth1, titleHeight);
00181 iBtnPix2 = new KPixmap;
00182 iBtnPix2->resize(btnWidth2, titleHeight);
00183 iBtnDownPix2 = new KPixmap;
00184 iBtnDownPix2->resize(btnWidth2, titleHeight);
00185 if(QPixmap::defaultDepth() > 8){
00186 KPixmapEffect::gradient(*btnPix1, c.light(120), c.dark(130),
00187 KPixmapEffect::DiagonalGradient);
00188 KPixmapEffect::gradient(*btnDownPix1, c.dark(130), c.light(120),
00189 KPixmapEffect::DiagonalGradient);
00190 KPixmapEffect::gradient(*btnPix2, c.light(120), c.dark(130),
00191 KPixmapEffect::DiagonalGradient);
00192 KPixmapEffect::gradient(*btnDownPix2, c.dark(130), c.light(120),
00193 KPixmapEffect::DiagonalGradient);
00194 g = options()->colorGroup(KDecoration::ColorButtonBg, false);
00195 c = g.background();
00196 KPixmapEffect::gradient(*iBtnPix1, c.light(120), c.dark(130),
00197 KPixmapEffect::DiagonalGradient);
00198 KPixmapEffect::gradient(*iBtnDownPix1, c.dark(130), c.light(120),
00199 KPixmapEffect::DiagonalGradient);
00200 KPixmapEffect::gradient(*iBtnPix2, c.light(120), c.dark(130),
00201 KPixmapEffect::DiagonalGradient);
00202 KPixmapEffect::gradient(*iBtnDownPix2, c.dark(130), c.light(120),
00203 KPixmapEffect::DiagonalGradient);
00204 }
00205 else{
00206 btnPix1->fill(c.rgb());
00207 btnDownPix1->fill(c.rgb());
00208 btnPix2->fill(c.rgb());
00209 btnDownPix2->fill(c.rgb());
00210 g = options()->colorGroup(KDecoration::ColorButtonBg, false);
00211 c = g.background();
00212 iBtnPix1->fill(c.rgb());
00213 iBtnDownPix1->fill(c.rgb());
00214 iBtnPix2->fill(c.rgb());
00215 iBtnDownPix2->fill(c.rgb());
00216 }
00217 g = options()->colorGroup(KDecoration::ColorButtonBg, true);
00218 c = g.background();
00219 drawButtonFrame(btnPix1, g, false);
00220 drawButtonFrame(btnDownPix1, g, true);
00221 drawButtonFrame(btnPix2, g, false);
00222 drawButtonFrame(btnDownPix2, g, true);
00223 g = options()->colorGroup(KDecoration::ColorButtonBg, false);
00224 c = g.background();
00225 drawButtonFrame(iBtnPix1, g, false);
00226 drawButtonFrame(iBtnDownPix1, g, true);
00227 drawButtonFrame(iBtnPix2, g, false);
00228 drawButtonFrame(iBtnDownPix2, g, true);
00229
00230 if(qGray(options()->color(KDecoration::ColorButtonBg, true).rgb()) > 128)
00231 btnForeground = Qt::black;
00232 else
00233 btnForeground = Qt::white;
00234 }
00235
00236 static void delete_pixmaps()
00237 {
00238 delete titlePix;
00239 if(aUpperGradient){
00240 delete aUpperGradient;
00241 delete iUpperGradient;
00242 delete btnPix1;
00243 delete btnDownPix1;
00244 delete iBtnPix1;
00245 delete iBtnDownPix1;
00246 delete btnPix2;
00247 delete btnDownPix2;
00248 delete iBtnPix2;
00249 delete iBtnDownPix2;
00250 }
00251 pixmaps_created = false;
00252 }
00253
00254
00255
00256 LaptopButton::LaptopButton(int w, int h, LaptopClient *parent,
00257 const char *name, const unsigned char *bitmap,
00258 const QString& tip, const int realizeBtns)
00259 : QButton(parent->widget(), name), client(parent)
00260 {
00261 realizeButtons = realizeBtns;
00262
00263 setCursor( arrowCursor );
00264 defaultSize = QSize(w, h);
00265 setFixedHeight(h);
00266 resize(defaultSize);
00267 if(bitmap)
00268 setBitmap(bitmap);
00269
00270
00271
00272 QToolTip::add(this, tip);
00273 }
00274
00275 QSize LaptopButton::sizeHint() const
00276 {
00277 return(defaultSize);
00278 }
00279
00280 void LaptopButton::reset()
00281 {
00282 repaint(false);
00283 }
00284
00285 void LaptopButton::setBitmap(const unsigned char *bitmap)
00286 {
00287 deco = QBitmap(8, 8, bitmap, true);
00288 deco.setMask(deco);
00289 repaint();
00290 }
00291
00292 void LaptopButton::drawButton(QPainter *p)
00293 {
00294 bool smallBtn = width() == btnWidth1;
00295 if(btnPix1){
00296 if(client->isActive()){
00297 if(isDown())
00298 p->drawPixmap(0, 0, smallBtn ? *btnDownPix1 : *btnDownPix2);
00299 else
00300 p->drawPixmap(0, 0, smallBtn ? *btnPix1 : *btnPix2);
00301 }
00302 else{
00303 if(isDown())
00304 p->drawPixmap(0, 0, smallBtn ? *iBtnDownPix1 : *iBtnDownPix2);
00305 else
00306 p->drawPixmap(0, 0, smallBtn ? *iBtnPix1 : *iBtnPix2);
00307 }
00308 }
00309 else{
00310 QColorGroup g = options()->colorGroup(KDecoration::ColorButtonBg,
00311 client->isActive());
00312 int w = width();
00313 int h = height();
00314 p->fillRect(1, 1, w-2, h-2, isDown() ? g.mid() : g.button());
00315 p->setPen(isDown() ? g.dark() : g.light());
00316 p->drawLine(0, 0, w-1, 0);
00317 p->drawLine(0, 0, 0, w-1);
00318 p->setPen(isDown() ? g.light() : g.dark());
00319 p->drawLine(w-1, 0, w-1, h-1);
00320 p->drawLine(0, h-1, w-1, h-1);
00321 }
00322
00323 p->setPen(btnForeground);
00324 int xOff = (width()-8)/2;
00325 int yOff = (height()-8)/2;
00326 p->drawPixmap(isDown() ? xOff+1: xOff, isDown() ? yOff+1 : yOff, deco);
00327 }
00328
00329
00330
00331 void LaptopClient::reset(unsigned long)
00332 {
00333 for (int i=0; i<BtnTypeCount; i++) {
00334 if (button[i])
00335 button[i]->reset();
00336 }
00337 widget()->repaint();
00338 }
00339
00340 LaptopClient::LaptopClient(KDecorationBridge *b, KDecorationFactory *f)
00341 : KDecoration(b, f)
00342 {
00343 }
00344
00345 LaptopClient::~LaptopClient()
00346 {
00347 for (int n=0; n<BtnTypeCount; n++) {
00348 if (button[n]) delete button[n];
00349 }
00350 }
00351
00352 void LaptopClient::init()
00353 {
00354 createMainWidget(WResizeNoErase | WStaticContents);
00355 widget()->installEventFilter(this);
00356
00357 lastButtonWidth = 0;
00358 lastBufferWidth = 0;
00359
00360
00361
00362
00363 g = new QGridLayout(widget(), 0, 0, 0);
00364 g->setResizeMode(QLayout::FreeResize);
00365 g->addRowSpacing(0, 3);
00366 g->addRowSpacing(2, 1);
00367 if (isPreview())
00368 g->addWidget(new QLabel(i18n("<center><b>Laptop preview</b></center>"),
00369 widget()), 3, 1);
00370 else
00371 g->addItem( new QSpacerItem( 0, 0 ), 3, 1);
00372
00373 g->setRowStretch(3, 10);
00374 spacer = new QSpacerItem(10, mustDrawHandle() ? handleSize : 4,
00375 QSizePolicy::Expanding, QSizePolicy::Minimum);
00376 g->addItem(spacer, 4, 1);
00377 g->addColSpacing(0, 4);
00378 g->addColSpacing(2, 4);
00379
00380 int th = titleHeight;
00381 if ( isTool() )
00382 th -= 2;
00383
00384 hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
00385 hb->setResizeMode(QLayout::FreeResize);
00386 g->addLayout( hb, 1, 1 );
00387
00388 titlebar = new QSpacerItem(10, th, QSizePolicy::Expanding,
00389 QSizePolicy::Minimum);
00390
00391
00392 for (int n=0; n<BtnTypeCount; n++) button[n] = 0;
00393 addButtons(hb, th, options()->customButtonPositions() ? options()->titleButtonsLeft() : QString(default_left));
00394 hb->addSpacing(1);
00395 hb->addItem(titlebar);
00396 hb->addSpacing(1);
00397 addButtons(hb, th, options()->customButtonPositions() ? options()->titleButtonsRight() : QString(default_right));
00398
00399 hiddenItems = false;
00400 bufferDirty = true;
00401
00402 }
00403
00404 void LaptopClient::addButtons(QBoxLayout *hb, int th, const QString& s)
00405 {
00406 const unsigned char *bitmap;
00407 bool m = maximizeMode() == MaximizeFull;
00408 int l_max = options()->titleButtonsLeft().find('A');
00409 QString tip;
00410
00411 if (s.length() > 0) {
00412 for (unsigned n=0; n < s.length(); n++) {
00413 switch (s[n]) {
00414 case 'S':
00415 if ((!button[BtnSticky]) && (!isTransient() || !isTool())) {
00416 button[BtnSticky] = new LaptopButton(btnWidth1, th, this, "sticky",
00417 NULL, isOnAllDesktops()?i18n("Not on all desktops"):i18n("On all desktops") );
00418 if(isOnAllDesktops())
00419 button[BtnSticky]->setBitmap(unsticky_bits);
00420 else
00421 button[BtnSticky]->setBitmap(sticky_bits);
00422 connect( button[BtnSticky], SIGNAL( clicked() ), this, SLOT( toggleOnAllDesktops() ) );
00423 hb->addWidget( button[BtnSticky]);
00424 }
00425 break;
00426
00427 case 'H':
00428 if ((!button[BtnHelp]) && providesContextHelp()) {
00429 button[BtnHelp] = new LaptopButton(btnWidth1, th, this, "help",
00430 question_bits, i18n("Help"));
00431 connect(button[BtnHelp], SIGNAL( clicked() ), this, SLOT( showContextHelp() ) );
00432 hb->addWidget(button[BtnHelp]);
00433 }
00434 break;
00435
00436 case 'I':
00437 if ((!button[BtnIconify]) && isMinimizable()) {
00438 button[BtnIconify] = new LaptopButton(btnWidth2, th, this, "iconify",
00439 iconify_bits, i18n("Minimize"));
00440 connect( button[BtnIconify], SIGNAL( clicked() ), this, SLOT( minimize() ) );
00441 hb->addWidget( button[BtnIconify]);
00442 }
00443 break;
00444
00445 case 'A':
00446 if ((!button[BtnMax]) && isMaximizable()) {
00447 if (!m) {
00448 bitmap = maximize_bits;
00449 tip = i18n("Maximize");
00450 } else {
00451 if (options()->customButtonPositions() && (l_max>-1))
00452 bitmap = l_minmax_bits;
00453 else
00454 bitmap = r_minmax_bits;
00455 tip = i18n("Restore");
00456 }
00457 button[BtnMax] = new LaptopButton(btnWidth2, th, this, "maximize",
00458 bitmap, tip, LeftButton|MidButton|RightButton);
00459 connect( button[BtnMax], SIGNAL( clicked() ), this, SLOT( slotMaximize() ) );
00460 hb->addWidget( button[BtnMax]);
00461 }
00462 break;
00463
00464 case 'X':
00465 if ((!button[BtnClose]) && isCloseable()) {
00466 button[BtnClose] = new LaptopButton(btnWidth2, th, this, "close",
00467 close_bits, i18n("Close"));
00468 connect( button[BtnClose], SIGNAL( clicked() ), this, SLOT( closeWindow() ) );
00469 hb->addWidget( button[BtnClose]);
00470 }
00471 break;
00472 }
00473 }
00474 }
00475 }
00476
00477 void LaptopClient::slotMaximize()
00478 {
00479 maximize(button[BtnMax]->last_button);
00480 }
00481
00482 void LaptopClient::resizeEvent(QResizeEvent* e)
00483 {
00484 doShape();
00485 calcHiddenButtons();
00486 if ( widget()->isVisibleToTLW() ) {
00487 int dx = 0;
00488 int dy = 0;
00489 if ( e->oldSize().width() != width() )
00490 dx = 32 + QABS( e->oldSize().width() - width() );
00491 if ( e->oldSize().height() != height() )
00492 dy = mustDrawHandle() ? handleSize : 4 +
00493 QABS( e->oldSize().height() - height() );
00494 if ( dy )
00495 widget()->update( 0, height() - dy + 1, width(), dy );
00496 if ( dx ) {
00497 widget()->update( width() - dx + 1, 0, dx, height() );
00498 widget()->update( QRect( QPoint(4,4),
00499 titlebar->geometry().bottomLeft() - QPoint(1,0) ) );
00500 widget()->update( QRect( titlebar->geometry().topRight(),
00501 QPoint( width() - 4, titlebar->geometry().bottom() ) ) );
00502 widget()->update(titlebar->geometry());
00503 }
00504 }
00505 }
00506
00507 void LaptopClient::captionChange()
00508 {
00509 bufferDirty = true;
00510 widget()->repaint(titlebar->geometry(), false);
00511 }
00512
00513 void LaptopClient::paintEvent( QPaintEvent* )
00514 {
00515 QPainter p(widget());
00516 QColorGroup g = options()->colorGroup(KDecoration::ColorFrame, isActive());
00517
00518 QRect r(widget()->rect());
00519 p.setPen(Qt::black);
00520 p.drawRect(r);
00521
00522 p.setPen(g.light());
00523 p.drawLine(r.x()+1, r.y()+1, r.right()-1, r.y()+1);
00524 p.drawLine(r.x()+1, r.y()+1, r.x()+1, r.bottom()-1);
00525 p.setPen(g.dark());
00526 p.drawLine(r.right()-1, r.y()+1, r.right()-1, r.bottom()-1);
00527 p.drawLine(r.x()+1, r.bottom()-1, r.right()-1, r.bottom()-1);
00528
00529 int th = titleHeight;
00530 int bb = handleSize + 2;
00531 int bs = handleSize - 2;
00532 if (!mustDrawHandle()) {
00533 bb = 6;
00534 bs = 0;
00535 }
00536 if ( isTool() )
00537 th -= 2;
00538
00539
00540 p.drawRect(r.x() + 3, r.y() + th + 3, r.width() - 6, r.height() - th - bb);
00541
00542
00543 if (mustDrawHandle()) {
00544 if (r.width() > 3*handleSize + 20) {
00545 int range = 8 + 3*handleSize/2;
00546 qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs, range,
00547 handleSize - 2, g, false, 1, &g.brush(QColorGroup::Mid));
00548 qDrawShadePanel(&p, r.x() + range + 1, r.bottom() - bs,
00549 r.width() - 2*range - 2, handleSize - 2, g, false, 1,
00550 isActive() ? &g.brush(QColorGroup::Background) :
00551 &g.brush(QColorGroup::Mid));
00552 qDrawShadePanel(&p, r.right() - range, r.bottom() - bs,
00553 range, bs, g, false, 1, &g.brush(QColorGroup::Mid));
00554 } else {
00555 qDrawShadePanel(&p, r.x() + 1, r.bottom() - bs,
00556 r.width() - 2, bs, g, false, 1,
00557 isActive() ? &g.brush(QColorGroup::Background) :
00558 &g.brush(QColorGroup::Mid));
00559 }
00560 }
00561 r = titlebar->geometry();
00562 r.setRight(r.right()-1);
00563
00564 if(isActive()){
00565 updateActiveBuffer();
00566 p.drawPixmap(r.x(), r.y(), activeBuffer);
00567 }
00568 else{
00569 if(iUpperGradient)
00570 p.drawTiledPixmap(r.x(), r.y(), r.width(), r.height()-1,
00571 *iUpperGradient);
00572 else
00573 p.fillRect(r.x(), r.y(), r.width(), r.height()-1,
00574 options()->color(KDecoration::ColorTitleBar, false));
00575
00576 p.setFont(options()->font(false, isTool() ));
00577 QFontMetrics fm(options()->font(false));
00578 g = options()->colorGroup(KDecoration::ColorTitleBar, false);
00579 if(iUpperGradient)
00580 p.drawTiledPixmap(r.x()+((r.width()-fm.width(caption()))/2)-4,
00581 r.y(), fm.width(caption())+8, r.height()-1,
00582 *iUpperGradient);
00583 else
00584 p.fillRect(r.x()+((r.width()-fm.width(caption()))/2)-4, r.y(),
00585 fm.width(caption())+8, r.height()-1,
00586 g.brush(QColorGroup::Background));
00587 p.setPen(g.mid());
00588 p.drawLine(r.x(), r.y(), r.right(), r.y());
00589 p.drawLine(r.x(), r.y(), r.x(), r.bottom());
00590 p.setPen(g.button());
00591 p.drawLine(r.right(), r.y(), r.right(), r.bottom());
00592 p.drawLine(r.x(), r.bottom(), r.right(), r.bottom());
00593 p.setPen(options()->color(KDecoration::ColorFont, false));
00594 p.drawText(r.x(), r.y(), r.width(), r.height()-1,
00595 AlignCenter, caption() );
00596 g = options()->colorGroup(KDecoration::ColorFrame, true);
00597 p.setPen(g.background());
00598 p.drawPoint(r.x(), r.y());
00599 p.drawPoint(r.right(), r.y());
00600 p.drawLine(r.right()+1, r.y(), r.right()+1, r.bottom());
00601 }
00602 }
00603
00604 #define QCOORDARRLEN(x) sizeof(x)/(sizeof(QCOORD)*2)
00605
00606 void LaptopClient::doShape()
00607 {
00608 QRegion mask(QRect(0, 0, width(), height()));
00609 mask -= QRect(0, 0, 1, 1);
00610 mask -= QRect(width()-1, 0, 1, 1);
00611 mask -= QRect(0, height()-1, 1, 1);
00612 mask -= QRect(width()-1, height()-1, 1, 1);
00613
00614 setMask(mask);
00615 }
00616
00617 void LaptopClient::showEvent(QShowEvent *)
00618 {
00619 doShape();
00620 widget()->repaint();
00621 }
00622
00623 void LaptopClient::mouseDoubleClickEvent( QMouseEvent * e )
00624 {
00625 if ( e->button() == LeftButton && titlebar->geometry().contains( e->pos() ) )
00626 titlebarDblClickOperation();
00627 }
00628
00629 bool LaptopClient::mustDrawHandle() const
00630 {
00631 bool drawSmallBorders = !options()->moveResizeMaximizedWindows();
00632 if (drawSmallBorders && (maximizeMode() & MaximizeVertical)) {
00633 return false;
00634 } else {
00635 return isResizable();
00636 }
00637 }
00638
00639 void LaptopClient::iconChange()
00640 {
00641
00642 }
00643
00644 void LaptopClient::desktopChange()
00645 {
00646 bool on = isOnAllDesktops();
00647 if(button[BtnSticky]) {
00648 button[BtnSticky]->setBitmap(on ? unsticky_bits : sticky_bits);
00649 QToolTip::remove(button[BtnSticky]);
00650 QToolTip::add(button[BtnSticky],
00651 on ? i18n("Not on all desktops") : i18n("On all desktops"));
00652 }
00653 }
00654
00655 void LaptopClient::maximizeChange()
00656 {
00657 bool m = (maximizeMode() == MaximizeFull);
00658 int l_max = options()->titleButtonsLeft().find('A');
00659 if (button[BtnMax]) {
00660 if (!m)
00661 button[BtnMax]->setBitmap(maximize_bits);
00662 else {
00663 if (options()->customButtonPositions() && (l_max>-1))
00664 button[BtnMax]->setBitmap(l_minmax_bits);
00665 else
00666 button[BtnMax]->setBitmap(r_minmax_bits);
00667 }
00668 QToolTip::remove(button[BtnMax]);
00669 QToolTip::add(button[BtnMax], m ? i18n("Restore") : i18n("Maximize"));
00670 spacer->changeSize(10, mustDrawHandle() ? handleSize : 4,
00671 QSizePolicy::Expanding, QSizePolicy::Minimum);
00672 g->activate();
00673 doShape();
00674 widget()->repaint(false);
00675 }
00676 }
00677
00678 void LaptopClient::activeChange()
00679 {
00680 widget()->repaint(false);
00681 int i;
00682 for(i=0; i<BtnTypeCount; i++){
00683 if(button[i])
00684 button[i]->reset();
00685 }
00686 }
00687
00688
00689 void LaptopClient::calcHiddenButtons()
00690 {
00691
00692
00693 int minWidth = 32 + btnWidth2*3 + (providesContextHelp() ? btnWidth1*2 :
00694 btnWidth1);
00695
00696 if(lastButtonWidth > width()){
00697 lastButtonWidth = width();
00698 if(width() < minWidth){
00699 hiddenItems = true;
00700 int i;
00701 for(i=0; i<BtnTypeCount; i++){
00702 if(button[i]){
00703 if( !button[i]->isHidden() ) {
00704 button[i]->hide();
00705 }
00706 minWidth-=button[i]->sizeHint().width();
00707 if(width() >= minWidth)
00708 return;
00709 }
00710 }
00711 }
00712 }
00713 else if(hiddenItems){
00714 lastButtonWidth = width();
00715 int i;
00716 int totalSize=32;
00717 for(i=(BtnTypeCount-1); i>=0; --i){
00718 if(button[i]){
00719 if(button[i]->sizeHint().width() + totalSize <= width()){
00720 totalSize+=button[i]->sizeHint().width();
00721 if(button[i]->isHidden() &&
00722 ( !isTransient() || i != BtnSticky ) &&
00723 ( isMinimizable() || i != BtnIconify ) &&
00724 ( isMaximizable() || ( i != BtnIconify && i != BtnSticky && i != BtnMax ) )
00725
00726 ) {
00727 button[i]->resize(button[i]->sizeHint());
00728 button[i]->show();
00729 }
00730 }
00731 else
00732 return;
00733 }
00734 }
00735
00736 hiddenItems = false;
00737 }
00738 else
00739 lastButtonWidth = width();
00740 }
00741
00742 void LaptopClient::updateActiveBuffer( )
00743 {
00744 if( !bufferDirty && (lastBufferWidth == titlebar->geometry().width()))
00745 return;
00746 if ( titlebar->geometry().width() <= 0 || titlebar->geometry().height() <= 0 )
00747 return;
00748 lastBufferWidth = titlebar->geometry().width();
00749 bufferDirty = false;
00750
00751 activeBuffer.resize(titlebar->geometry().width(),
00752 titlebar->geometry().height());
00753 QPainter p;
00754 QRect r(0, 0, activeBuffer.width()-1, activeBuffer.height());
00755 p.begin(&activeBuffer);
00756 if(aUpperGradient){
00757 p.drawTiledPixmap(r, *aUpperGradient);
00758 }
00759 else{
00760 p.fillRect(r, options()->color(KDecoration::ColorTitleBar, true));
00761 }
00762 if(titlePix)
00763 p.drawTiledPixmap(r, *titlePix);
00764
00765 p.setFont(options()->font(true, isTool() ));
00766 QFontMetrics fm(options()->font(true));
00767 QColorGroup g = options()->colorGroup(KDecoration::ColorTitleBar, true);
00768 if(aUpperGradient)
00769 p.drawTiledPixmap(r.x()+((r.width()-fm.width(caption()))/2)-4,
00770 r.y(), fm.width(caption())+8, r.height()-1,
00771 *aUpperGradient);
00772 else
00773 p.fillRect(r.x()+((r.width()-fm.width(caption()))/2)-4, 0,
00774 fm.width(caption())+8, r.height(),
00775 g.brush(QColorGroup::Background));
00776 p.setPen(g.mid());
00777 p.drawLine(r.x(), r.y(), r.right(), r.y());
00778 p.drawLine(r.x(), r.y(), r.x(), r.bottom());
00779 p.setPen(g.button());
00780 p.drawLine(r.right(), r.y(), r.right(), r.bottom());
00781 p.drawLine(r.x(), r.bottom(), r.right(), r.bottom());
00782 p.setPen(options()->color(KDecoration::ColorFont, true));
00783 p.drawText(r.x(), r.y(), r.width(), r.height()-1,
00784 AlignCenter, caption() );
00785 g = options()->colorGroup(KDecoration::ColorFrame, true);
00786 p.setPen(g.background());
00787 p.drawPoint(r.x(), r.y());
00788 p.drawPoint(r.right(), r.y());
00789 p.drawLine(r.right()+1, r.y(), r.right()+1, r.bottom());
00790 p.end();
00791 }
00792
00793 LaptopClient::Position LaptopClient::mousePosition(const QPoint & p) const
00794 {
00795 Position m = PositionCenter;
00796 int range = 8 + 3*handleSize/2;
00797
00798 if (p.y() < (height() - handleSize + 1))
00799 m = KDecoration::mousePosition(p);
00800
00801 else {
00802 if (p.x() >= (width() - range))
00803 m = PositionBottomRight;
00804 else if (p.x() <= range)
00805 m = PositionBottomLeft;
00806 else
00807 m = PositionBottom;
00808 }
00809
00810 return m;
00811 }
00812
00813 void LaptopClient::borders(int &left, int &right, int &top, int &bottom) const
00814 {
00815 left = right = 4;
00816 top = titleHeight + 4;
00817 bottom = mustDrawHandle() ? handleSize : 4;
00818 }
00819
00820 void LaptopClient::shadeChange()
00821 {
00822 }
00823
00824 QSize LaptopClient::minimumSize() const
00825 {
00826 return QSize(4 * handleSize, handleSize);
00827 }
00828
00829 void LaptopClient::resize(const QSize& s)
00830 {
00831 widget()->resize(s);
00832 widget()->repaint();
00833 }
00834
00835 static const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask |
00836 NET::DesktopMask | NET::DockMask | NET::ToolbarMask | NET::MenuMask |
00837 NET::DialogMask | NET::OverrideMask | NET::TopMenuMask |
00838 NET::UtilityMask | NET::SplashMask;
00839
00840 bool LaptopClient::isTransient() const
00841 {
00842 NET::WindowType type = windowType(SUPPORTED_WINDOW_TYPES_MASK);
00843 return type == NET::Dialog;
00844 }
00845
00846 bool LaptopClient::isTool() const
00847 {
00848 NET::WindowType type = windowType(SUPPORTED_WINDOW_TYPES_MASK);
00849 return type == NET::Toolbar || type == NET::Utility || type == NET::Menu;
00850 }
00851
00852 bool LaptopClient::eventFilter(QObject *o, QEvent *e)
00853 {
00854 if (o != widget())
00855 return false;
00856 switch (e->type()) {
00857 case QEvent::Resize:
00858 resizeEvent(static_cast< QResizeEvent* >( e ));
00859 return true;
00860 case QEvent::Paint:
00861 paintEvent(static_cast< QPaintEvent* >( e ));
00862 return true;
00863 case QEvent::MouseButtonDblClick:
00864 mouseDoubleClickEvent(static_cast< QMouseEvent* >( e ));
00865 return true;
00866 case QEvent::MouseButtonPress:
00867 processMousePressEvent(static_cast< QMouseEvent* >( e ));
00868 return true;
00869 case QEvent::Show:
00870 showEvent(static_cast< QShowEvent* >( e ));
00871 return true;
00872 default:
00873 break;
00874 }
00875 return false;
00876 }
00877
00878
00879
00880 LaptopClientFactory::LaptopClientFactory()
00881 {
00882 create_pixmaps();
00883 }
00884
00885 LaptopClientFactory::~LaptopClientFactory()
00886 {
00887 delete_pixmaps();
00888 }
00889
00890 KDecoration *LaptopClientFactory::createDecoration(KDecorationBridge *b)
00891 {
00892 findPreferredHandleSize();
00893 return new Laptop::LaptopClient(b, this);
00894 }
00895
00896 bool LaptopClientFactory::reset(unsigned long )
00897 {
00898 findPreferredHandleSize();
00899
00900
00901
00902 Laptop::delete_pixmaps();
00903 Laptop::create_pixmaps();
00904
00905 return true;
00906 }
00907
00908 bool LaptopClientFactory::supports( Ability ability )
00909 {
00910 switch( ability )
00911 {
00912 case AbilityAnnounceButtons:
00913 case AbilityButtonOnAllDesktops:
00914 case AbilityButtonHelp:
00915 case AbilityButtonMinimize:
00916 case AbilityButtonMaximize:
00917 case AbilityButtonClose:
00918 return true;
00919 default:
00920 return false;
00921 };
00922 }
00923
00924 QValueList< LaptopClientFactory::BorderSize >
00925 LaptopClientFactory::borderSizes() const
00926 {
00927
00928 return QValueList< BorderSize >() << BorderNormal << BorderLarge <<
00929 BorderVeryLarge << BorderHuge << BorderVeryHuge << BorderOversized;
00930 }
00931
00932 void LaptopClientFactory::findPreferredHandleSize()
00933 {
00934 switch (options()->preferredBorderSize(this)) {
00935 case KDecoration::BorderLarge:
00936 handleSize = 11;
00937 break;
00938 case KDecoration::BorderVeryLarge:
00939 handleSize = 16;
00940 break;
00941 case KDecoration::BorderHuge:
00942 handleSize = 24;
00943 break;
00944 case KDecoration::BorderVeryHuge:
00945 handleSize = 32;
00946 break;
00947 case KDecoration::BorderOversized:
00948 handleSize = 40;
00949 break;
00950 case KDecoration::BorderTiny:
00951 case KDecoration::BorderNormal:
00952 default:
00953 handleSize = 8;
00954 }
00955 }
00956
00957 }
00958
00959 #include "laptopclient.moc"
00960
00961