Back to index

kdeartwork  4.3.2
cdeclient.cpp
Go to the documentation of this file.
00001 /*
00002  *     $Id: cdeclient.cpp 922431 2009-02-07 01:12:28Z schwarzer $
00003  *
00004  *     CDE KWin client - emulates the look and feel
00005  *     of dtwm, the CDE window manager.
00006  *
00007  *     Copyright (c) 2000-2001, 2002
00008  *            Chris Lee       <lee@azsites.com>
00009  *            Lennart Kudling <kudling@kde.org>
00010  *            Fredrik Höglund <fredrik@kde.org>
00011  *
00012  *     Copyright (c) 2003,2004
00013  *            Luciano Montanaro <mikelima@cirulla.net>
00014  *
00015  *     Originally based on the KStep client.
00016  *
00017  *     Distributed under the terms of the BSD license.
00018  */
00019 
00020 #include "cdeclient.h"
00021 #include <qdatetime.h>
00022 #include <qlayout.h>
00023 #include <q3button.h>
00024 #include <qcursor.h>
00025 #include <qlabel.h>
00026 #include <qtooltip.h>
00027 #include <qdrawutil.h>
00028 #include <qpainter.h>
00029 #include <qapplication.h>
00030 //Added by qt3to4:
00031 #include <QPaintEvent>
00032 #include <Q3PointArray>
00033 #include <QEvent>
00034 #include <QBoxLayout>
00035 #include <Q3ValueList>
00036 #include <QShowEvent>
00037 #include <QVBoxLayout>
00038 #include <QResizeEvent>
00039 #include <QMouseEvent>
00040 #include <klocale.h>
00041 #include <kconfig.h>
00042 
00043 extern "C" KDE_EXPORT KDecorationFactory* create_factory()
00044 {
00045     return new CDE::CdeClientFactory();
00046 }
00047 
00048 namespace CDE {
00049 
00050 static int s_frameWidth = 5;
00051 static int s_buttonSize = 19;
00052 static bool titlebarButtonMode = true;
00053 static bool coloredFrame = true;
00054 static Qt::AlignmentFlags textAlignment = Qt::AlignHCenter;
00055 
00056 // Precomputed border sizes for accessibility
00057 // The sizes are applied for tiny -> normal -> large -> very large -> huge ->
00058 // very huge -> oversized
00059 static const int borderSizes[] = { 4, 6, 9, 12, 18, 26, 42 };
00060 
00061 // Parameters needed to draw the widgets (offsets from the border)
00062 static int s_o1 = 4;
00063 static int s_o2 = 7;
00064 static int s_w1 = 11;
00065 static int s_w2 = 5;
00066 
00067 // These are the line segments for the X on the close button
00068 
00069 static const int NUM_CLOSEL_COORDS = 2 * 14;
00070 static const QCOORD closeLLinesTemplate[NUM_CLOSEL_COORDS] =
00071     { 14,3, 12,3,  12,3, 9,6,  5,3, 3,3,  3,3, 3,5,
00072       3,5, 6,8, 6,9, 3,12,  3,12, 3,14 };
00073 
00074 static const int NUM_CLOSED_COORDS = 2 * 18;
00075 static const QCOORD closeDLinesTemplate[NUM_CLOSED_COORDS] =
00076     { 5,3, 8,6,  14,4, 14,5,  14,5, 11,8,  11,9, 14,12,  14,12, 14,14,
00077       14,14, 12,14,  12,14, 9,11,  8,11, 5,14,  5,14, 4,14 };
00078 
00079 static QCOORD closeLLines[NUM_CLOSEL_COORDS];
00080 
00081 static QCOORD closeDLines[NUM_CLOSED_COORDS];
00082 
00083 // These are the line segments for the ? on the help button
00084 static const int NUM_HELPL_COORDS = 2 * 16;
00085 static const QCOORD helpLLinesTemplate[NUM_HELPL_COORDS] =
00086     { 4,6, 4,5,  4,5, 6,3,  6,3, 9,3,  10,3, 11,4,
00087       9,7, 7,9,  7,9, 7,10,  7,14, 7,13,  8,12, 9,12  };
00088 
00089 static const int NUM_HELPD_COORDS = 2 * 14;
00090 static const QCOORD helpDLinesTemplate[NUM_HELPD_COORDS] =
00091     {  5,7, 8,6,  12,5, 12,8,  12,8, 10,10,  10,10, 10,11,
00092        10,11, 8,11,  10,14, 10,13,  9,15, 8,15 };
00093 
00094 static QCOORD helpLLines[NUM_HELPL_COORDS];
00095 
00096 static QCOORD helpDLines[NUM_HELPD_COORDS];
00097 
00098 
00099 // This question mark is taller than the one above and
00100 // is positioned one pixel higher on the button
00101 /*
00102 static const QCOORD helpLLines[] =
00103     { 4,5, 4,4,  4,4, 6,2,  6,2, 9,2,  10,2, 11,3,
00104       9,6, 7,8,  7,9, 7,10,  7,13, 8,12,  8,12, 9,12  };
00105 
00106 static const QCOORD helpDLines[] =
00107     {  5,6, 8,5,  12,4, 12,7,  12,7, 10,9,  10,10, 10,11,
00108        10,11, 8,11,  10,13, 9,14,  9,14, 8,14 };
00109 */
00110 // Same as the one above but with a larger dot under
00111 // the question mark
00112 /*
00113 static const QCOORD helpLLines[] =
00114     { 4,5, 4,4,  4,4, 6,2,  6,2, 9,2,  10,2, 11,3,
00115       9,6, 7,8,  7,9, 7,10,  7,14, 7,13,  8,12, 9,12  };
00116 
00117 static const QCOORD helpDLines[] =
00118     {  5,6, 8,5,  12,4, 12,7,  12,7, 10,9,  10,10, 10,11,
00119        10,11, 8,11,  10,13, 10,14,  9,15, 8,15 };
00120 */
00121 
00122 static inline const KDecorationOptions* options()
00123 {
00124     return KDecoration::options();
00125 }
00126 
00127 static void fixColorGroup(QColorGroup & colorGroup)
00128 {
00129     QColor light = colorGroup.light();
00130 
00131     int hue, saturation, value;
00132 
00133     light.hsv(&hue, &saturation, &value);
00134 
00135     if (value < 128)
00136     {
00137       light.setHsv(hue, saturation, 128);
00138       colorGroup.setColor(QPalette::Light, light);
00139     }
00140 
00141     QColor dark = colorGroup.dark();
00142 
00143     dark.hsv(&hue, &saturation, &value);
00144 
00145     if (value < 84)
00146     {
00147       dark.setHsv(hue, saturation, 84);
00148       colorGroup.setColor(QPalette::Dark, dark);
00149     }
00150 }
00151 
00152 // scaling helper function used to scale the close 'X' glyph
00153 
00154 static int scaleCoord(int c)
00155 {
00156     if (c < 6) return c;
00157     if (c <= 11) return c + (s_buttonSize - 19) / 2;
00158     return c + s_buttonSize - 19;
00159 }
00160 
00161 static void readConfig(CdeClientFactory *f)
00162 {
00163     KConfig conf( "kwincderc" );
00164 
00165     conf.setGroup("General");
00166     coloredFrame = conf.readEntry( "UseTitleBarBorderColors", true );
00167     titlebarButtonMode = conf.readEntry( "TitlebarButtonMode", true );
00168 
00169     QString value = conf.readEntry( "TextAlignment", "AlignHCenter" );
00170     if ( value == "AlignLeft" )
00171        textAlignment = Qt::AlignLeft;
00172     else if ( value == "AlignHCenter" )
00173        textAlignment = Qt::AlignHCenter;
00174     else if ( value == "AlignRight" )
00175        textAlignment = Qt::AlignRight;
00176 
00177 
00178     // find preferred border size
00179     int i = options()->preferredBorderSize(f);
00180     if (i >= 0 && i <= 6) s_frameWidth = borderSizes[i];
00181 
00182     // Do not allow malicious users or corrupt config files to
00183     // go past the domain of the valid border sizes.
00184 
00185     // Size limit increased for accessability. LM
00186     if (s_frameWidth < 0)  s_frameWidth = 0;
00187     if (s_frameWidth > 30) s_frameWidth = 30;
00188 
00189     // Force button size to be in a reasonable range.
00190     // If the frame width is large, the button size must be large too.
00191     s_buttonSize = QFontMetrics(options()->font( true )).height() + 2;
00192     if (s_buttonSize < 19) s_buttonSize = 19;
00193     if (s_buttonSize < s_frameWidth) s_buttonSize = s_frameWidth;
00194     s_buttonSize |= 1; // Be sure the button size is odd.
00195 
00196     // Calculate widths and offsets for the button icons
00197     s_o1 = s_buttonSize * 4 / 19;
00198     s_o2 = s_buttonSize * 7 / 19;
00199     s_w1 = s_buttonSize - 2 * s_o1;
00200     s_w2 = s_buttonSize - 2 * s_o2;
00201 
00202     // Copy and scale the close icon
00203     int offset = (s_buttonSize - 19) / 2;
00204     for (int i = 0; i < NUM_CLOSEL_COORDS; i++) {
00205        closeLLines[i] = scaleCoord(closeLLinesTemplate[i]);
00206     }
00207     for (int i = 0; i < NUM_CLOSED_COORDS; i++) {
00208        closeDLines[i] = scaleCoord(closeDLinesTemplate[i]);
00209     }
00210     // Copy and center the help icon
00211     for (int i = 0; i < NUM_HELPL_COORDS; i++) {
00212        helpLLines[i] = helpLLinesTemplate[i] + offset;
00213     }
00214     for (int i = 0; i < NUM_HELPD_COORDS; i++) {
00215        helpDLines[i] = helpDLinesTemplate[i] + offset;
00216     }
00217 }
00218 
00219 // ---------------------------------------
00220 
00221 CdeClientFactory::CdeClientFactory()
00222 {
00223     CDE::readConfig(this);
00224 }
00225 
00226 CdeClientFactory::~CdeClientFactory()
00227 {
00228 }
00229 
00230 KDecoration *CdeClientFactory::createDecoration(KDecorationBridge *b)
00231 {
00232     return new CdeClient(b, this);
00233 }
00234 
00235 bool CdeClientFactory::reset(unsigned long /*changed*/)
00236 {
00237     // TODO Do not recreate decorations if it is not needed. Look at
00238     // ModernSystem for how to do that
00239     // For now just return true.
00240     CDE::readConfig(this);
00241     return true;
00242 }
00243 
00244 bool CdeClientFactory::supports( Ability ability )
00245 {
00246     switch( ability )
00247     {
00248         case AbilityAnnounceButtons:
00249         case AbilityButtonMenu:
00250         case AbilityButtonOnAllDesktops:
00251         case AbilityButtonHelp:
00252         case AbilityButtonMinimize:
00253         case AbilityButtonMaximize:
00254         case AbilityButtonClose:
00255             return true;
00256         default:
00257             return false;
00258     };
00259 }
00260 
00261 Q3ValueList< CdeClientFactory::BorderSize >
00262 CdeClientFactory::borderSizes() const
00263 {
00264     // the list must be sorted
00265     return Q3ValueList< BorderSize >() << BorderTiny << BorderNormal <<
00266        BorderLarge << BorderVeryLarge <<  BorderHuge <<
00267        BorderVeryHuge << BorderOversized;
00268 }
00269 
00270 // ---------------------------------------
00271 
00272 CdeClient::CdeClient(KDecorationBridge *b, KDecorationFactory *f)
00273     : KDecoration(b, f)
00274 {
00275 }
00276 
00277 void CdeClient::init()
00278 {
00279     createMainWidget(WStaticContents | WResizeNoErase | WRepaintNoErase);
00280     widget()->installEventFilter(this);
00281 
00282     widget()->setBackgroundMode(NoBackground);
00283 
00284     mainLayout = new QVBoxLayout(widget());
00285     QBoxLayout* windowLayout = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
00286     titleLayout = new QBoxLayout(0, QBoxLayout::LeftToRight, 0, 0, 0);
00287 
00288     // TODO Check if this stuff can be simplified.
00289     // Border sizes are from a fixed set now.
00290     if ( s_frameWidth > 1 )
00291     {
00292        // the style normally draws a black frame around the window, so we
00293        // need 1 line of space for that in addition to the normal window frame
00294        mainLayout->setMargin( s_frameWidth+1 );
00295     }
00296     else
00297     {
00298        // but if the frame is set to just 1 pixel we just draw the black frame
00299        // instead of the normal window frame, so no extra space is needed. if
00300        // it is 0 we don't draw anything.
00301        mainLayout->setMargin( s_frameWidth );
00302     }
00303 
00304     mainLayout->addLayout( titleLayout );
00305     mainLayout->addLayout( windowLayout, 1 );
00306 
00307     if (isPreview())
00308         windowLayout->addWidget(new QLabel(i18n(
00309                      "<center><b>CDE preview</b></center>"), widget()), 1);
00310     else
00311        windowLayout->addItem( new QSpacerItem( 0, 0 ));
00312 
00313     for ( int i=0; i < BtnCount; i++ )
00314         button[i] = NULL;
00315 
00316     addClientButtons( options()->titleButtonsLeft() );
00317 
00318     titlebar = new QSpacerItem( 10, 16, QSizePolicy::Expanding, QSizePolicy::Minimum );
00319     titleLayout->addItem( titlebar );
00320 
00321     addClientButtons( options()->titleButtonsRight() );
00322 
00323     titlebarPressed = false;
00324     closing = false;
00325 }
00326 
00327 void CdeClient::addClientButtons( const QString& s )
00328 {
00329     if ( s.length() > 0 )
00330         for ( unsigned int i = 0; i < s.length(); i++ )
00331         {
00332             switch( s[i].latin1() )
00333             {
00334                 // Menu button
00335                 case 'M':
00336                     if ( ! button[BtnMenu] )
00337                     {
00338                         button[BtnMenu] = new CdeButton( this, "menu", BtnMenu, i18n("Menu"), Qt::LeftButton|Qt::RightButton );
00339                         connect( button[BtnMenu], SIGNAL(pressed()), SLOT(menuButtonPressed()) );
00340                         connect( button[BtnMenu], SIGNAL(released()), SLOT(menuButtonReleased()) );
00341                         titleLayout->addWidget( button[BtnMenu] );
00342                     }
00343                     break;
00344 
00345                 //Help button
00346                 case 'H':
00347                     if ( providesContextHelp() && (! button[BtnHelp] ) )
00348                     {
00349                         button[BtnHelp] = new CdeButton( this, "help", BtnHelp, i18n("Help") );
00350                         connect(button[BtnHelp],
00351                             SIGNAL(clicked()), SLOT(showContextHelp()));
00352                         titleLayout->addWidget( button[BtnHelp] );
00353                     }
00354                     break;
00355 
00356               //Minimize button
00357                 case 'I':
00358                     if ( (! button[BtnIconify] ) && isMinimizable() )
00359                     {
00360                         button[BtnIconify] = new CdeButton( this, "iconify", BtnIconify, i18n("Minimize") );
00361                         connect(button[BtnIconify],
00362                             SIGNAL(clicked()), SLOT(minimize()));
00363                         titleLayout->addWidget( button[BtnIconify] );
00364                     }
00365                     break;
00366 
00367                 // Maximize button
00368                 case 'A':
00369                     if ( (! button[BtnMax] ) && isMaximizable() )
00370                     {
00371                         button[BtnMax] = new CdeButton(this, "maximize", BtnMax, i18n("Maximize"), Qt::LeftButton|Qt::MidButton|Qt::RightButton);
00372                         connect(button[BtnMax], SIGNAL(clicked()),
00373                             SLOT(maximizeButtonClicked()));
00374                         titleLayout->addWidget( button[BtnMax] );
00375                     }
00376                     break;
00377 
00378                 // Close button
00379                 case 'X':
00380                     if ( !button[BtnClose] && isCloseable())
00381                     {
00382                         button[BtnClose] = new CdeButton(this, "close", BtnClose, i18n("Close"));
00383                         connect( button[BtnClose], SIGNAL( clicked()), SLOT(closeWindow()) );
00384                         titleLayout->addWidget( button[BtnClose] );
00385                     }
00386               // Add onAlldesktops button and spacers
00387             }
00388         }
00389 
00390 }
00391 
00392 void CdeClient::captionChange()
00393 {
00394     widget()->repaint(titlebar->geometry(), false);
00395 }
00396 
00397 void CdeClient::activeChange()
00398 {
00399     for ( int i=0; i < BtnCount; i++ )
00400        if ( button[i] ) button[i]->reset();
00401 
00402     widget()->repaint(false);
00403 }
00404 
00405 void CdeClient::maximizeChange()
00406 {
00407     if ( button[BtnMax] ) {
00408        bool m = maximizeMode() == MaximizeFull;
00409        QToolTip::remove(button[BtnMax]);
00410        button[BtnMax]->setToolTip( m ? i18n("Restore") : i18n("Maximize"));
00411        button[BtnMax]->repaint();
00412     }
00413 }
00414 
00415 void CdeClient::iconChange()
00416 {
00417 }
00418 
00419 void CdeClient::shadeChange()
00420 {
00421 }
00422 
00423 void CdeClient::showEvent(QShowEvent *)
00424 {
00425     widget()->repaint();
00426 }
00427 
00428 void CdeClient::desktopChange()
00429 {
00430     // Nothing to do yet
00431 }
00432 
00433 QSize CdeClient::minimumSize() const
00434 {
00435     return QSize(2 * (s_buttonSize + s_frameWidth),
00436                 2 * s_frameWidth + s_buttonSize);
00437 }
00438 
00439 void CdeClient::resize(const QSize& s)
00440 {
00441     widget()->resize(s);
00442 }
00443 
00444 void CdeClient::maximizeButtonClicked()
00445 {
00446     if (button[BtnMax]) {
00447        maximize(button[BtnMax]->lastButton());
00448     }
00449 }
00450 
00451 void CdeClient::menuButtonPressed()
00452 {
00453     static QTime* t = NULL;
00454     static CdeClient* lastClient = NULL;
00455     if( t == NULL )
00456        t = new QTime;
00457     bool dbl = ( lastClient == this && t->elapsed() <= QApplication::doubleClickInterval());
00458     lastClient = this;
00459     t->start();
00460     if( !dbl )
00461     {
00462        QRect menuRect = button[BtnMenu]->rect();
00463         QPoint menuTop = button[BtnMenu]->mapToGlobal(menuRect.topLeft());
00464         QPoint menuBottom = 
00465            button[BtnMenu]->mapToGlobal(menuRect.bottomRight());
00466         KDecorationFactory* f = factory();
00467         showWindowMenu(QRect(menuTop, menuBottom));
00468         if( !f->exists( this )) // 'this' was deleted
00469             return;
00470        button[BtnMenu]->setDown(false);
00471     }
00472     else
00473        closing = true;
00474 }
00475 
00476 void CdeClient::menuButtonReleased()
00477 {
00478     if( closing )
00479         closeWindow();
00480 }
00481 
00482 void CdeClient::resizeEvent( QResizeEvent* e)
00483 {
00484     if (widget()->isVisibleToTLW()) {
00485         widget()->update();
00486         int dx = 0;
00487         int dy = 0;
00488 
00489            if ( e->oldSize().width() != width() )
00490               dx = 32 + qAbs( e->oldSize().width() -  width() );
00491 
00492            if ( e->oldSize().height() != height() )
00493               dy = 8 + qAbs( e->oldSize().height() -  height() );
00494 
00495            if ( dy )
00496               widget()->update( 0, height() - dy + 1, width(), dy );
00497 
00498         if ( dx )
00499         {
00500            widget()->update( width() - dx + 1, 0, dx, height() );
00501            widget()->update( QRect( QPoint(4,4),
00502            titlebar->geometry().bottomLeft() - QPoint(1,0) ) );
00503            widget()->update(QRect(titlebar->geometry().topRight(),
00504                      QPoint(width() - 4, titlebar->geometry().bottom())));
00505 
00506            // Titlebar needs no paint event
00507            QApplication::postEvent( this, new QPaintEvent( titlebar->geometry(), false ) );
00508        }
00509     }
00510 }
00511 
00512 void CdeClient::paintEvent( QPaintEvent* )
00513 {
00514     QPainter p(widget());
00515 
00516     QColorGroup colorGroup;
00517 
00518     if ( coloredFrame )
00519        colorGroup = options()->colorGroup( KDecoration::ColorTitleBar, isActive() );
00520     else
00521        colorGroup = options()->colorGroup( KDecoration::ColorFrame, isActive() );
00522 
00523     fixColorGroup( colorGroup );
00524 
00525     QRect trect = titlebar->geometry();
00526     QRect mrect = widget()->rect();
00527 
00528     if ( s_frameWidth > 0 )
00529     {
00530        // draw black frame:
00531        p.setPen( Qt::black );
00532        p.drawRect( mrect );
00533     }
00534 
00535     p.setPen( Qt::NoPen );
00536     p.setBrush( colorGroup.background() );
00537 
00538 
00539     if ( s_frameWidth > 1 )
00540     {
00541        bool shaded = isShade();
00542        int longSide = s_frameWidth + s_buttonSize;
00543 
00544        // draw frame-background:
00545        p.drawRect( 1, 1,
00546               mrect.width() - 2, s_frameWidth );
00547        p.drawRect( 1, mrect.height() - s_frameWidth - 1,
00548               mrect.width() - 2, s_frameWidth );
00549        p.drawRect( 1, s_frameWidth + 1,
00550               s_frameWidth, mrect.height() - 2*s_frameWidth - 2 );
00551        p.drawRect( mrect.width() - s_frameWidth - 1, s_frameWidth + 1,
00552               s_frameWidth, mrect.height() - 2*s_frameWidth - 2 );
00553 
00554        if ( ! shaded )
00555        {
00556            // draw left  and right frames:
00557            qDrawShadePanel( &p, 1, longSide + 1,
00558               s_frameWidth, mrect.height() - 2 * (longSide + 1),
00559               colorGroup );
00560 
00561            qDrawShadePanel( &p, mrect.width() - s_frameWidth - 1, longSide + 1,
00562               s_frameWidth, mrect.height() - 2 * (longSide + 1),
00563               colorGroup );
00564        }
00565 
00566        // draw top and bottom frames:
00567        qDrawShadePanel( &p, longSide + 1, 1,
00568            mrect.width() - 2 * (longSide + 1), s_frameWidth,
00569            colorGroup );
00570 
00571        qDrawShadePanel( &p, longSide + 1, mrect.height() - s_frameWidth - 1,
00572            mrect.width() - 2 * (longSide + 1), s_frameWidth,
00573            colorGroup );
00574 
00575        // draw light corner parts:
00576        p.setPen( colorGroup.light() );
00577 
00578        // tl corner:
00579        p.drawLine( 1, 1, longSide - 1, 1 );
00580        p.drawLine( 1, 1, 1, longSide - 1 );
00581 
00582        // tr corner:
00583        p.drawLine( mrect.width() - 3, 1, mrect.width() - longSide - 1, 1 );
00584        p.drawLine( mrect.width() - longSide - 1, 1,
00585            mrect.width() - longSide - 1, s_frameWidth - 1 );
00586        p.drawLine( mrect.width() - s_frameWidth - 1, s_frameWidth,
00587            mrect.width() - s_frameWidth - 1, longSide - 1 );
00588 
00589        // br corner:
00590        if ( !shaded )
00591        {
00592            p.drawLine( mrect.width() - 3, mrect.height() - longSide - 1,
00593               mrect.width() - s_frameWidth - 1, mrect.height() - longSide - 1 );
00594        }
00595        p.drawLine( mrect.width() - s_frameWidth - 1, mrect.height() - longSide,
00596            mrect.width() - s_frameWidth - 1, mrect.height() - s_frameWidth - 1 );
00597        p.drawLine( mrect.width() - s_frameWidth - 2, mrect.height() - s_frameWidth - 1,
00598            mrect.width() - longSide - 1, mrect.height() - s_frameWidth - 1 );
00599        p.drawLine( mrect.width() - longSide - 1, mrect.height() - s_frameWidth,
00600            mrect.width() - longSide - 1, mrect.height() - 2 );
00601 
00602        // bl corner:
00603        if ( !shaded )
00604        {
00605            p.drawLine( s_frameWidth-1, mrect.height() - longSide - 1,
00606               2, mrect.height() - longSide - 1 );
00607        }
00608        p.drawLine( 1, mrect.height() - longSide - 1,
00609            1, mrect.height() - 3 );
00610        p.drawLine( longSide - 1, mrect.height() - s_frameWidth - 1,
00611            s_frameWidth + 1, mrect.height() - s_frameWidth - 1 );
00612 
00613        // draw dark corner parts:
00614        p.setPen( colorGroup.dark() );
00615 
00616        // tl corner:
00617        if ( !shaded )
00618            p.drawLine( 1, longSide, s_frameWidth, longSide );
00619        p.drawLine( s_frameWidth, longSide - 1, s_frameWidth, s_frameWidth );
00620        p.drawLine( s_frameWidth + 1, s_frameWidth, longSide, s_frameWidth );
00621        p.drawLine( s_frameWidth + s_buttonSize, s_frameWidth, longSide, 1 );
00622 
00623        // tr corner:
00624        p.drawLine( mrect.width() - longSide - 1, s_frameWidth,
00625            mrect.width() - s_frameWidth - 2, s_frameWidth );
00626        if ( !shaded )
00627        {
00628            p.drawLine( mrect.width() - s_frameWidth - 1, longSide,
00629               mrect.width() - 2, longSide );
00630        }
00631        p.drawLine( mrect.width() - 2, longSide, mrect.width() - 2, 1 );
00632 
00633        // br corner:
00634        p.drawLine( mrect.width() - longSide - 1, mrect.height() - 2,
00635            mrect.width() - 3, mrect.height() - 2 );
00636        p.drawLine( mrect.width() - 2, mrect.height() - 2,
00637            mrect.width() - 2, mrect.height() - longSide - 2 );
00638 
00639        // bl corner:
00640        p.drawLine( 1, mrect.height() - 2,
00641               longSide, mrect.height() - 2 );
00642        p.drawLine( s_frameWidth + s_buttonSize, mrect.height() - 3,
00643               longSide, mrect.height() - s_frameWidth - 1 );
00644        p.drawLine( s_frameWidth, mrect.height() - s_frameWidth - 1,
00645               s_frameWidth, mrect.height() - longSide - 1 );
00646     }
00647 
00648 
00649     p.setPen( Qt::NoPen );
00650 
00651     if ( !coloredFrame )
00652     {
00653        colorGroup = options()->colorGroup( KDecoration::ColorTitleBar, isActive() );
00654        fixColorGroup( colorGroup );
00655        p.setBrush( colorGroup.background() );
00656     }
00657 
00658     // draw titlebar:
00659     p.drawRect( trect );
00660     qDrawShadePanel( &p, trect, colorGroup, titlebarPressed );
00661 
00662     // draw caption:
00663     if ( titlebarPressed ) // move the caption right and down if the titlebar is pressed
00664        trect.moveBy( 1,1 ); // Note: the real Mwm doesn't actually do this
00665 
00666     p.setFont( options()->font( true ) );
00667     p.setPen( options()->color( KDecoration::ColorFont, isActive() ) );
00668     if ( p.fontMetrics().width( caption() ) > trect.width() - 6 )
00669     {
00670        // left align the text if it is too wide to fit in the titlebar
00671        p.drawText( trect.x() + 3, trect.y(),
00672            trect.width() - 6, trect.height(),
00673            AlignLeft | AlignVCenter, caption() );
00674     }
00675     else
00676     {
00677        // otherwise we'll draw it according to the user settings
00678        p.drawText( trect.x() + 3, trect.y(),
00679            trect.width() - 6, trect.height(),
00680            textAlignment | AlignVCenter, caption() );
00681     }
00682 
00683     // Draw a line behind the wrapped window to prevent having
00684     // unpainted areas when we're shaded.
00685     p.setPen( colorGroup.dark() );
00686     p.drawLine(s_frameWidth + 1, mrect.height() - s_frameWidth - 2,
00687                mrect.width() - s_frameWidth - 2, mrect.height() - s_frameWidth - 2);
00688 
00689 }
00690 
00691 KDecoration::Position CdeClient::mousePosition( const QPoint& p ) const
00692 {
00693     const int range = s_frameWidth + s_buttonSize;
00694     const int border = s_frameWidth + 1;
00695 
00696     Position m = PositionCenter;
00697 
00698     if ((p.x() > border && p.x() < width() - border)
00699          && (p.y() > border && p.y() < height() - border))
00700         return PositionCenter;
00701 
00702     if (p.y() < range && p.x() <= range)
00703         m = PositionTopLeft;
00704     else if (p.y() >= height() - range && p.x() >= width() - range)
00705         m = PositionBottomRight;
00706     else if (p.y() >= height()-range && p.x() <= range)
00707         m = PositionBottomLeft;
00708     else if (p.y() < range && p.x() >= width() - range)
00709         m = PositionTopRight;
00710     else if (p.y() < border)
00711         m = PositionTop;
00712     else if (p.y() >= height() - border)
00713         m = PositionBottom;
00714     else if (p.x() <= border)
00715         m = PositionLeft;
00716     else if (p.x() >= width() - border)
00717         m = PositionRight;
00718     else
00719         m = PositionCenter;
00720     return m;
00721 }
00722 
00723 void CdeClient::mouseDoubleClickEvent( QMouseEvent * e )
00724 {
00725     if ( e->button() == Qt::LeftButton && titlebar->geometry().contains( e->pos() ) )
00726        titlebarDblClickOperation();
00727 }
00728 
00729 void CdeClient::mousePressEvent( QMouseEvent * e )
00730 {
00731     if ( e->button() == Qt::LeftButton && titlebar->geometry().contains( e->pos() ) )
00732     {
00733        if ( titlebarButtonMode )
00734        {
00735            titlebarPressed = true;
00736            widget()->repaint(titlebar->geometry(), false);
00737        }
00738     }
00739 }
00740 
00741 void CdeClient::borders(int &left, int &right, int &top, int &bottom) const
00742 {
00743     left = right = bottom = s_frameWidth + 1;
00744     top = s_buttonSize + s_frameWidth + 1;
00745 }
00746 
00747 void CdeClient::mouseReleaseEvent( QMouseEvent * e )
00748 {
00749     if ( e->button() == Qt::LeftButton && titlebarPressed )
00750     {
00751        titlebarPressed = false;
00752        widget()->repaint(titlebar->geometry(), false);
00753     }
00754 }
00755 
00756 bool CdeClient::eventFilter(QObject *o, QEvent *e)
00757 {
00758     if (o != widget())
00759        return false;
00760     switch (e->type()) {
00761     case QEvent::Resize:
00762        resizeEvent(static_cast< QResizeEvent* >(e));
00763        return true;
00764     case QEvent::Paint:
00765        paintEvent(static_cast< QPaintEvent* >(e));
00766        return true;
00767     case QEvent::MouseButtonDblClick:
00768        mouseDoubleClickEvent(static_cast< QMouseEvent* >(e));
00769        return true;
00770     case QEvent::MouseButtonPress:
00771        processMousePressEvent(static_cast< QMouseEvent* >(e));
00772        return true;
00773     case QEvent::Show:
00774        showEvent(static_cast< QShowEvent* >(e));
00775        return true;
00776     default:
00777        break;
00778     }
00779     return false;
00780 }
00781 
00782 // ---------------------------------------
00783 
00784 CdeButton::CdeButton(CdeClient* parent,
00785        const char* name, int btnType, const QString& tip, int realize_btns)
00786     : Q3Button(parent->widget(), name), m_btnType(btnType), last_button(Qt::NoButton)
00787 {
00788     setBackgroundMode( QWidget::NoBackground );
00789     setFixedSize( s_buttonSize, s_buttonSize );
00790     resize( s_buttonSize, s_buttonSize );
00791     m_parent = parent;
00792 
00793     setCursor(ArrowCursor);
00794     this->setToolTip( tip);
00795 
00796     m_realize_buttons = realize_btns;
00797 }
00798 
00799 void CdeButton::reset()
00800 {
00801     repaint( false );
00802 }
00803 
00804 void CdeButton::drawButton( QPainter* p )
00805 {
00806     p->setBrush( options()->color( KDecoration::ColorTitleBar, m_parent->isActive() ) );
00807     p->drawRect( 0, 0, s_buttonSize, s_buttonSize );
00808 
00809     QColorGroup colorGroup =
00810       options()->colorGroup( KDecoration::ColorTitleBar, m_parent->isActive() );
00811 
00812     fixColorGroup(colorGroup);
00813 
00814     qDrawShadePanel( p, 0, 0, s_buttonSize, s_buttonSize,
00815                   colorGroup, isDown() );
00816 
00817     switch ( m_btnType )
00818     {
00819         case (BtnMenu):
00820             qDrawShadePanel( p, s_o1, s_o2, s_w1, s_w2, colorGroup );
00821        break;
00822        case (BtnHelp):
00823            p->setPen( colorGroup.light() );
00824            p->drawLineSegments( Q3PointArray(16, helpLLines) );
00825            p->setPen( colorGroup.dark() );
00826            p->drawLineSegments( Q3PointArray(14, helpDLines) );
00827        break;
00828        case (BtnIconify):
00829            qDrawShadePanel( p, s_o2, s_o2, s_w2, s_w2, colorGroup );
00830        break;
00831        case (BtnMax):
00832            qDrawShadePanel( p, s_o1, s_o1, s_w1, s_w1, colorGroup,
00833                   m_parent->maximizeMode() == KDecoration::MaximizeFull );
00834        break;
00835        case (BtnClose):
00836            p->setPen( colorGroup.dark() );
00837            p->drawLineSegments( Q3PointArray(18, closeDLines) );
00838            p->setPen( colorGroup.light() );
00839            p->drawLineSegments( Q3PointArray(15, closeLLines) );
00840        break;
00841     }
00842 }
00843 
00844 void CdeButton::mousePressEvent(QMouseEvent *e)
00845 {
00846     last_button = e->button();
00847     QMouseEvent me(e->type(), e->pos(),
00848            e->globalPos(), (e->button()&m_realize_buttons)?Qt::LeftButton:Qt::NoButton, e->state());
00849     Q3Button::mousePressEvent(&me);
00850 }
00851 
00852 void CdeButton::mouseReleaseEvent(QMouseEvent * e)
00853 {
00854     last_button = e->button();
00855     QMouseEvent me(e->type(), e->pos(),
00856            e->globalPos(), (e->button()&m_realize_buttons)?Qt::LeftButton:Qt::NoButton, e->state());
00857     Q3Button::mouseReleaseEvent(&me);
00858 }
00859 
00860 } // CDE namespace
00861 
00862 #include "cdeclient.moc"
00863 
00864 // vim: sw=4