Back to index

kdeartwork  4.3.2
systemclient.cpp
Go to the documentation of this file.
00001 /********************************************************************
00002 This program is free software; you can redistribute it and/or modify
00003 it under the terms of the GNU General Public License as published by
00004 the Free Software Foundation; either version 2 of the License, or
00005 (at your option) any later version.
00006 
00007 This program is distributed in the hope that it will be useful,
00008 but WITHOUT ANY WARRANTY; without even the implied warranty of
00009 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010 GNU General Public License for more details.
00011 
00012 You should have received a copy of the GNU General Public License
00013 along with this program.  If not, see <http://www.gnu.org/licenses/>.
00014 *********************************************************************/
00015 
00016 #include "systemclient.h"
00017 
00018 #include <qlayout.h>
00019 #include <qdrawutil.h>
00020 #include <qbitmap.h>
00021 #include <qtooltip.h>
00022 #include <qlabel.h>
00023 #include <qcursor.h>
00024 //Added by qt3to4:
00025 #include <QPixmap>
00026 #include <QPaintEvent>
00027 #include <QGridLayout>
00028 #include <QEvent>
00029 #include <QBoxLayout>
00030 #include <Q3ValueList>
00031 #include <QShowEvent>
00032 #include <QResizeEvent>
00033 #include <QMouseEvent>
00034 
00035 #include <kpixmapeffect.h>
00036 #include <kdrawutil.h>
00037 #include <klocale.h>
00038 #include <kapplication.h>
00039 #include <kdebug.h>
00040 
00041 
00042 namespace System {
00043 
00044 static unsigned char iconify_bits[] = {
00045     0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00};
00046 
00047 static unsigned char maximize_bits[] = {
00048     0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00};
00049 
00050 static unsigned char r_minmax_bits[] = {
00051     0x0c, 0x18, 0x33, 0x67, 0xcf, 0x9f, 0x3f, 0x3f};
00052 
00053 static unsigned char l_minmax_bits[] = {
00054     0x30, 0x18, 0xcc, 0xe6, 0xf3, 0xf9, 0xfc, 0xfc};
00055 
00056 static unsigned char unsticky_bits[] = {
00057     0x00, 0x18, 0x18, 0x7e, 0x7e, 0x18, 0x18, 0x00};
00058 
00059 static unsigned char sticky_bits[] = {
00060     0x00, 0x00, 0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00};
00061 
00062 static unsigned char question_bits[] = {
00063     0x3c, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18};
00064 
00065 static KPixmap *aUpperGradient=0;
00066 static KPixmap *iUpperGradient=0;
00067 
00068 static KPixmap *btnPix=0;
00069 static KPixmap *btnPixDown=0;
00070 static KPixmap *iBtnPix=0;
00071 static KPixmap *iBtnPixDown=0;
00072 static QColor *btnForeground;
00073 
00074 static bool pixmaps_created = false;
00075 
00076 static void drawButtonFrame(KPixmap *pix, const QColorGroup &g)
00077 {
00078     QPainter p;
00079     p.begin(pix);
00080     p.setPen(g.mid());
00081     p.drawLine(0, 0, 13, 0);
00082     p.drawLine(0, 0, 0, 13);
00083     p.setPen(g.light());
00084     p.drawLine(13, 0, 13, 13);
00085     p.drawLine(0, 13, 13, 13);
00086     p.setPen(g.dark());
00087     p.drawRect(1, 1, 12, 12);
00088     p.end();
00089 }
00090 
00091 static void create_pixmaps()
00092 {
00093     if(pixmaps_created)
00094         return;
00095     pixmaps_created = true;
00096 
00097     if(QPixmap::defaultDepth() > 8){
00098         // titlebar
00099         aUpperGradient = new KPixmap;
00100         aUpperGradient->resize(32, 18);
00101         iUpperGradient = new KPixmap;
00102         iUpperGradient->resize(32, 18);
00103         QColor bgColor = kapp->palette().active().background();
00104         KPixmapEffect::gradient(*aUpperGradient,
00105                                 KDecoration::options()->color(KDecorationOptions::ColorFrame, true).light(130),
00106                                 bgColor,
00107                                 KPixmapEffect::VerticalGradient);
00108         KPixmapEffect::gradient(*iUpperGradient,
00109                                 KDecoration::options()->color(KDecorationOptions::ColorFrame, false).light(130),
00110                                 bgColor,
00111                                 KPixmapEffect::VerticalGradient);
00112 
00113         // buttons
00114         KPixmap aPix;
00115         aPix.resize(12, 12);
00116         KPixmap iPix;
00117         iPix.resize(12, 12);
00118         KPixmap aInternal;
00119         aInternal.resize(8, 8);
00120         KPixmap iInternal;
00121         iInternal.resize(8, 8);
00122 
00123         QColor hColor(KDecoration::options()->color(KDecorationOptions::ColorButtonBg, false));
00124         KPixmapEffect::gradient(iInternal,
00125                                 hColor.dark(120),
00126                                 hColor.light(120),
00127                                 KPixmapEffect::DiagonalGradient);
00128         KPixmapEffect::gradient(iPix,
00129                                 hColor.light(150),
00130                                 hColor.dark(150),
00131                                 KPixmapEffect::DiagonalGradient);
00132 
00133         hColor =KDecoration::options()->color(KDecorationOptions::ColorButtonBg, true);
00134         KPixmapEffect::gradient(aInternal,
00135                                 hColor.dark(120),
00136                                 hColor.light(120),
00137                                 KPixmapEffect::DiagonalGradient);
00138         KPixmapEffect::gradient(aPix,
00139                                 hColor.light(150),
00140                                 hColor.dark(150),
00141                                 KPixmapEffect::DiagonalGradient);
00142         bitBlt(&aPix, 1, 1, &aInternal, 0, 0, 8, 8, Qt::CopyROP, true);
00143         bitBlt(&iPix, 1, 1, &iInternal, 0, 0, 8, 8, Qt::CopyROP, true);
00144 
00145         // normal buttons
00146         btnPix = new KPixmap;
00147         btnPix->resize(14, 14);
00148         bitBlt(btnPix, 2, 2, &aPix, 0, 0, 10, 10, Qt::CopyROP, true);
00149         drawButtonFrame(btnPix, KDecoration::options()->colorGroup(KDecorationOptions::ColorFrame, true));
00150 
00151         iBtnPix = new KPixmap;
00152         iBtnPix->resize(14, 14);
00153         bitBlt(iBtnPix, 2, 2, &iPix, 0, 0, 10, 10, Qt::CopyROP, true);
00154         drawButtonFrame(iBtnPix, KDecoration::options()->colorGroup(KDecorationOptions::ColorFrame, false));
00155 
00156 
00157         // pressed buttons
00158         hColor = KDecoration::options()->color(KDecorationOptions::ColorButtonBg, false);
00159         KPixmapEffect::gradient(iInternal,
00160                                 hColor.light(130),
00161                                 hColor.dark(130),
00162                                 KPixmapEffect::DiagonalGradient);
00163         KPixmapEffect::gradient(iPix,
00164                                 hColor.light(150),
00165                                 hColor.dark(150),
00166                                 KPixmapEffect::DiagonalGradient);
00167 
00168         hColor =KDecoration::options()->color(KDecorationOptions::ColorButtonBg, true);
00169         KPixmapEffect::gradient(aInternal,
00170                                 hColor.light(130),
00171                                 hColor.dark(130),
00172                                 KPixmapEffect::DiagonalGradient);
00173         KPixmapEffect::gradient(aPix,
00174                                 hColor.light(150),
00175                                 hColor.dark(150),
00176                                 KPixmapEffect::DiagonalGradient);
00177         bitBlt(&aPix, 1, 1, &aInternal, 0, 0, 8, 8, Qt::CopyROP, true);
00178         bitBlt(&iPix, 1, 1, &iInternal, 0, 0, 8, 8, Qt::CopyROP, true);
00179 
00180         btnPixDown = new KPixmap;
00181         btnPixDown->resize(14, 14);
00182         bitBlt(btnPixDown, 2, 2, &aPix, 0, 0, 10, 10, Qt::CopyROP, true);
00183         drawButtonFrame(btnPixDown, KDecoration::options()->colorGroup(KDecorationOptions::ColorFrame,
00184                                                         true));
00185 
00186         iBtnPixDown = new KPixmap;
00187         iBtnPixDown->resize(14, 14);
00188         bitBlt(iBtnPixDown, 2, 2, &iPix, 0, 0, 10, 10, Qt::CopyROP, true);
00189         drawButtonFrame(iBtnPixDown, options()->colorGroup(KDecorationOptions::ColorFrame,
00190                                                          false));
00191     }
00192     if(qGray(KDecoration::options()->color(KDecorationOptions::ColorButtonBg, true).rgb()) > 128)
00193         btnForeground = new QColor(Qt::black);
00194     else
00195         btnForeground = new QColor(Qt::white);
00196 }
00197 
00198 static void delete_pixmaps()
00199 {
00200     if(aUpperGradient){
00201         delete aUpperGradient;
00202         delete iUpperGradient;
00203         delete btnPix;
00204         delete btnPixDown;
00205         delete iBtnPix;
00206         delete iBtnPixDown;
00207         aUpperGradient = 0;
00208     }
00209     delete btnForeground;
00210     pixmaps_created = false;
00211 }
00212 
00213 SystemButton::SystemButton(SystemClient *parent, const char *name,
00214                            const unsigned char *bitmap)
00215 : KCommonDecorationButton(parent->widget(), name)
00216 {
00217    setBackgroundMode( Qt::NoBackground );
00218    setCursor(Qt::ArrowCursor);
00219    resize(14, 14);
00220    if(bitmap)
00221       setBitmap(bitmap);
00222    client = parent;
00223 }
00224 
00225 
00226 QSize SystemButton::sizeHint() const
00227 {
00228     return(QSize(14, 14));
00229 }
00230 
00231 void SystemButton::reset(unsigned long changed)
00232 {
00233   if (changed&DecorationReset || changed&ManualReset || changed&SizeChange || changed&StateChange) {
00234     switch (type() ) {
00235       case CloseButton:
00236         setBitmap(close_bits);
00237         break;
00238       case HelpButton:
00239         setBitmap(question_bits);
00240         break;
00241       case MinButton:
00242         setBitmap(iconify_bits);
00243         break;
00244       case MaxButton:
00245         setBitmap( isOn() ? unmaximize_bits : maximize_bits );
00246         break;
00247       case OnAllDesktopsButton:
00248         setBitmap( isOn() ? unsticky_bits : sticky_bits );
00249         break;
00250       case ShadeButton:
00251         setBitmap( isOn() ? shade_on_bits : shade_off_bits );
00252         break;
00253       default:
00254         setBitmap(0);
00255         break;
00256     }
00257 
00258     this->update();
00259   }
00260 #if 0
00261   static unsigned char iconify_bits[] = {
00262     0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00};
00263 
00264 static unsigned char maximize_bits[] = {
00265     0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00};
00266 
00267 static unsigned char r_minmax_bits[] = {
00268     0x0c, 0x18, 0x33, 0x67, 0xcf, 0x9f, 0x3f, 0x3f};
00269 
00270 static unsigned char l_minmax_bits[] = {
00271     0x30, 0x18, 0xcc, 0xe6, 0xf3, 0xf9, 0xfc, 0xfc};
00272 
00273 #endif
00274 }
00275 
00276 void SystemButton::setBitmap(const unsigned char *bitmap)
00277 {
00278     deco = QBitmap(8, 8, bitmap, true);
00279     deco.setMask(deco);
00280     repaint();
00281 }
00282 
00283 void SystemButton::drawButton(QPainter *p)
00284 {
00285     if(btnPixDown){
00286         if(client->isActive())
00287             p->drawPixmap(0, 0, isDown() ? *btnPixDown : *btnPix);
00288         else
00289             p->drawPixmap(0, 0, isDown() ? *iBtnPixDown : *iBtnPix);
00290     }
00291     else{
00292         QColorGroup g = KDecoration::options()->color(KDecorationOptions::ColorFrame,
00293                                             client->isActive());
00294         int x2 = width()-1;
00295         int y2 = height()-1;
00296         // outer frame
00297         p->setPen(g.mid());
00298         p->drawLine(0, 0, x2, 0);
00299         p->drawLine(0, 0, 0, y2);
00300         p->setPen(g.light());
00301         p->drawLine(x2, 0, x2, y2);
00302         p->drawLine(0, x2, y2, x2);
00303         p->setPen(g.dark());
00304         p->drawRect(1, 1, width()-2, height()-2);
00305         // inner frame
00306         g = KDecoration::options()->colorGroup(KDecorationOptions::ColorButtonBg, client->isActive());
00307         p->fillRect(3, 3, width()-6, height()-6, g.background());
00308         p->setPen(isDown() ? g.mid() : g.light());
00309         p->drawLine(2, 2, x2-2, 2);
00310         p->drawLine(2, 2, 2, y2-2);
00311         p->setPen(isDown() ? g.light() : g.mid());
00312         p->drawLine(x2-2, 2, x2-2, y2-2);
00313         p->drawLine(2, x2-2, y2-2, x2-2);
00314 
00315     }
00316 
00317     if(!deco.isNull()){
00318         p->setPen(*btnForeground);
00319         p->drawPixmap(isDown() ? 4 : 3, isDown() ? 4 : 3, deco);
00320     }
00321 }
00322 
00323 
00324 
00325 
00326 SystemClient::SystemClient(KDecorationBridge* bridge, KDecorationFactory* factory)
00327     : KCommonDecoration(bridge, factory)
00328 {}
00329 
00330 SystemClient::~SystemClient()
00331 {
00332 }
00333 
00334 QString SystemClient::visibleName() const
00335 {
00336     return i18n( "System++" );
00337 }
00338 
00339 QString SystemClient::defaultButtonsLeft() const
00340 {
00341     return "X";
00342 }
00343 
00344 QString SystemClient::defaultButtonsRight() const
00345 {
00346     return "HSIA";
00347 }
00348 
00349 KCommonDecorationButton *SystemClient::createButton(ButtonType type)
00350 {
00351     switch (type) {
00352         case OnAllDesktopsButton:
00353             return new SystemButton(this, "sticky", NULL);
00354 
00355         case HelpButton:
00356             return new SystemButton(this, "help", question_bits);
00357 
00358         case MinButton:
00359             return new SystemButton(this, "iconify", iconify_bits);
00360 
00361         case MaxButton:
00362             return new SystemButton(this, "maximize", maximize_bits);
00363 
00364         case CloseButton:
00365             return new SystemButton(this, "close", NULL);
00366 
00367 
00368         default:
00369             return 0;
00370     }
00371 }
00372 
00373 void SystemClient::init()
00374 {
00375     //TODO ?????
00376     KCommonDecoration::init();
00377 }
00378 
00379 
00380 void SystemClient::reset(unsigned long changed)
00381 {
00382 #if 0
00383     titleBuffer.resize(0, 0);
00384     recalcTitleBuffer();
00385 #endif
00386     KCommonDecoration::reset(changed);
00387 }
00388 
00389 void SystemClient::resizeEvent( QResizeEvent* )
00390 {
00391     //Client::resizeEvent( e );
00392     recalcTitleBuffer();
00393     doShape();
00394     /*
00395     if ( isVisibleToTLW() && !testWFlags( WStaticContents )) {
00396         QPainter p( this );
00397        QRect t = titlebar->geometry();
00398        t.setTop( 0 );
00399        QRegion r = rect();
00400        r = r.subtract( t );
00401        p.setClipRegion( r );
00402        p.eraseRect( rect() );
00403         }*/
00404 }
00405 
00406 
00407 QSize SystemClient::minimumSize() const
00408 {
00409    return widget()->minimumSize();
00410 }
00411 
00412 
00413 void SystemClient::recalcTitleBuffer()
00414 {
00415     if(oldTitle == caption() && width() == titleBuffer.width())
00416         return;
00417     QFontMetrics fm(options()->font(true));
00418     titleBuffer.resize(width(), 18);
00419     QPainter p;
00420     p.begin(&titleBuffer);
00421     if(aUpperGradient)
00422         p.drawTiledPixmap(0, 0, width(), 18, *aUpperGradient);
00423     else
00424         p.fillRect(0, 0, width(), 18,
00425                    options()->colorGroup(KDecorationOptions::ColorFrame, true).
00426                    brush(QPalette::Button));
00427 
00428     QRect t = titlebar->geometry();
00429     t.setTop( 2 );
00430     t.setLeft( t.left() + 4 );
00431     t.setRight( t.right() - 2 );
00432 
00433     QRegion r(t.x(), 0, t.width(), 18);
00434     r -= QRect(t.x()+((t.width()-fm.width(caption()))/2)-4,
00435                0, fm.width(caption())+8, 18);
00436     p.setClipRegion(r);
00437     int i, ly;
00438     for(i=0, ly=4; i < 4; ++i, ly+=3){
00439         p.setPen(options()->color(KDecorationOptions::ColorTitleBar, true).light(150));
00440         p.drawLine(0, ly, width()-1, ly);
00441         p.setPen(options()->color(KDecorationOptions::ColorTitleBar, true).dark(120));
00442         p.drawLine(0, ly+1, width()-1, ly+1);
00443     }
00444     p.setClipRect(t);
00445     p.setPen(options()->color(KDecorationOptions::ColorFont, true));
00446     p.setFont(options()->font(true));
00447 
00448     p.drawText(t.x()+((t.width()-fm.width(caption()))/2)-4,
00449                0, fm.width(caption())+8, 18, Qt::AlignCenter, caption());
00450     p.setClipping(false);
00451     p.end();
00452     oldTitle = caption();
00453 }
00454 
00455 
00456 void SystemClient::drawRoundFrame(QPainter &p, int x, int y, int w, int h)
00457 {
00458    kDrawRoundButton(&p, x, y, w, h,
00459                     options()->colorGroup(KDecorationOptions::ColorFrame, isActive()), false);
00460 
00461 }
00462 
00463 void SystemClient::paintEvent( QPaintEvent* )
00464 {
00465     QPainter p(widget());
00466     QRect t = titlebar->geometry();
00467 
00468     QBrush fillBrush(widget()->palette().brush(QPalette::Background).pixmap() ?
00469                      widget()->palette().brush(QPalette::Background) :
00470                      options()->color(KDecorationOptions::ColorFrame, isActive()).
00471                      brush(QPalette::Button));
00472 
00473     p.fillRect(1, 18, width()-2, height()-19, fillBrush);
00474 
00475     t.setTop( 2 );
00476     t.setLeft( t.left() + 4 );
00477     t.setRight( t.right() - 2 );
00478 
00479     if(isActive())
00480         p.drawPixmap(0, 0, titleBuffer);
00481     else{
00482         if(iUpperGradient)
00483             p.drawTiledPixmap(0, 0, width(), 18, *iUpperGradient);
00484         else
00485             p.fillRect(0, 0, width(), 18, fillBrush);
00486         p.setPen(options()->color(KDecorationOptions::ColorFont, isActive()));
00487         p.setFont(options()->font(isActive()));
00488         p.drawText(t, Qt::AlignCenter, caption() );
00489     }
00490 
00491     p.setPen(options()->color(KDecorationOptions::ColorFrame, isActive()).light());
00492     p.drawLine(width()-20, height()-7, width()-10,  height()-7);
00493     p.drawLine(width()-20, height()-5, width()-10,  height()-5);
00494     p.setPen(options()->color(KDecorationOptions::ColorFrame, isActive()).dark());
00495     p.drawLine(width()-20, height()-6, width()-10,  height()-6);
00496     p.drawLine(width()-20, height()-4, width()-10,  height()-4);
00497 
00498     drawRoundFrame(p, 0, 0, width(), height());
00499 }
00500 
00501 #define QCOORDARRLEN(x) sizeof(x)/(sizeof(QCOORD)*2)
00502 
00503 void SystemClient::doShape()
00504 {
00505     // using a bunch of QRect lines seems much more efficent than bitmaps or
00506     // point arrays
00507 
00508     QRegion mask;
00509     kRoundMaskRegion(mask, 0, 0, width(), height());
00510     setMask(mask);
00511 }
00512 
00513 void SystemClient::showEvent(QShowEvent *)
00514 {
00515 //    Client::showEvent(ev);
00516     doShape();
00517     widget()->show();
00518 //    widget()->repaint();
00519 }
00520 
00521 /*void SystemClient::windowWrapperShowEvent( QShowEvent* )
00522 {
00523     doShape();
00524 }*/
00525 
00526 void SystemClient::mouseDoubleClickEvent( QMouseEvent * e )
00527 {
00528    if ( e->button() == Qt::LeftButton && titlebar->geometry().contains( e->pos() ) )
00529       titlebarDblClickOperation();
00530 }
00531 
00532 
00533 
00534 
00535 /*void SystemClient::stickyChange(bool on)
00536 {
00537 }*/
00538 
00539 KDecoration::Position SystemClient::mousePosition(const QPoint &p) const
00540 {
00541    return KDecoration::mousePosition(p);
00542 }
00543 
00544 void SystemClient::borders(int& left, int& right, int& top, int& bottom) const
00545 {
00546     left = 4;
00547     right = 4;
00548     top =  18;
00549     bottom = 8;
00550 
00551 /*    if ((maximizeMode()==MaximizeFull) && !options()->moveResizeMaximizedWindows()) {
00552         left = right = bottom = 0;
00553         top = 1 + titleHeight + (borderSize-1);
00554     }*/
00555 }
00556 
00557 SystemDecoFactory::SystemDecoFactory()
00558 {
00559    create_pixmaps();
00560 }
00561 
00562 SystemDecoFactory::~SystemDecoFactory()
00563 {
00564    delete_pixmaps();
00565 }
00566 
00567 KDecoration *SystemDecoFactory::createDecoration( KDecorationBridge *b )
00568 {
00569    return new SystemClient(b, this);
00570 }
00571 
00572 bool SystemDecoFactory::reset( unsigned long changed )
00573 {
00574    System::delete_pixmaps();
00575    System::create_pixmaps();
00576    // Ensure changes in tooltip state get applied
00577    resetDecorations(changed);
00578    return true;
00579 }
00580 
00581 bool SystemDecoFactory::supports( Ability ability )
00582 {
00583     switch( ability )
00584     {
00585         case AbilityAnnounceButtons:
00586         case AbilityButtonOnAllDesktops:
00587         case AbilityButtonHelp:
00588         case AbilityButtonMinimize:
00589         case AbilityButtonMaximize:
00590         case AbilityButtonClose:
00591             return true;
00592         default:
00593             return false;
00594     };
00595 }
00596 
00597 QList<KDecorationFactory::BorderSize> SystemDecoFactory::borderSizes() const
00598 { // the list must be sorted
00599    return Q3ValueList< BorderSize >() << BorderNormal;
00600 }
00601 
00602 }
00603 
00604 extern "C" KDE_EXPORT KDecorationFactory *create_factory()
00605 {
00606    return new System::SystemDecoFactory();
00607 }
00608 
00609 #include "systemclient.moc"