• Skip to content
  • Skip to link menu
KDE 4.1 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KWinLibraries

kcommondecoration.cpp

Go to the documentation of this file.
00001 /*
00002   This file is part of the KDE project.
00003 
00004   Copyright (C) 2005 Sandro Giessl <sandro@giessl.com>
00005 
00006   Permission is hereby granted, free of charge, to any person obtaining a
00007   copy of this software and associated documentation files (the "Software"),
00008   to deal in the Software without restriction, including without limitation
00009   the rights to use, copy, modify, merge, publish, distribute, sublicense,
00010   and/or sell copies of the Software, and to permit persons to whom the
00011   Software is furnished to do so, subject to the following conditions:
00012 
00013   The above copyright notice and this permission notice shall be included in
00014   all copies or substantial portions of the Software.
00015 
00016   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00017   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00018   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00019   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00020   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00021   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00022   DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 #include "kcommondecoration.h"
00026 #include "kcommondecoration_p.h"
00027 
00028 #include <QApplication>
00029 #include <QCursor>
00030 #include <QDateTime>
00031 #include <QLabel>
00032 
00033 #include <QWidget>
00034 
00035 #include <kdebug.h>
00036 
00037 #include <kapplication.h>
00038 #include "kdecorationfactory.h"
00039 #include <klocale.h>
00040 #include <QDesktopWidget>
00041 
00042 #include "kcommondecoration.moc"
00043 
00047 KCommonDecoration::KCommonDecoration(KDecorationBridge* bridge, KDecorationFactory* factory)
00048     :   m_previewWidget(0),
00049         btnHideMinWidth(200),
00050         btnHideLastWidth(0),
00051         closing(false),
00052         wrapper( new KCommonDecorationWrapper( this, bridge, factory ))
00053         
00054 {
00055     // sizeof(...) is calculated at compile time
00056     memset(m_button, 0, sizeof(KCommonDecorationButton *) * NumButtons);
00057     connect( wrapper, SIGNAL( keepAboveChanged( bool )), this, SIGNAL( keepAboveChanged( bool )));
00058     connect( wrapper, SIGNAL( keepBelowChanged( bool )), this, SIGNAL( keepBelowChanged( bool )));
00059 }
00060 
00061 KCommonDecoration::~KCommonDecoration()
00062 {
00063     for (int n=0; n<NumButtons; n++) {
00064         if (m_button[n]) delete m_button[n];
00065     }
00066     delete m_previewWidget;
00067 //    delete wrapper; - do not do this, this object is actually owned and deleted by the wrapper
00068 }
00069 
00070 QString KCommonDecoration::defaultButtonsLeft() const
00071 {
00072     return KDecorationOptions::defaultTitleButtonsLeft();
00073 }
00074 
00075 QString KCommonDecoration::defaultButtonsRight() const
00076 {
00077     return KDecorationOptions::defaultTitleButtonsRight();
00078 }
00079 
00080 bool KCommonDecoration::decorationBehaviour(DecorationBehaviour behaviour) const
00081 {
00082     switch (behaviour) {
00083         case DB_MenuClose:
00084             return false;
00085 
00086         case DB_WindowMask:
00087             return false;
00088 
00089         case DB_ButtonHide:
00090             return true;
00091     }
00092 
00093     return false;
00094 }
00095 
00096 int KCommonDecoration::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *button) const
00097 {
00098     switch (lm) {
00099         case LM_BorderLeft:
00100         case LM_BorderRight:
00101         case LM_BorderBottom:
00102         case LM_TitleEdgeTop:
00103         case LM_TitleEdgeBottom:
00104         case LM_TitleEdgeLeft:
00105         case LM_TitleEdgeRight:
00106         case LM_TitleBorderLeft:
00107         case LM_TitleBorderRight:
00108             return 5;
00109 
00110 
00111         case LM_ButtonWidth:
00112         case LM_ButtonHeight:
00113         case LM_TitleHeight:
00114             return 20;
00115 
00116         case LM_ButtonSpacing:
00117             return 5;
00118 
00119         case LM_ButtonMarginTop:
00120             return 0;
00121 
00122         case LM_ExplicitButtonSpacer:
00123             return layoutMetric(LM_ButtonWidth, respectWindowState, button )/2; // half button width by default
00124 
00125         default:
00126             return 0;
00127     }
00128 }
00129 
00130 void KCommonDecoration::init()
00131 {
00132     createMainWidget();
00133 
00134     // for flicker-free redraws
00135     widget()->setAttribute(Qt::WA_NoSystemBackground);
00136 
00137     widget()->installEventFilter( this );
00138 
00139     resetLayout();
00140 
00141     connect(this, SIGNAL(keepAboveChanged(bool) ), SLOT(keepAboveChange(bool) ) );
00142     connect(this, SIGNAL(keepBelowChanged(bool) ), SLOT(keepBelowChange(bool) ) );
00143 
00144     updateCaption();
00145 }
00146 
00147 void KCommonDecoration::reset( unsigned long changed )
00148 {
00149     if (changed & SettingButtons) {
00150         resetLayout();
00151         widget()->update();
00152     }
00153 }
00154 
00155 QRegion KCommonDecoration::cornerShape(WindowCorner)
00156 {
00157     return QRegion();
00158 }
00159 
00160 void KCommonDecoration::updateCaption()
00161 {
00162     // This should be reimplemented in decorations for better efficiency
00163     widget()->update();
00164 }
00165 
00166 void KCommonDecoration::borders( int& left, int& right, int& top, int& bottom ) const
00167 {
00168     left = layoutMetric(LM_BorderLeft);
00169     right = layoutMetric(LM_BorderRight);
00170     bottom = layoutMetric(LM_BorderBottom);
00171     top = layoutMetric(LM_TitleHeight) +
00172             layoutMetric(LM_TitleEdgeTop) +
00173             layoutMetric(LM_TitleEdgeBottom);
00174 
00175     updateLayout(); // TODO!! don't call every time we are in ::borders
00176 }
00177 
00178 void KCommonDecoration::updateLayout() const
00179 {
00180     QRect r = widget()->rect();
00181     int r_x, r_y, r_x2, r_y2;
00182     r.getCoords(&r_x, &r_y, &r_x2, &r_y2);
00183 
00184     // layout preview widget
00185     if (m_previewWidget) {
00186         const int borderLeft = layoutMetric(LM_BorderLeft);
00187         const int borderRight = layoutMetric(LM_BorderRight);
00188         const int borderBottom = layoutMetric(LM_BorderBottom);
00189         const int titleHeight = layoutMetric(LM_TitleHeight);
00190         const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
00191         const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
00192 
00193         int left = r_x+borderLeft;
00194         int top = r_y+titleEdgeTop+titleHeight+titleEdgeBottom;
00195         int width = r_x2-borderRight-left+1;
00196         int height = r_y2-borderBottom-top+1;
00197         m_previewWidget->setGeometry(left, top, width, height);
00198         moveWidget(left,top, m_previewWidget);
00199         resizeWidget(width, height, m_previewWidget);
00200     }
00201 
00202     // resize buttons...
00203     for (int n=0; n<NumButtons; n++) {
00204         if (m_button[n]) {
00205             QSize newSize = QSize(layoutMetric(LM_ButtonWidth, true, m_button[n]),
00206                                   layoutMetric(LM_ButtonHeight, true, m_button[n]) );
00207             if (newSize != m_button[n]->size() )
00208                 m_button[n]->setSize(newSize);
00209         }
00210     }
00211 
00212     // layout buttons
00213     int y = r_y + layoutMetric(LM_TitleEdgeTop) + layoutMetric(LM_ButtonMarginTop);
00214     if (m_buttonsLeft.count() > 0) {
00215         const int buttonSpacing = layoutMetric(LM_ButtonSpacing);
00216         int x = r_x + layoutMetric(LM_TitleEdgeLeft);
00217         for (ButtonContainer::const_iterator it = m_buttonsLeft.begin(); it != m_buttonsLeft.end(); ++it) {
00218             bool elementLayouted = false;
00219             if (*it) {
00220                 if (!(*it)->isHidden() ) {
00221                     moveWidget(x,y, *it);
00222                     x += layoutMetric(LM_ButtonWidth, true, qobject_cast<KCommonDecorationButton*>(*it) );
00223                     elementLayouted = true;
00224                 }
00225             } else {
00226                 x+= layoutMetric(LM_ExplicitButtonSpacer);
00227                 elementLayouted = true;
00228             }
00229             if (elementLayouted && it != m_buttonsLeft.end() )
00230                 x += buttonSpacing;
00231         }
00232     }
00233 
00234     if (m_buttonsRight.count() > 0) {
00235         const int titleEdgeRightLeft = r_x2-layoutMetric(LM_TitleEdgeRight)+1;
00236 
00237         const int buttonSpacing = layoutMetric(LM_ButtonSpacing);
00238         int x = titleEdgeRightLeft - buttonContainerWidth(m_buttonsRight);
00239         for (ButtonContainer::const_iterator it = m_buttonsRight.begin(); it != m_buttonsRight.end(); ++it) {
00240             bool elementLayouted = false;
00241             if (*it) {
00242                 if (!(*it)->isHidden() ) {
00243                     moveWidget(x,y, *it);
00244                     x += layoutMetric(LM_ButtonWidth, true, qobject_cast<KCommonDecorationButton*>(*it) );;
00245                     elementLayouted = true;
00246                 }
00247             } else {
00248                 x += layoutMetric(LM_ExplicitButtonSpacer);
00249                 elementLayouted = true;
00250             }
00251             if (elementLayouted && it != m_buttonsRight.end() )
00252                 x += buttonSpacing;
00253         }
00254     }
00255 }
00256 
00257 void KCommonDecoration::updateButtons() const
00258 {
00259     for (int n=0; n<NumButtons; n++)
00260         if (m_button[n]) m_button[n]->update();
00261 }
00262 
00263 void KCommonDecoration::resetButtons() const
00264 {
00265     for (int n=0; n<NumButtons; n++)
00266         if (m_button[n]) m_button[n]->reset(KCommonDecorationButton::ManualReset);
00267 }
00268 
00269 void KCommonDecoration::resetLayout()
00270 {
00271     for (int n=0; n<NumButtons; n++) {
00272         if (m_button[n]) {
00273             delete m_button[n];
00274             m_button[n] = 0;
00275         }
00276     }
00277     m_buttonsLeft.clear();
00278     m_buttonsRight.clear();
00279 
00280     delete m_previewWidget;
00281     m_previewWidget = 0;
00282 
00283     // shown instead of the window contents in decoration previews
00284     if(isPreview() ) {
00285         m_previewWidget = new QLabel(i18n("<center><b>%1 preview</b></center>", visibleName() ), widget());
00286         m_previewWidget->setAutoFillBackground(true);
00287         m_previewWidget->show();
00288     }
00289 
00290     addButtons(m_buttonsLeft,
00291                options()->customButtonPositions() ? options()->titleButtonsLeft() : defaultButtonsLeft(),
00292                true);
00293     addButtons(m_buttonsRight,
00294                options()->customButtonPositions() ? options()->titleButtonsRight() : defaultButtonsRight(),
00295                false);
00296 
00297     updateLayout();
00298 
00299     const int minTitleBarWidth = 35;
00300     btnHideMinWidth = buttonContainerWidth(m_buttonsLeft,true) + buttonContainerWidth(m_buttonsRight,true) +
00301             layoutMetric(LM_TitleEdgeLeft,false) + layoutMetric(LM_TitleEdgeRight,false) +
00302             layoutMetric(LM_TitleBorderLeft,false) + layoutMetric(LM_TitleBorderRight,false) +
00303             minTitleBarWidth;
00304     btnHideLastWidth = 0;
00305 }
00306 
00307 int KCommonDecoration::buttonsLeftWidth() const
00308 {
00309     return buttonContainerWidth(m_buttonsLeft);
00310 }
00311 
00312 int KCommonDecoration::buttonsRightWidth() const
00313 {
00314     return buttonContainerWidth(m_buttonsRight);
00315 }
00316 
00317 int KCommonDecoration::buttonContainerWidth(const ButtonContainer &btnContainer, bool countHidden) const
00318 {
00319     int explicitSpacer = layoutMetric(LM_ExplicitButtonSpacer);
00320 
00321     int shownElementsCount = 0;
00322 
00323     int w = 0;
00324     for (ButtonContainer::const_iterator it = btnContainer.begin(); it != btnContainer.end(); ++it) {
00325         if (*it) {
00326             if (countHidden || !(*it)->isHidden() ) {
00327                 w += (*it)->width();
00328                 ++shownElementsCount;
00329             }
00330         } else {
00331             w += explicitSpacer;
00332             ++shownElementsCount;
00333         }
00334     }
00335     w += layoutMetric(LM_ButtonSpacing)*(shownElementsCount-1);
00336 
00337     return w;
00338 }
00339 
00340 void KCommonDecoration::addButtons(ButtonContainer &btnContainer, const QString& s, bool isLeft)
00341 {
00342     if (s.length() > 0) {
00343         for (int n=0; n < s.length(); n++) {
00344             KCommonDecorationButton *btn = 0;
00345             switch (s[n].toAscii()) {
00346               case 'M': // Menu button
00347                   if (!m_button[MenuButton]){
00348                       btn = createButton(MenuButton);
00349                       if (!btn) break;
00350                       btn->setTipText(i18n("Menu") );
00351                       btn->setRealizeButtons(Qt::LeftButton|Qt::RightButton);
00352                       connect(btn, SIGNAL(pressed()), SLOT(menuButtonPressed()));
00353                       connect(btn, SIGNAL(released()), this, SLOT(menuButtonReleased()));
00354 
00355                       m_button[MenuButton] = btn;
00356                   }
00357                   break;
00358               case 'S': // OnAllDesktops button
00359                   if (!m_button[OnAllDesktopsButton]){
00360                       btn = createButton(OnAllDesktopsButton);
00361                       if (!btn) break;
00362                       const bool oad = isOnAllDesktops();
00363                       btn->setTipText(oad?i18n("Not on all desktops"):i18n("On all desktops") );
00364                       btn->setToggleButton(true);
00365                       btn->setOn( oad );
00366                       connect(btn, SIGNAL(clicked()), SLOT(toggleOnAllDesktops()));
00367 
00368                       m_button[OnAllDesktopsButton] = btn;
00369                   }
00370                   break;
00371               case 'H': // Help button
00372                   if ((!m_button[HelpButton]) && providesContextHelp()){
00373                       btn = createButton(HelpButton);
00374                       if (!btn) break;
00375                       btn->setTipText(i18n("Help") );
00376                       connect(btn, SIGNAL(clicked()), SLOT(showContextHelp()));
00377 
00378                       m_button[HelpButton] = btn;
00379                   }
00380                   break;
00381               case 'I': // Minimize button
00382                   if ((!m_button[MinButton]) && isMinimizable()){
00383                       btn = createButton(MinButton);
00384                       if (!btn) break;
00385                       btn->setTipText(i18n("Minimize") );
00386                       connect(btn, SIGNAL(clicked()), SLOT(minimize()));
00387 
00388                       m_button[MinButton] = btn;
00389                   }
00390                   break;
00391               case 'A': // Maximize button
00392                   if ((!m_button[MaxButton]) && isMaximizable()){
00393                       btn = createButton(MaxButton);
00394                       if (!btn) break;
00395                       btn->setRealizeButtons(Qt::LeftButton|Qt::MidButton|Qt::RightButton);
00396                       const bool max = maximizeMode()==MaximizeFull;
00397                       btn->setTipText(max?i18n("Restore"):i18n("Maximize") );
00398                       btn->setToggleButton(true);
00399                       btn->setOn( max );
00400                       connect(btn, SIGNAL(clicked()), SLOT(slotMaximize()));
00401 
00402                       m_button[MaxButton] = btn;
00403                   }
00404                   break;
00405               case 'X': // Close button
00406                   if ((!m_button[CloseButton]) && isCloseable()){
00407                       btn = createButton(CloseButton);
00408                       if (!btn) break;
00409                       btn->setTipText(i18n("Close") );
00410                       connect(btn, SIGNAL(clicked()), SLOT(closeWindow()));
00411 
00412                       m_button[CloseButton] = btn;
00413                   }
00414                   break;
00415               case 'F': // AboveButton button
00416                   if (!m_button[AboveButton]){
00417                       btn = createButton(AboveButton);
00418                       if (!btn) break;
00419                       bool above = keepAbove();
00420                       btn->setTipText(above?i18n("Do not keep above others"):i18n("Keep above others") );
00421                       btn->setToggleButton(true);
00422                       btn->setOn( above );
00423                       connect(btn, SIGNAL(clicked()), SLOT(slotKeepAbove()));
00424 
00425                       m_button[AboveButton] = btn;
00426                   }
00427                   break;
00428               case 'B': // BelowButton button
00429                   if (!m_button[BelowButton]){
00430                       btn = createButton(BelowButton);
00431                       if (!btn) break;
00432                       bool below = keepBelow();
00433                       btn->setTipText(below?i18n("Do not keep below others"):i18n("Keep below others") );
00434                       btn->setToggleButton(true);
00435                       btn->setOn( below );
00436                       connect(btn, SIGNAL(clicked()), SLOT(slotKeepBelow()));
00437 
00438                       m_button[BelowButton] = btn;
00439                   }
00440                   break;
00441               case 'L': // Shade button
00442                   if ((!m_button[ShadeButton]) && isShadeable()){
00443                       btn = createButton(ShadeButton);
00444                       if (!btn) break;
00445                       bool shaded = isSetShade();
00446                       btn->setTipText(shaded?i18n("Unshade"):i18n("Shade") );
00447                       btn->setToggleButton(true);
00448                       btn->setOn( shaded );
00449                       connect(btn, SIGNAL(clicked()), SLOT(slotShade()));
00450 
00451                       m_button[ShadeButton] = btn;
00452                   }
00453                   break;
00454               case '_': // Spacer item
00455                   btnContainer.append(0);
00456             }
00457 
00458 
00459             if (btn) {
00460                 btn->setLeft(isLeft);
00461                 btn->setSize(QSize(layoutMetric(LM_ButtonWidth, true, btn),layoutMetric(LM_ButtonHeight, true, btn)) );
00462                 btn->show();
00463                 btnContainer.append(btn);
00464             }
00465 
00466         }
00467     }
00468 }
00469 
00470 void KCommonDecoration::calcHiddenButtons()
00471 {
00472     if (width() == btnHideLastWidth)
00473         return;
00474 
00475     btnHideLastWidth = width();
00476 
00477     //Hide buttons in the following order:
00478     KCommonDecorationButton* btnArray[] = { m_button[HelpButton], m_button[ShadeButton], m_button[BelowButton],
00479         m_button[AboveButton], m_button[OnAllDesktopsButton], m_button[MaxButton],
00480         m_button[MinButton], m_button[MenuButton], m_button[CloseButton] };
00481     const int buttonsCount = sizeof( btnArray ) / sizeof( btnArray[ 0 ] );
00482 
00483     int current_width = width();
00484     int count = 0;
00485 
00486     // Hide buttons
00487     while (current_width < btnHideMinWidth && count < buttonsCount)
00488     {
00489         if (btnArray[count] ) {
00490             current_width += btnArray[count]->width();
00491             if (btnArray[count]->isVisible() )
00492                 btnArray[count]->hide();
00493         }
00494         count++;
00495     }
00496     // Show the rest of the buttons...
00497     for(int i = count; i < buttonsCount; i++)
00498     {
00499         if (btnArray[i] ) {
00500 
00501             if (! btnArray[i]->isHidden() )
00502                 break; // all buttons shown...
00503 
00504             btnArray[i]->show();
00505         }
00506     }
00507 }
00508 
00509 void KCommonDecoration::show()
00510 {
00511     if (decorationBehaviour(DB_ButtonHide) )
00512         calcHiddenButtons();
00513     widget()->show();
00514 }
00515 
00516 void KCommonDecoration::resize( const QSize& s )
00517 {
00518     widget()->resize( s );
00519 }
00520 
00521 QSize KCommonDecoration::minimumSize() const
00522 {
00523     const int minWidth = qMax(layoutMetric(LM_TitleEdgeLeft), layoutMetric(LM_BorderLeft))
00524             +qMax(layoutMetric(LM_TitleEdgeRight), layoutMetric(LM_BorderRight))
00525             +layoutMetric(LM_TitleBorderLeft)+layoutMetric(LM_TitleBorderRight);
00526     return QSize(minWidth,
00527                  layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)
00528                          +layoutMetric(LM_TitleEdgeBottom)
00529                          +layoutMetric(LM_BorderBottom) );
00530 }
00531 
00532 void KCommonDecoration::maximizeChange()
00533 {
00534     if( m_button[MaxButton] ) {
00535         m_button[MaxButton]->setOn( maximizeMode()==MaximizeFull);
00536         m_button[MaxButton]->setTipText( (maximizeMode()!=MaximizeFull) ?
00537                 i18n("Maximize")
00538             : i18n("Restore"));
00539         m_button[MaxButton]->reset(KCommonDecorationButton::StateChange);
00540     }
00541     updateWindowShape();
00542     widget()->update();
00543 }
00544 
00545 void KCommonDecoration::desktopChange()
00546 {
00547     if ( m_button[OnAllDesktopsButton] ) {
00548         m_button[OnAllDesktopsButton]->setOn( isOnAllDesktops() );
00549         m_button[OnAllDesktopsButton]->setTipText( isOnAllDesktops() ?
00550                 i18n("Not on all desktops")
00551             : i18n("On all desktops"));
00552         m_button[OnAllDesktopsButton]->reset(KCommonDecorationButton::StateChange);
00553     }
00554 }
00555 
00556 void KCommonDecoration::shadeChange()
00557 {
00558     if ( m_button[ShadeButton] ) {
00559         bool shaded = isSetShade();
00560         m_button[ShadeButton]->setOn( shaded );
00561         m_button[ShadeButton]->setTipText( shaded ?
00562                 i18n("Unshade")
00563             : i18n("Shade"));
00564         m_button[ShadeButton]->reset(KCommonDecorationButton::StateChange);
00565     }
00566 }
00567 
00568 void KCommonDecoration::iconChange()
00569 {
00570     if (m_button[MenuButton])
00571     {
00572         m_button[MenuButton]->update();
00573         m_button[MenuButton]->reset(KCommonDecorationButton::IconChange);
00574     }
00575 }
00576 
00577 void KCommonDecoration::activeChange()
00578 {
00579     updateButtons();
00580     widget()->update(); // do something similar to updateCaption here
00581 }
00582 
00583 void KCommonDecoration::captionChange()
00584 {
00585     updateCaption();
00586 }
00587 
00588 void KCommonDecoration::keepAboveChange(bool above)
00589 {
00590     if (m_button[AboveButton])
00591     {
00592         m_button[AboveButton]->setOn(above);
00593         m_button[AboveButton]->setTipText( above?i18n("Do not keep above others"):i18n("Keep above others") );
00594         m_button[AboveButton]->reset(KCommonDecorationButton::StateChange);
00595     }
00596 
00597     if (m_button[BelowButton] && m_button[BelowButton]->isChecked())
00598     {
00599         m_button[BelowButton]->setOn(false);
00600         m_button[BelowButton]->setTipText( i18n("Keep below others") );
00601         m_button[BelowButton]->reset(KCommonDecorationButton::StateChange);
00602     }
00603 }
00604 
00605 void KCommonDecoration::keepBelowChange(bool below)
00606 {
00607     if (m_button[BelowButton])
00608     {
00609         m_button[BelowButton]->setOn(below);
00610         m_button[BelowButton]->setTipText( below?i18n("Do not keep below others"):i18n("Keep below others") );
00611         m_button[BelowButton]->reset(KCommonDecorationButton::StateChange);
00612     }
00613 
00614     if (m_button[AboveButton] && m_button[AboveButton]->isChecked())
00615     {
00616         m_button[AboveButton]->setOn(false);
00617         m_button[AboveButton]->setTipText( i18n("Keep above others") );
00618         m_button[AboveButton]->reset(KCommonDecorationButton::StateChange);
00619     }
00620 }
00621 
00622 void KCommonDecoration::slotMaximize()
00623 {
00624     if (m_button[MaxButton])
00625     {
00626         maximize(m_button[MaxButton]->lastMousePress() );
00627     }
00628 }
00629 
00630 void KCommonDecoration::slotShade()
00631 {
00632     setShade( !isSetShade() );
00633 }
00634 
00635 void KCommonDecoration::slotKeepAbove()
00636 {
00637     setKeepAbove(!keepAbove() );
00638 }
00639 
00640 void KCommonDecoration::slotKeepBelow()
00641 {
00642     setKeepBelow(!keepBelow() );
00643 }
00644 
00645 void KCommonDecoration::menuButtonPressed()
00646 {
00647     static QTime* t = NULL;
00648     static KCommonDecoration* lastClient = NULL;
00649     if (t == NULL)
00650         t = new QTime;
00651     bool dbl = (lastClient==this && t->elapsed() <= QApplication::doubleClickInterval());
00652     lastClient = this;
00653     t->start();
00654     if (!dbl || !decorationBehaviour(DB_MenuClose) ) {
00655         QRect menuRect = m_button[MenuButton]->rect();
00656         QPoint menutop = m_button[MenuButton]->mapToGlobal(menuRect.topLeft());
00657         QPoint menubottom = m_button[MenuButton]->mapToGlobal(menuRect.bottomRight())+QPoint(0,2);
00658         KDecorationFactory* f = factory();
00659         showWindowMenu(QRect(menutop, menubottom));
00660         if( !f->exists( decoration())) // 'this' was deleted
00661             return;
00662         m_button[MenuButton]->setDown(false);
00663     }
00664     else
00665         closing = true;
00666 }
00667 
00668 void KCommonDecoration::menuButtonReleased()
00669 {
00670     if(closing)
00671         closeWindow();
00672 }
00673 
00674 void KCommonDecoration::resizeEvent(QResizeEvent */*e*/)
00675 {
00676     if (decorationBehaviour(DB_ButtonHide) )
00677         calcHiddenButtons();
00678 
00679     updateLayout();
00680 
00681     updateWindowShape();
00682     // FIXME: don't update() here! this would result in two paintEvent()s
00683     // because there is already "something" else triggering the repaint...
00684 //     widget()->update();
00685 }
00686 
00687 void KCommonDecoration::moveWidget(int x, int y, QWidget *widget) const
00688 {
00689     QPoint p = widget->pos();
00690     int oldX = p.y();
00691     int oldY = p.x();
00692 
00693     if (x!=oldX || y!=oldY)
00694         widget->move(x,y);
00695 }
00696 
00697 void KCommonDecoration::resizeWidget(int w, int h, QWidget *widget) const
00698 {
00699     QSize s = widget->size();
00700     int oldW = s.width();
00701     int oldH = s.height();
00702 
00703     if (w!=oldW || h!=oldH)
00704         widget->resize(w,h);
00705 }
00706 
00707 void KCommonDecoration::mouseDoubleClickEvent(QMouseEvent *e)
00708 {
00709     if( e->button() != Qt::LeftButton )
00710         return;
00711 
00712     int tb = layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeBottom);
00713     // when shaded, react on double clicks everywhere to make it easier to unshade. otherwise
00714     // react only on double clicks in the title bar region...
00715     if (isSetShade() || e->pos().y() <= tb )
00716         titlebarDblClickOperation();
00717 }
00718 
00719 void KCommonDecoration::wheelEvent(QWheelEvent *e)
00720 {
00721     int tb = layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeBottom);
00722     if (isSetShade() || e->pos().y() <= tb )
00723         titlebarMouseWheelOperation( e->delta());
00724 }
00725 
00726 KCommonDecoration::Position KCommonDecoration::mousePosition(const QPoint &point) const
00727 {
00728     const int corner = 18+3*layoutMetric(LM_BorderBottom, false)/2;
00729     Position pos = PositionCenter;
00730 
00731     QRect r = widget()->rect();
00732     int r_x, r_y, r_x2, r_y2;
00733     r.getCoords(&r_x, &r_y, &r_x2, &r_y2);
00734     int p_x = point.x();
00735     int p_y = point.y();
00736     const int borderLeft = layoutMetric(LM_BorderLeft);
00737 //     const int borderRight = layoutMetric(LM_BorderRight);
00738     const int borderBottom = layoutMetric(LM_BorderBottom);
00739     const int titleHeight = layoutMetric(LM_TitleHeight);
00740     const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
00741     const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
00742     const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
00743     const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);
00744 
00745     const int borderBottomTop = r_y2-borderBottom+1;
00746     const int borderLeftRight = r_x+borderLeft-1;
00747 //     const int borderRightLeft = r_x2-borderRight+1;
00748     const int titleEdgeLeftRight = r_x+titleEdgeLeft-1;
00749     const int titleEdgeRightLeft = r_x2-titleEdgeRight+1;
00750     const int titleEdgeBottomBottom = r_y+titleEdgeTop+titleHeight+titleEdgeBottom-1;
00751     const int titleEdgeTopBottom = r_y+titleEdgeTop-1;
00752 
00753     if (p_y <= titleEdgeTopBottom) {
00754         if (p_x <= r_x+corner)
00755             pos = PositionTopLeft;
00756         else if (p_x >= r_x2-corner)
00757             pos = PositionTopRight;
00758         else
00759             pos = PositionTop;
00760     } else if (p_y <= titleEdgeBottomBottom) {
00761         if (p_x <= titleEdgeLeftRight)
00762             pos = PositionTopLeft;
00763         else if (p_x >= titleEdgeRightLeft)
00764             pos = PositionTopRight;
00765         else
00766             pos = PositionCenter; // title bar
00767     } else if (p_y < borderBottomTop) {
00768         if      (p_y < r_y2-corner) {
00769             if (p_x <= borderLeftRight)
00770                 pos = PositionLeft;
00771             else
00772                 pos = PositionRight;
00773         } else {
00774             if (p_x <= borderLeftRight)
00775                 pos = PositionBottomLeft;
00776             else
00777                 pos = PositionBottomRight;
00778         }
00779     } else if(p_y >= borderBottomTop) {
00780         if (p_x <= r_x+corner)
00781             pos = PositionBottomLeft;
00782         else if (p_x >= r_x2-corner)
00783             pos = PositionBottomRight;
00784         else
00785             pos = PositionBottom;
00786     }
00787 
00788     return pos;
00789 }
00790 
00791 void KCommonDecoration::updateWindowShape()
00792 {
00793     // don't mask the widget...
00794     if (!decorationBehaviour(DB_WindowMask) )
00795         return;
00796 
00797     int w = widget()->width();
00798     int h = widget()->height();
00799 
00800     bool tl=true,tr=true,bl=true,br=true; // is there a transparent rounded corner in top-left? etc
00801 
00802     QDesktopWidget *desktop=KApplication::desktop();
00803     // no transparent rounded corners if this window corner lines up with a screen corner
00804     for(int screen=0; screen < desktop->numScreens(); ++screen)
00805     {
00806         QRect fullscreen(desktop->screenGeometry(screen));
00807         QRect window = geometry();
00808 
00809         if(window.topLeft()    == fullscreen.topLeft() ) tl = false;
00810         if(window.topRight()   == fullscreen.topRight() ) tr = false;
00811         if(window.bottomLeft() == fullscreen.bottomLeft() ) bl = false;
00812         if(window.bottomRight()== fullscreen.bottomRight() ) br = false;
00813     }
00814 
00815     QRegion mask(0, 0, w, h);
00816 
00817     // Remove top-left corner.
00818     if(tl)
00819     {
00820         mask -= cornerShape(WC_TopLeft);
00821     }
00822     // Remove top-right corner.
00823     if(tr)
00824     {
00825         mask -= cornerShape(WC_TopRight);
00826     }
00827         // Remove top-left corner.
00828     if(bl)
00829     {
00830         mask -= cornerShape(WC_BottomLeft);
00831     }
00832     // Remove top-right corner.
00833     if(br)
00834     {
00835         mask -= cornerShape(WC_BottomRight);
00836     }
00837 
00838     setMask( mask );
00839 }
00840 
00841 bool KCommonDecoration::eventFilter( QObject* o, QEvent* e )
00842 {
00843     if( o != widget())
00844         return false;
00845     switch( e->type())
00846     {
00847         case QEvent::Resize:
00848             resizeEvent(static_cast<QResizeEvent*>(e) );
00849             return true;
00850         case QEvent::Paint:
00851             paintEvent( static_cast< QPaintEvent* >( e ));
00852             return true;
00853         case QEvent::MouseButtonDblClick:
00854             mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ));
00855             return true;
00856         case QEvent::MouseButtonPress:
00857             processMousePressEvent( static_cast< QMouseEvent* >( e ));
00858             return true;
00859         case QEvent::Wheel:
00860             wheelEvent( static_cast< QWheelEvent* >( e ));
00861             return true;
00862         default:
00863             return false;
00864     }
00865 }
00866 
00867 const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
00868         | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask
00869         | NET::UtilityMask | NET::SplashMask;
00870 
00871 bool KCommonDecoration::isToolWindow() const
00872 {
00873     NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK );
00874     return ((type==NET::Toolbar)||(type==NET::Utility)||(type==NET::Menu));
00875 }
00876 
00877 QRect KCommonDecoration::titleRect() const
00878 {
00879     int r_x, r_y, r_x2, r_y2;
00880     widget()->rect().getCoords(&r_x, &r_y, &r_x2, &r_y2);
00881     const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
00882     const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
00883     const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);
00884     const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
00885     const int titleBorderLeft = layoutMetric(LM_TitleBorderLeft);
00886     const int titleBorderRight = layoutMetric(LM_TitleBorderRight);
00887     const int ttlHeight = layoutMetric(LM_TitleHeight);
00888     const int titleEdgeBottomBottom = r_y+titleEdgeTop+ttlHeight+titleEdgeBottom-1;
00889     return QRect(r_x+titleEdgeLeft+buttonsLeftWidth()+titleBorderLeft, r_y+titleEdgeTop,
00890               r_x2-titleEdgeRight-buttonsRightWidth()-titleBorderRight-(r_x+titleEdgeLeft+buttonsLeftWidth()+titleBorderLeft),
00891               titleEdgeBottomBottom-(r_y+titleEdgeTop) );
00892 }
00893 
00894 
00895 KCommonDecorationButton::KCommonDecorationButton(ButtonType type, KCommonDecoration *parent)
00896     : QAbstractButton(parent->widget() ),
00897         m_decoration(parent),
00898         m_type(type),
00899         m_realizeButtons(Qt::LeftButton),
00900         m_lastMouse(Qt::NoButton),
00901         m_isLeft(true)
00902 {
00903     setCursor(Qt::ArrowCursor);
00904 }
00905 
00906 KCommonDecorationButton::~KCommonDecorationButton()
00907 {
00908 }
00909 
00910 KCommonDecoration *KCommonDecorationButton::decoration() const
00911 {
00912     return m_decoration;
00913 }
00914 
00915 ButtonType KCommonDecorationButton::type() const
00916 {
00917     return m_type;
00918 }
00919 
00920 bool KCommonDecorationButton::isLeft() const
00921 {
00922     return m_isLeft;
00923 }
00924 
00925 void KCommonDecorationButton::setLeft(bool left)
00926 {
00927     m_isLeft = left;
00928 }
00929 
00930 void KCommonDecorationButton::setRealizeButtons(int btns)
00931 {
00932     m_realizeButtons = btns;
00933 }
00934 
00935 void KCommonDecorationButton::setSize(const QSize &s)
00936 {
00937     if (!m_size.isValid() || s != size() ) {
00938         m_size = s;
00939 
00940         setFixedSize(m_size);
00941         reset(SizeChange);
00942     }
00943 }
00944 
00945 QSize KCommonDecorationButton::sizeHint() const
00946 {
00947     return m_size;
00948 }
00949 
00950 void KCommonDecorationButton::setTipText(const QString &tip) {
00951     this->setToolTip( tip );
00952 }
00953 
00954 void KCommonDecorationButton::setToggleButton(bool toggle)
00955 {
00956     QAbstractButton::setCheckable(toggle);
00957     reset(ToggleChange);
00958 }
00959 
00960 void KCommonDecorationButton::setOn(bool on)
00961 {
00962     if (on != isChecked() ) {
00963         QAbstractButton::setChecked(on);
00964         reset(StateChange);
00965     }
00966 }
00967 
00968 void KCommonDecorationButton::mousePressEvent(QMouseEvent* e)
00969 {
00970     m_lastMouse = e->button();
00971     // pass on event after changing button to LeftButton
00972     QMouseEvent me(e->type(), e->pos(), (e->button()&m_realizeButtons)?Qt::LeftButton : Qt::NoButton, e->buttons(), e->modifiers() );
00973 
00974     QAbstractButton::mousePressEvent(&me);
00975 }
00976 
00977 void KCommonDecorationButton::mouseReleaseEvent(QMouseEvent* e)
00978 {
00979     m_lastMouse = e->button();
00980     // pass on event after changing button to LeftButton
00981     QMouseEvent me(e->type(), e->pos(), (e->button()&m_realizeButtons)?Qt::LeftButton : Qt::NoButton, e->buttons(), e->modifiers() );
00982 
00983     QAbstractButton::mouseReleaseEvent(&me);
00984 }
00985 
00986 
00987 
00988 // *** wrap everything from KDecoration *** //
00989 bool KCommonDecoration::drawbound( const QRect&, bool )
00990 {
00991     return false;
00992 }
00993 bool KCommonDecoration::windowDocked( Position )
00994 {
00995     return false;
00996 }
00997 const KDecorationOptions* KCommonDecoration::options()
00998 {
00999     return KDecoration::options();
01000 }
01001 bool KCommonDecoration::isActive() const
01002 {
01003     return wrapper->isActive();
01004 }
01005 bool KCommonDecoration::isCloseable() const
01006 {
01007     return wrapper->isCloseable();
01008 }
01009 bool KCommonDecoration::isMaximizable() const
01010 {
01011     return wrapper->isMaximizable();
01012 }
01013 KCommonDecoration::MaximizeMode KCommonDecoration::maximizeMode() const
01014 {
01015     return wrapper->maximizeMode();
01016 }
01017 bool KCommonDecoration::isMinimizable() const
01018 {
01019     return wrapper->isMinimizable();
01020 }
01021 bool KCommonDecoration::providesContextHelp() const
01022 {
01023     return wrapper->providesContextHelp();
01024 }
01025 int KCommonDecoration::desktop() const
01026 {
01027     return wrapper->desktop();
01028 }
01029 bool KCommonDecoration::isOnAllDesktops() const
01030 {
01031     return wrapper->isOnAllDesktops();
01032 }
01033 bool KCommonDecoration::isModal() const
01034 {
01035     return wrapper->isModal();
01036 }
01037 bool KCommonDecoration::isShadeable() const
01038 {
01039     return wrapper->isShadeable();
01040 }
01041 bool KCommonDecoration::isShade() const
01042 {
01043     return wrapper->isShade();
01044 }
01045 bool KCommonDecoration::isSetShade() const
01046 {
01047     return wrapper->isSetShade();
01048 }
01049 bool KCommonDecoration::keepAbove() const
01050 {
01051     return wrapper->keepAbove();
01052 }
01053 bool KCommonDecoration::keepBelow() const
01054 {
01055     return wrapper->keepBelow();
01056 }
01057 bool KCommonDecoration::isMovable() const
01058 {
01059     return wrapper->isMovable();
01060 }
01061 bool KCommonDecoration::isResizable() const
01062 {
01063     return wrapper->isResizable();
01064 }
01065 NET::WindowType KCommonDecoration::windowType( unsigned long supported_types ) const
01066 {
01067     return wrapper->windowType( supported_types );
01068 }
01069 QIcon KCommonDecoration::icon() const
01070 {
01071     return wrapper->icon();
01072 }
01073 QString KCommonDecoration::caption() const
01074 {
01075     return wrapper->caption();
01076 }
01077 void KCommonDecoration::showWindowMenu( const QRect &pos )
01078 {
01079     return wrapper->showWindowMenu( pos );
01080 }
01081 void KCommonDecoration::showWindowMenu( QPoint pos )
01082 {
01083     return wrapper->showWindowMenu( pos );
01084 }
01085 void KCommonDecoration::performWindowOperation( WindowOperation op )
01086 {
01087     return wrapper->performWindowOperation( op );
01088 }
01089 void KCommonDecoration::setMask( const QRegion& reg, int mode )
01090 {
01091     return wrapper->setMask( reg, mode );
01092 }
01093 void KCommonDecoration::clearMask()
01094 {
01095     return wrapper->clearMask();
01096 }
01097 bool KCommonDecoration::isPreview() const
01098 {
01099     return wrapper->isPreview();
01100 }
01101 QRect KCommonDecoration::geometry() const
01102 {
01103     return wrapper->geometry();
01104 }
01105 QRect KCommonDecoration::iconGeometry() const
01106 {
01107     return wrapper->iconGeometry();
01108 }
01109 QRegion KCommonDecoration::unobscuredRegion( const QRegion& r ) const
01110 {
01111     return wrapper->unobscuredRegion( r );
01112 }
01113 WId KCommonDecoration::windowId() const
01114 {
01115     return wrapper->windowId();
01116 }
01117 int KCommonDecoration::width() const
01118 {
01119     return wrapper->width();
01120 }
01121 int KCommonDecoration::height() const
01122 {
01123     return wrapper->height();
01124 }
01125 void KCommonDecoration::processMousePressEvent( QMouseEvent* e )
01126 {
01127     return wrapper->processMousePressEvent( e );
01128 }
01129 void KCommonDecoration::setMainWidget( QWidget* w )
01130 {
01131     return wrapper->setMainWidget( w );
01132 }
01133 void KCommonDecoration::createMainWidget( Qt::WFlags flags )
01134 {
01135     return wrapper->createMainWidget( flags );
01136 }
01137 QWidget* KCommonDecoration::initialParentWidget() const
01138 {
01139     return wrapper->initialParentWidget();
01140 }
01141 Qt::WFlags KCommonDecoration::initialWFlags() const
01142 {
01143     return wrapper->initialWFlags();
01144 }
01145 QWidget* KCommonDecoration::widget()
01146 {
01147     return wrapper->widget();
01148 }
01149 const QWidget* KCommonDecoration::widget() const
01150 {
01151     return wrapper->widget();
01152 }
01153 KDecorationFactory* KCommonDecoration::factory() const
01154 {
01155     return wrapper->factory();
01156 }
01157 void KCommonDecoration::grabXServer()
01158 {
01159     return wrapper->grabXServer();
01160 }
01161 void KCommonDecoration::ungrabXServer()
01162 {
01163     return wrapper->ungrabXServer();
01164 }
01165 void KCommonDecoration::closeWindow()
01166 {
01167     return wrapper->closeWindow();
01168 }
01169 void KCommonDecoration::maximize( Qt::MouseButtons button )
01170 {
01171     return wrapper->maximize( button );
01172 }
01173 void KCommonDecoration::maximize( MaximizeMode mode )
01174 {
01175     return wrapper->maximize( mode );
01176 }
01177 void KCommonDecoration::minimize()
01178 {
01179     return wrapper->minimize();
01180 }
01181 void KCommonDecoration::showContextHelp()
01182 {
01183     return wrapper->showContextHelp();
01184 }
01185 void KCommonDecoration::setDesktop( int desktop )
01186 {
01187     return wrapper->setDesktop( desktop );
01188 }
01189 void KCommonDecoration::toggleOnAllDesktops()
01190 {
01191     return wrapper->toggleOnAllDesktops();
01192 }
01193 void KCommonDecoration::titlebarDblClickOperation()
01194 {
01195     return wrapper->titlebarDblClickOperation();
01196 }
01197 void KCommonDecoration::titlebarMouseWheelOperation( int delta )
01198 {
01199     return wrapper->titlebarMouseWheelOperation( delta );
01200 }
01201 void KCommonDecoration::setShade( bool set )
01202 {
01203     return wrapper->setShade( set );
01204 }
01205 void KCommonDecoration::setKeepAbove( bool set )
01206 {
01207     return wrapper->setKeepAbove( set );
01208 }
01209 void KCommonDecoration::setKeepBelow( bool set )
01210 {
01211     return wrapper->setKeepBelow( set );
01212 }
01213 // *** end of wrapping of everything from KDecoration *** //
01214 
01215 const KDecoration* KCommonDecoration::decoration() const
01216 {
01217     return wrapper;
01218 }
01219 KDecoration* KCommonDecoration::decoration()
01220 {
01221     return wrapper;
01222 }
01223 
01224 // kate: space-indent on; indent-width 4; mixedindent off; indent-mode cstyle;
01225 

KWinLibraries

Skip menu "KWinLibraries"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal