kwin Library API Documentation

modernsys.cpp

00001 // Daniel M. DULEY <mosfet@kde.org>               original work
00002 // Melchior FRANZ  <a8603365@unet.univie.ac.at>   configuration options
00003 
00004 #include <kconfig.h>
00005 #include <kglobal.h>
00006 #include <klocale.h>
00007 #include <qlayout.h>
00008 #include <qdrawutil.h>
00009 #include <kpixmapeffect.h>
00010 #include <kdrawutil.h>
00011 #include <qbitmap.h>
00012 #include <qtooltip.h>
00013 #include <qapplication.h>
00014 #include <qlabel.h>
00015 #include "modernsys.h"
00016 
00017 #include "buttondata.h"
00018 #include "btnhighcolor.h"
00019 #include <qimage.h>
00020 
00021 namespace ModernSystem {
00022 
00023 static unsigned char iconify_bits[] = {
00024     0x00, 0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00};
00025 
00026 static unsigned char close_bits[] = {
00027     0x00, 0x66, 0x7e, 0x3c, 0x3c, 0x7e, 0x66, 0x00};
00028 
00029 static unsigned char maximize_bits[] = {
00030     0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00};
00031 
00032 static unsigned char minmax_bits[] = {
00033     0x0c, 0x18, 0x33, 0x67, 0xcf, 0x9f, 0x3f, 0x3f};
00034 
00035 static unsigned char unsticky_bits[] = {
00036     0x3c, 0x42, 0x99, 0xbd, 0xbd, 0x99, 0x42, 0x3c};
00037 
00038 static unsigned char sticky_bits[] = {
00039     0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
00040 
00041 static unsigned char question_bits[] = {
00042     0x3c, 0x66, 0x60, 0x30, 0x18, 0x00, 0x18, 0x18};
00043 
00044 static unsigned char above_on_bits[] = {
00045     0x7e, 0x00, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00};
00046 
00047 static unsigned char above_off_bits[] = {
00048     0x18, 0x3c, 0x7e, 0x00, 0x7e, 0x00, 0x00, 0x00};
00049 
00050 static unsigned char below_off_bits[] = {
00051     0x00, 0x00, 0x00, 0x7e, 0x00, 0x7e, 0x3c, 0x18};
00052 
00053 static unsigned char below_on_bits[] = {
00054     0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x00, 0x7e};
00055 
00056 static unsigned char shade_off_bits[] = {
00057     0x00, 0x7e, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00};
00058 
00059 static unsigned char shade_on_bits[] = {
00060     0x00, 0x7e, 0x7e, 0x42, 0x42, 0x42, 0x7e, 0x00};
00061 
00062 static unsigned char btnhighcolor_mask_bits[] = {
00063     0xe0,0x41,0xf8,0x07,0xfc,0x0f,0xfe,0xdf,0xfe,0x1f,0xff,0x3f,0xff,0xff,0xff,
00064     0x3f,0xff,0x3f,0xff,0xff,0xff,0xff,0xfe,0x9f,0xfe,0x1f,0xfc,0x0f,0xf0,0x03,
00065     0x00,0x40,0x80,0x00,0x00,0x00,0x39,0x00,0x00,0x00,0x20,0x99,0x0f,0x08,0xc4,
00066     0x00,0x00,0x00,0x67,0x00,0x00,0x00,0x58,0x5f,0x43,0x68,0x61,0x6e,0x67,0x65 };
00067 
00068 static KPixmap *aUpperGradient=0;
00069 static KPixmap *iUpperGradient=0;
00070 static QPixmap *buttonPix=0;
00071 static QPixmap *buttonPixDown=0;
00072 static QPixmap *iButtonPix=0;
00073 static QPixmap *iButtonPixDown=0;
00074 
00075 static QColor *buttonFg;
00076 static bool pixmaps_created = false;
00077 
00078 static QBitmap *lcDark1;
00079 static QBitmap *lcDark2;
00080 static QBitmap *lcDark3;
00081 static QBitmap *lcLight1;
00082 static QImage *btnSource;
00083 
00084 static QString *button_pattern = NULL;
00085 static bool show_handle;
00086 static int handle_size;
00087 static int handle_width;
00088 static int border_width;
00089 static int title_height;
00090 
00091 static inline const KDecorationOptions* options()
00092 {
00093     return KDecoration::options();
00094 }
00095 
00096 static void make_button_fx(const QColorGroup &g, QPixmap *pix, bool light=false)
00097 {
00098     pix->fill(g.background());
00099     QPainter p(pix);
00100 
00101     if(QPixmap::defaultDepth() > 8){
00102         int i, destH, destS, destV, srcH, srcS, srcV;
00103         QColor btnColor = g.background();
00104 
00105         if(btnSource->depth() < 32)
00106             *btnSource = btnSource->convertDepth(32);
00107         if(light)
00108             btnColor = btnColor.light(120);
00109         btnColor.hsv(&destH, &destS, &destV);
00110         QImage btnDest(14, 15, 32);
00111 
00112         unsigned int *srcData = (unsigned int *)btnSource->bits();
00113         unsigned int *destData = (unsigned int *)btnDest.bits();
00114         QColor srcColor;
00115         for(i=0; i < btnSource->width()*btnSource->height(); ++i){
00116             srcColor.setRgb(srcData[i]);
00117             srcColor.hsv(&srcH, &srcS, &srcV);
00118             srcColor.setHsv(destH, destS, srcV);
00119             destData[i] = srcColor.rgb();
00120         }
00121         pix->convertFromImage(btnDest);
00122 
00123     }
00124     else{
00125         if(!lcDark1->mask()){
00126             lcDark1->setMask(*lcDark1);
00127             lcDark2->setMask(*lcDark2);
00128             lcDark3->setMask(*lcDark3);
00129             lcLight1->setMask(*lcLight1);
00130         }
00131         p.setPen(g.dark());
00132         p.drawPixmap(0, 0, *lcDark2);
00133         p.drawPixmap(0, 0, *lcDark1);
00134         p.setPen(g.mid());
00135         p.drawPixmap(0, 0, *lcDark3);
00136         p.setPen(g.light());
00137         p.drawPixmap(0, 0, *lcLight1);
00138     }
00139 }
00140 
00141 
00142 static void create_pixmaps()
00143 {
00144     if(pixmaps_created)
00145         return;
00146     pixmaps_created = true;
00147 
00148     lcDark1 = new QBitmap(14, 15, lowcolor_6a696a_bits, true);
00149     lcDark2 = new QBitmap(14, 15, lowcolor_949194_bits, true);
00150     lcDark3 = new QBitmap(14, 15, lowcolor_b4b6b4_bits, true);
00151     lcLight1 = new QBitmap(14, 15, lowcolor_e6e6e6_bits, true);
00152     btnSource = new QImage(btnhighcolor_xpm);
00153 
00154     if(QPixmap::defaultDepth() > 8){
00155         aUpperGradient = new KPixmap;
00156         aUpperGradient->resize(32, title_height+2);
00157         iUpperGradient = new KPixmap;
00158         iUpperGradient->resize(32, title_height+2);
00159         KPixmapEffect::gradient(*aUpperGradient,
00160                                 options()->color(KDecoration::ColorTitleBar, true).light(130),
00161                                 options()->color(KDecoration::ColorTitleBlend, true),
00162                                 KPixmapEffect::VerticalGradient);
00163         KPixmapEffect::gradient(*iUpperGradient,
00164                                 options()->color(KDecoration::ColorTitleBar, false).light(130),
00165                                 options()->color(KDecoration::ColorTitleBlend, false),
00166                                 KPixmapEffect::VerticalGradient);
00167     }
00168     // buttons
00169     QColorGroup btnColor(options()->colorGroup(KDecoration::ColorButtonBg, true));
00170     buttonPix = new QPixmap(14, 15);
00171     make_button_fx(btnColor, buttonPix);
00172     buttonPixDown = new QPixmap(14, 15);
00173     make_button_fx(btnColor, buttonPixDown, true);
00174 
00175     btnColor = options()->colorGroup(KDecoration::ColorButtonBg, false);
00176     iButtonPix = new QPixmap(14, 15);
00177     make_button_fx(btnColor, iButtonPix);
00178     iButtonPixDown = new QPixmap(14, 15);
00179     make_button_fx(btnColor, iButtonPixDown, true);
00180 
00181 
00182     if(qGray(btnColor.background().rgb()) < 150)
00183         buttonFg = new QColor(Qt::white);
00184     else
00185         buttonFg = new QColor(Qt::black);
00186 
00187     delete lcDark1;
00188     delete lcDark2;
00189     delete lcDark3;
00190     delete lcLight1;
00191     delete btnSource;
00192 }
00193 
00194 static void delete_pixmaps()
00195 {
00196     if(aUpperGradient){
00197         delete aUpperGradient;
00198         delete iUpperGradient;
00199     }
00200     delete buttonPix;
00201     delete buttonPixDown;
00202     delete iButtonPix;
00203     delete iButtonPixDown;
00204 
00205     delete buttonFg;
00206 
00207     pixmaps_created = false;
00208 }
00209 
00210 bool ModernSysFactory::read_config()
00211 {
00212     bool showh;
00213     int hsize, hwidth, bwidth, theight;
00214     QString bpatt;
00215 
00216     KConfig c("kwinmodernsysrc");
00217     c.setGroup("General");
00218     showh = c.readBoolEntry("ShowHandle", true);
00219 
00220     hwidth = c.readUnsignedNumEntry("HandleWidth", 6);
00221     hsize = c.readUnsignedNumEntry("HandleSize", 30);
00222     if (!(showh && hsize && hwidth)) {
00223         showh = false;
00224         hwidth = hsize = 0;
00225     }
00226 
00227     switch(options()->preferredBorderSize( this )) {
00228       case BorderLarge:
00229           bwidth = 8;
00230           hwidth = hwidth * 7/5;
00231           hsize  = hsize  * 7/5;
00232           break;
00233       case BorderVeryLarge:
00234           bwidth = 12;
00235           hwidth = hwidth * 17/10 + 2;
00236           hsize  = hsize  * 17/10;
00237           break;
00238       case BorderHuge:
00239           bwidth = 18;
00240           hwidth = hwidth * 2 + 6;
00241           hsize  = hsize  * 2;
00242           break;
00243       /*
00244       // If we allow these large sizes we need to change the
00245       // correlation between the border width and the handle size.
00246       case BorderVeryHuge:
00247           bwidth = 27;
00248           hwidth = hwidth * 5/2 + 15;
00249           hsize  = hsize  * 5/2;
00250           break;
00251       case BorderOversized:
00252           bwidth = 40;
00253           hwidth = hwidth * 3 + 22;
00254           hsize  = hsize  * 3;
00255           break;
00256       */
00257       case BorderNormal:
00258       default:
00259           bwidth = 4;
00260     }
00261 
00262     theight = QFontMetrics(options()->font(true)).height() + 2;
00263     if (theight < 16)
00264         theight = 16;
00265     if (theight < bwidth)
00266         theight = bwidth;
00267 
00268     if (options()->customButtonPositions()) {
00269         bpatt = "2" + options()->titleButtonsLeft() + "3t3"
00270                 + options()->titleButtonsRight() + "2";
00271     }
00272     else
00273         bpatt = "2X3t3HSIA2";
00274 
00275     if (showh == show_handle && hwidth == handle_width && hsize == handle_size
00276             && bwidth == border_width && theight == title_height
00277             && bpatt == *button_pattern)
00278         return false;
00279 
00280     show_handle = showh;
00281     handle_width = hwidth;
00282     handle_size = hsize;
00283     border_width = bwidth;
00284     title_height = theight;
00285     *button_pattern = bpatt;
00286     return true;
00287 }
00288 
00289 QValueList< ModernSysFactory::BorderSize > ModernSysFactory::borderSizes() const
00290 { // the list must be sorted
00291   return QValueList< BorderSize >() << BorderNormal << BorderLarge <<
00292       BorderVeryLarge <<  BorderHuge;
00293    // as long as the buttons don't scale don't offer the largest two sizes.
00294    //   BorderVeryLarge <<  BorderHuge << BorderVeryHuge << BorderOversized;
00295 }
00296 
00297 ModernButton::ModernButton(ModernSys *parent, const char *name, bool toggle,
00298                            const unsigned char *bitmap, const QString& tip, const int realizeBtns)
00299     : QButton(parent->widget(), name),
00300       last_button( NoButton ) 
00301 {
00302     setBackgroundMode( NoBackground );
00303 
00304     setToggleButton(toggle);
00305 
00306     setCursor( arrowCursor );
00307     realizeButtons = realizeBtns;
00308     QBitmap mask(14, 15, QPixmap::defaultDepth() > 8 ?
00309                  btnhighcolor_mask_bits : lowcolor_mask_bits, true);
00310     resize(14, 15);
00311 
00312     if(bitmap)
00313         setBitmap(bitmap);
00314     setMask(mask);
00315     hide();
00316     client = parent;
00317     QToolTip::add( this, tip );
00318 
00319 }
00320 
00321 QSize ModernButton::sizeHint() const
00322 {
00323     return(QSize(14, 15));
00324 }
00325 
00326 // Make the protected member public
00327 void ModernButton::turnOn( bool isOn )
00328 {
00329     if ( isToggleButton() )
00330         setOn( isOn );
00331 }
00332 
00333 void ModernButton::reset()
00334 {
00335     repaint(false);
00336 }
00337 
00338 void ModernButton::setBitmap(const unsigned char *bitmap)
00339 {
00340     deco = QBitmap(8, 8, bitmap, true);
00341     deco.setMask(deco);
00342     repaint();
00343 }
00344 
00345 void ModernButton::drawButton(QPainter *p)
00346 {
00347     if(client->isActive()){
00348         if(buttonPix)
00349             p->drawPixmap(0, 0, isDown() ? *buttonPixDown : *buttonPix);
00350     }
00351     else{
00352         if(iButtonPix)
00353             p->drawPixmap(0, 0, isDown() ? *iButtonPixDown : *iButtonPix);
00354     }
00355     if(!deco.isNull()){
00356         p->setPen(*buttonFg);
00357         p->drawPixmap(isDown() ? 4 : 3, isDown() ? 5 : 4, deco);
00358     }
00359 }
00360 
00361 void ModernButton::mousePressEvent( QMouseEvent* e )
00362 {
00363     last_button = e->button();
00364     QMouseEvent me ( e->type(), e->pos(), e->globalPos(), (e->button()&realizeButtons)?LeftButton:NoButton, e->state() );
00365     QButton::mousePressEvent( &me );
00366 }
00367 
00368 void ModernButton::mouseReleaseEvent( QMouseEvent* e )
00369 {
00370     QMouseEvent me ( e->type(), e->pos(), e->globalPos(), (e->button()&realizeButtons)?LeftButton:NoButton, e->state() );
00371     QButton::mouseReleaseEvent( &me );
00372 }
00373 
00374 
00375 void ModernSys::reset( unsigned long )
00376 {
00377     titleBuffer.resize(0, 0);
00378     recalcTitleBuffer();
00379     for (int i = 0; i < 5; button[i++]->reset());
00380     widget()->repaint();
00381 }
00382 
00383 ModernSys::ModernSys( KDecorationBridge* b, KDecorationFactory* f )
00384     : KDecoration( b, f )
00385 {
00386 }
00387 
00388 void ModernSys::init()
00389 {
00390     connect( this, SIGNAL( keepAboveChanged( bool )), SLOT( keepAboveChange( bool )));
00391     connect( this, SIGNAL( keepBelowChanged( bool )), SLOT( keepBelowChange( bool )));
00392 
00393     createMainWidget( WResizeNoErase );
00394     widget()->installEventFilter( this );
00395     bool reverse = QApplication::reverseLayout();
00396 
00397     bool help = providesContextHelp();
00398 
00399     QGridLayout* g = new QGridLayout(widget(), 0, 0, 2);
00400     if( isPreview())
00401         g->addWidget( new QLabel( i18n( "<center><b>Modern System preview</b></center>" ), widget()), 1, 1 );
00402     else
00403         g->addItem( new QSpacerItem( 0, 0 ), 1, 1 ); // no widget in the middle
00404     g->setRowStretch(1, 10);
00405     g->addItem( new QSpacerItem( 0, 0, QSizePolicy::Fixed, QSizePolicy::Expanding ) );
00406 
00407     g->addColSpacing(0, border_width-2 + (reverse ? handle_width : 0));
00408     g->addColSpacing(2, border_width-2 + (reverse ? 0 : handle_width));
00409 
00410     g->addRowSpacing(2, border_width-2 + handle_width);
00411 
00412     QBoxLayout* hb = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
00413     hb->setResizeMode(QLayout::FreeResize);
00414     titlebar = new QSpacerItem(10, title_height, QSizePolicy::Expanding,
00415                                QSizePolicy::Minimum);
00416 
00417     button[BtnClose] = new ModernButton(this, "close", false, close_bits, i18n("Close"));
00418     button[BtnSticky] = new ModernButton(this, "sticky", false, NULL, isOnAllDesktops()?i18n("Unsticky"):i18n("Sticky"));
00419     button[BtnMinimize] = new ModernButton(this, "iconify", false, iconify_bits, i18n("Minimize"));
00420     button[BtnMaximize] = new ModernButton(this, "maximize", false, maximize_bits, i18n("Maximize"), LeftButton|MidButton|RightButton);
00421     button[BtnHelp] = new ModernButton(this, "help", false, question_bits, i18n("Help"));
00422     button[BtnAbove] = new ModernButton(this, "above", true, above_off_bits, i18n("Keep above others"));
00423     button[BtnBelow] = new ModernButton(this, "below", true, below_off_bits, i18n("Keep below others"));
00424     button[BtnShade] = new ModernButton(this, "shade", true, shade_off_bits, isSetShade()?i18n("Unshade"):i18n("Shade") );
00425 
00426     connect( button[BtnClose], SIGNAL(clicked()), this, SLOT( closeWindow() ) );
00427     connect( button[BtnSticky], SIGNAL(clicked()), this, SLOT( toggleOnAllDesktops() ) );
00428     connect( button[BtnMinimize], SIGNAL(clicked()), this, SLOT( minimize() ) );
00429     connect( button[BtnMaximize], SIGNAL(clicked()), this, SLOT( maxButtonClicked() ) );
00430     connect( button[BtnHelp], SIGNAL(clicked()), this, SLOT( showContextHelp() ) );
00431     connect( button[BtnAbove], SIGNAL( clicked()), this, SLOT(slotAbove()) );
00432     connect( button[BtnBelow], SIGNAL( clicked()), this, SLOT(slotBelow()) );
00433     connect( button[BtnShade], SIGNAL( clicked()), this, SLOT(slotShade()) );
00434 
00435     for (int i = 0; i < (int)button_pattern->length();) {
00436         QChar c = (*button_pattern)[i++];
00437         if (c == '_')
00438             c = '3';
00439 
00440         if (c.isDigit()) {
00441             hb->addSpacing(int(c - '0'));
00442             continue;
00443         }
00444         else if (c == 'X' && isCloseable()) {
00445             hb->addWidget(button[BtnClose]);
00446             button[BtnClose]->show();
00447         }
00448         else if (c == 'S') {
00449             if(isOnAllDesktops())
00450                 button[BtnSticky]->setBitmap(unsticky_bits);
00451             else
00452                 button[BtnSticky]->setBitmap(sticky_bits);
00453             hb->addWidget(button[BtnSticky]);
00454             button[BtnSticky]->show();
00455         }
00456         else if (c == 'I' && isMinimizable()) {
00457             hb->addWidget(button[BtnMinimize]);
00458             button[BtnMinimize]->show();
00459         }
00460         else if (c == 'A' && isMaximizable()) {
00461             hb->addWidget(button[BtnMaximize]);
00462             button[BtnMaximize]->show();
00463         }
00464         else if (help && c == 'H') {
00465             hb->addWidget(button[BtnHelp]);
00466             button[BtnHelp]->show();
00467         }
00468         else if (c == 'F') {
00469             button[BtnAbove]->setBitmap(keepAbove()?above_on_bits:above_off_bits);
00470             hb->addWidget(button[BtnAbove]);
00471             button[BtnAbove]->show();
00472         }
00473         else if (c == 'B') {
00474             button[BtnBelow]->setBitmap(keepBelow()?below_on_bits:below_off_bits);
00475             hb->addWidget(button[BtnBelow]);
00476             button[BtnBelow]->show();
00477         }
00478         else if (c == 'L' && isShadeable()) {
00479             button[BtnShade]->setBitmap(isSetShade()?shade_on_bits:shade_off_bits);
00480             hb->addWidget(button[BtnShade]);
00481             button[BtnShade]->show();
00482         }
00483         else if (c == 't')
00484             hb->addItem(titlebar);
00485 
00486         if ((*button_pattern)[i] >= 'A' && (*button_pattern)[i] <= 'Z')
00487             hb->addSpacing(1);
00488     }
00489 
00490     g->addLayout( hb, 0, 1 );
00491     widget()->setBackgroundMode(NoBackground);
00492     recalcTitleBuffer();
00493     widget()->layout()->activate();
00494 }
00495 
00496 
00497 void ModernSys::maxButtonClicked( )
00498 {
00499     if (button[BtnMaximize]) {
00500         maximize(button[BtnMaximize]->last_button);
00501     }
00502 }
00503 
00504 void ModernSys::slotAbove()
00505 {
00506     setKeepAbove( !keepAbove());
00507     if (button[BtnAbove]) {
00508         button[BtnAbove]->turnOn(keepAbove());
00509         button[BtnAbove]->repaint(true);
00510     }
00511 }
00512 
00513     
00514 void ModernSys::slotBelow()
00515 {
00516     setKeepBelow( !keepBelow());
00517     if (button[BtnBelow]) {
00518         button[BtnBelow]->turnOn(keepBelow());
00519         button[BtnBelow]->repaint(true);
00520     }
00521 }
00522 
00523         
00524 void ModernSys::slotShade()
00525 {
00526     setShade( !isSetShade());
00527 }
00528 
00529 void ModernSys::resizeEvent( QResizeEvent* )
00530 {
00531     recalcTitleBuffer();
00532     doShape();
00533 }
00534 
00535 void ModernSys::recalcTitleBuffer()
00536 {
00537     if(oldTitle == caption() && width() == titleBuffer.width())
00538         return;
00539 
00540     QFontMetrics fm(options()->font(true));
00541     titleBuffer.resize(width(), title_height+2);
00542     QPainter p;
00543     p.begin(&titleBuffer);
00544     if(aUpperGradient)
00545         p.drawTiledPixmap(0, 0, width(), title_height+2, *aUpperGradient);
00546     else
00547         p.fillRect(0, 0, width(), title_height+2,
00548                    options()->colorGroup(ColorTitleBar, true).
00549                    brush(QColorGroup::Button));
00550 
00551     QRect t = titlebar->geometry();
00552     t.setTop( 2 );
00553     t.setLeft( t.left() );
00554     t.setRight( t.right() - 2 );
00555 
00556     QRegion r(t.x(), 0, t.width(), title_height+2);
00557     r -= QRect(t.x()+((t.width()-fm.width(caption()))/2)-4,
00558                0, fm.width(caption())+8, title_height+2);
00559     p.setClipRegion(r);
00560     int i, ly;
00561     ly = (title_height % 3 == 0) ? 3 : 4;
00562     for(i=0; i < (title_height-2)/3; ++i, ly+=3){
00563         p.setPen(options()->color(ColorTitleBar, true).light(150));
00564         p.drawLine(0, ly, width()-1, ly);
00565         p.setPen(options()->color(ColorTitleBar, true).dark(120));
00566         p.drawLine(0, ly+1, width()-1, ly+1);
00567     }
00568     p.setClipRect(t);
00569     p.setPen(options()->color(ColorFont, true));
00570     p.setFont(options()->font(true));
00571 
00572     p.drawText(t.x()+((t.width()-fm.width(caption()))/2)-4,
00573                0, fm.width(caption())+8, title_height+2, AlignCenter, caption());
00574     p.setClipping(false);
00575     p.end();
00576     oldTitle = caption();
00577 }
00578 
00579 void ModernSys::captionChange()
00580 {
00581     recalcTitleBuffer();
00582     widget()->repaint( titlebar->geometry(), false );
00583 }
00584 
00585 void ModernSys::drawRoundFrame(QPainter &p, int x, int y, int w, int h)
00586 {
00587     kDrawRoundButton(&p, x, y, w, h,
00588                      options()->colorGroup(ColorFrame, isActive()), false);
00589 
00590 }
00591 
00592 void ModernSys::paintEvent( QPaintEvent* )
00593 {
00594     int hs = handle_size;
00595     int hw = handle_width;
00596 
00597     QPainter p( widget() );
00598     QRect t = titlebar->geometry();
00599 
00600     QBrush fillBrush(widget()->colorGroup().brush(QColorGroup::Background).pixmap() ?
00601                      widget()->colorGroup().brush(QColorGroup::Background) :
00602                      options()->colorGroup(ColorFrame, isActive()).
00603                      brush(QColorGroup::Button));
00604 
00605     p.fillRect(1, 16, width()-2, height()-16, fillBrush);
00606     p.fillRect(width()-6, 0, width()-1, height(), fillBrush);
00607 
00608     t.setTop( 2 );
00609     t.setLeft( t.left() );
00610     t.setRight( t.right() - 2 );
00611 
00612     int w = width() - hw; // exclude handle
00613     int h = height() - hw;
00614 
00615     // titlebar
00616     QColorGroup g = options()->colorGroup(ColorTitleBar, isActive());
00617     if(isActive()){
00618         p.drawPixmap(1, 1, titleBuffer, 0, 0, w-2, title_height+2);
00619     }
00620     else{
00621         if(iUpperGradient)
00622             p.drawTiledPixmap(1, 1, w-2, title_height+2, *iUpperGradient);
00623         else
00624             p.fillRect(1, 1, w-2, title_height+2, fillBrush);
00625         p.setPen(options()->color(ColorFont, isActive()));
00626         p.setFont(options()->font(isActive()));
00627         p.drawText(t, AlignCenter, caption() );
00628     }
00629 
00630     // titlebar highlight
00631     p.setPen(g.light());
00632     p.drawLine(1, 1, 1, title_height+3);
00633     p.drawLine(1, 1, w-3, 1);
00634     p.setPen(g.dark());
00635     p.drawLine(w-2, 1, w-2, title_height+3);
00636     p.drawLine(0, title_height+2, w-2, title_height+2);
00637 
00638     // frame
00639     g = options()->colorGroup(ColorFrame, isActive());
00640     p.setPen(g.light());
00641     p.drawLine(1, title_height+3, 1, h-2);
00642     p.setPen(g.dark());
00643     p.drawLine(2, h-2, w-2, h-2);
00644     p.drawLine(w-2, title_height+3, w-2, h-2);
00645     //p.drawPoint(w-3, title_height+3);
00646     //p.drawPoint(2, title_height+3);
00647 
00648     qDrawShadePanel(&p, border_width-1, title_height+3, w-2*border_width+2, h-title_height-border_width-2, g, true);
00649 
00650     if (show_handle) {
00651         p.setPen(g.dark());
00652         p.drawLine(width()-3, height()-hs-1, width()-3, height()-3);
00653         p.drawLine(width()-hs-1, height()-3, width()-3, height()-3);
00654 
00655         p.setPen(g.light());
00656         p.drawLine(width()-hw, height()-hs-1, width()-hw, height()-hw);
00657         p.drawLine(width()-hs-1, height()-hw, width()-hw, height()-hw);
00658         p.drawLine(width()-hw, height()-hs-1, width()-4, height()-hs-1);
00659         p.drawLine(width()-hs-1, height()-hw, width()-hs-1, height()-4);
00660 
00661         p.setPen(Qt::black);
00662         p.drawRect(0, 0, w, h);
00663 
00664         // handle outline
00665         p.drawLine(width()-hw, height()-hs, width(), height()-hs);
00666         p.drawLine(width()-2, height()-hs, width()-2, height()-2);
00667         p.drawLine(width()-hs, height()-2, width()-2, height()-2);
00668         p.drawLine(width()-hs, height()-hw, width()-hs, height()-2);
00669     } else {
00670         p.setPen(Qt::black);
00671         p.drawRect(0, 0, w, h);
00672     }
00673 }
00674 
00675 void ModernSys::doShape()
00676 {
00677     int hs = handle_size;
00678     int hw = handle_width;
00679     QRegion mask;
00680     mask += QRect(0, 0, width()-hw, height()-hw);
00681     //single points
00682     mask -= QRect(0, 0, 1, 1);
00683     mask -= QRect(width()-hw-1, 0, 1, 1);
00684     mask -= QRect(0, height()-hw-1, 1, 1);
00685 
00686     if (show_handle) {
00687         mask += QRect(width()-hs, height()-hs, hs-1, hs-1);
00688         mask -= QRect(width()-2, height()-2, 1, 1);
00689         mask -= QRect(width()-2, height()-hs, 1, 1);
00690         mask -= QRect(width()-hs, height()-2, 1, 1);
00691     } else
00692         mask -= QRect(width()-1, height()-1, 1, 1);
00693 
00694     setMask(mask);
00695 }
00696 
00697 void ModernSys::showEvent(QShowEvent *)
00698 {
00699     doShape();
00700     widget()->repaint();
00701 }
00702 
00703 void ModernSys::mouseDoubleClickEvent( QMouseEvent * e )
00704 {
00705     if (e->button() == LeftButton && titlebar->geometry().contains( e->pos() ) )
00706         titlebarDblClickOperation();
00707 }
00708 
00709 void ModernSys::desktopChange()
00710 {
00711     bool sticky_on = isOnAllDesktops();
00712     button[BtnSticky]->setBitmap(sticky_on ? unsticky_bits : sticky_bits);
00713     QToolTip::remove( button[BtnSticky] );
00714     QToolTip::add( button[BtnSticky], sticky_on ? i18n("Unsticky") : i18n("Sticky"));
00715 }
00716 
00717 void ModernSys::maximizeChange()
00718 {
00719     bool m = ( maximizeMode() == MaximizeFull );
00720     button[BtnMaximize]->setBitmap(m ? minmax_bits : maximize_bits);
00721     QToolTip::remove( button[BtnMaximize] );
00722     QToolTip::add( button[BtnMaximize], m ? i18n("Restore") : i18n("Maximize"));
00723 }
00724 
00725 void ModernSys::activeChange()
00726 {
00727     widget()->repaint(false);
00728     for (int i = 0; i < 5; button[i++]->reset());
00729 }
00730 
00731 
00732 void ModernSys::keepAboveChange( bool above )
00733 {
00734     if (button[BtnAbove]) {
00735         button[BtnAbove]->setBitmap( above ? above_on_bits : above_off_bits );
00736         button[BtnAbove]->repaint(false);
00737     }
00738 }
00739         
00740 void ModernSys::keepBelowChange( bool below )
00741 {
00742     if (button[BtnBelow]) {
00743         button[BtnBelow]->setBitmap( below ? below_on_bits : below_off_bits );
00744         button[BtnBelow]->repaint(false);
00745     }
00746 }
00747 
00748 
00749 ModernSys::Position ModernSys::mousePosition( const QPoint& p) const
00750 {
00751     Position m = KDecoration::mousePosition( p );
00752 
00753     const int range = 14 + 3*border_width/2;
00754     const int border = show_handle ? handle_width + border_width : border_width;
00755     const int range2 = show_handle ? handle_width + border_width : range;
00756     const int range3 = show_handle ? handle_width + range : range;
00757 
00758     if ( ( p.x() > border_width && p.x() < width() - border )
00759          && ( p.y() > 4 && p.y() < height() - border ) )
00760         m = PositionCenter;
00761     else if ( p.y() <= range && p.x() <= range)
00762         m = PositionTopLeft;
00763     else if ( p.y() >= height()-range2 && p.x() >= width()-range2)
00764         m = PositionBottomRight;
00765     else if ( p.y() >= height()-range3 && p.x() <= range)
00766         m = PositionBottomLeft;
00767     else if ( p.y() <= range && p.x() >= width()-range3)
00768         m = PositionTopRight;
00769     else if ( p.y() <= 4 )
00770         m = PositionTop;
00771     else if ( p.y() >= height()-border )
00772         m = PositionBottom;
00773     else if ( p.x() <= border_width )
00774         m = PositionLeft;
00775     else if ( p.x() >= width()-border )
00776         m = PositionRight;
00777     else
00778         m = PositionCenter;
00779 
00780     return m;
00781 }
00782 
00783 void ModernSys::resize( const QSize& s )
00784 {
00785     widget()->resize( s );
00786 }
00787 
00788 void ModernSys::iconChange()
00789 {
00790 }
00791 
00792 void ModernSys::shadeChange()
00793 {
00794     if (button[BtnShade]) {
00795         bool on = isSetShade();
00796         button[BtnShade]->turnOn(on);
00797         button[BtnShade]->setBitmap(isSetShade() ? shade_on_bits : shade_off_bits );
00798         button[BtnShade]->repaint(false);
00799         QToolTip::remove( button[BtnShade] );
00800         QToolTip::add( button[BtnShade], on ? i18n("Unshade") : i18n("Shade"));
00801     }
00802 }
00803 
00804 QSize ModernSys::minimumSize() const
00805 {
00806     return QSize( 50, 50 ); // FRAME
00807 }
00808 
00809 void ModernSys::borders( int& left, int& right, int& top, int& bottom ) const
00810 {
00811     bool reverse = QApplication::reverseLayout();
00812     left = border_width + (reverse ? handle_width : 0);
00813     right = border_width + (reverse ? 0 : handle_width);
00814     top = 4 + titlebar->geometry().height(); // FRAME is this ok?
00815     bottom = border_width + handle_width;
00816 // FRAME this below needs doShape() changes
00817 //    if( isShade())
00818 //        bottom = 0;
00819 //    if( ( maximizeMode() & MaximizeHorizontal ) && !options()->moveResizeMaximizedWindows())
00820 //        left = right = 0;
00821 //    if( ( maximizeMode() & MaximizeVertical ) && !options()->moveResizeMaximizedWindows())
00822 //        bottom = 0;
00823 }
00824 
00825 bool ModernSys::eventFilter( QObject* o, QEvent* e )
00826 {
00827     if( o != widget())
00828     return false;
00829     switch( e->type())
00830     {
00831     case QEvent::Resize:
00832         resizeEvent( static_cast< QResizeEvent* >( e ));
00833         return true;
00834     case QEvent::Paint:
00835         paintEvent( static_cast< QPaintEvent* >( e ));
00836         return true;
00837     case QEvent::MouseButtonDblClick:
00838         mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ));
00839         return true;
00840     case QEvent::MouseButtonPress:
00841         processMousePressEvent( static_cast< QMouseEvent* >( e ));
00842         return true;
00843     case QEvent::Show:
00844         showEvent( static_cast< QShowEvent* >( e ));
00845         return true;
00846     default:
00847         break;
00848     }
00849     return false;
00850 }
00851 
00852 ModernSysFactory::ModernSysFactory()
00853 {
00854     button_pattern = new QString;
00855     read_config();
00856     create_pixmaps();
00857 }
00858 
00859 ModernSysFactory::~ModernSysFactory()
00860 {
00861     ModernSystem::delete_pixmaps();
00862     delete ModernSystem::button_pattern;
00863 }
00864 
00865 KDecoration* ModernSysFactory::createDecoration( KDecorationBridge* b )
00866 {
00867     return(new ModernSys(b, this));
00868 }
00869 
00870 bool ModernSysFactory::reset( unsigned long changed )
00871 {
00872     bool ret = read_config();
00873     if( changed & (SettingColors | SettingBorder) )
00874     {
00875         delete_pixmaps();
00876         create_pixmaps();
00877     }
00878     if( ret )
00879         return true;
00880     else
00881     {
00882         resetDecorations( changed );
00883         return false; // no recreating of decorations
00884     }
00885 }
00886 
00887 bool ModernSysFactory::supports( Ability ability )
00888 {
00889     switch( ability )
00890     {
00891         case AbilityAnnounceButtons:
00892         case AbilityButtonOnAllDesktops:
00893         case AbilityButtonSpacer:
00894         case AbilityButtonHelp:
00895         case AbilityButtonMinimize:
00896         case AbilityButtonMaximize:
00897         case AbilityButtonClose:
00898         case AbilityButtonAboveOthers:
00899         case AbilityButtonBelowOthers:
00900         case AbilityButtonShade:
00901             return true;
00902         default:
00903             return false;
00904     };
00905 }
00906 
00907 }
00908 
00909 // KWin extended plugin interface
00910 extern "C" KDE_EXPORT KDecorationFactory* create_factory()
00911 {
00912     return new ModernSystem::ModernSysFactory();
00913 }
00914 
00915 
00916 
00917 #include "modernsys.moc"
00918 // vim:ts=4:sw=4
KDE Logo
This file is part of the documentation for kwin Library Version 3.4.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jun 14 16:47:03 2006 by doxygen 1.4.4 written by Dimitri van Heesch, © 1997-2003