• Skip to content
  • Skip to link menu
KDE 4.2 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 
00041 #include <kephal/screens.h>
00042 
00043 #include "kcommondecoration.moc"
00044 
00048 KCommonDecoration::KCommonDecoration(KDecorationBridge* bridge, KDecorationFactory* factory)
00049     :   m_previewWidget(0),
00050         btnHideMinWidth(200),
00051         btnHideLastWidth(0),
00052         closing(false),
00053         wrapper( new KCommonDecorationWrapper( this, bridge, factory ))
00054         
00055 {
00056     // sizeof(...) is calculated at compile time
00057     memset(m_button, 0, sizeof(KCommonDecorationButton *) * NumButtons);
00058     connect( wrapper, SIGNAL( keepAboveChanged( bool )), this, SIGNAL( keepAboveChanged( bool )));
00059     connect( wrapper, SIGNAL( keepBelowChanged( bool )), this, SIGNAL( keepBelowChanged( bool )));
00060 }
00061 
00062 KCommonDecoration::~KCommonDecoration()
00063 {
00064     for (int n=0; n<NumButtons; n++) {
00065         if (m_button[n]) delete m_button[n];
00066     }
00067     delete m_previewWidget;
00068 //    delete wrapper; - do not do this, this object is actually owned and deleted by the wrapper
00069 }
00070 
00071 QString KCommonDecoration::defaultButtonsLeft() const
00072 {
00073     return KDecorationOptions::defaultTitleButtonsLeft();
00074 }
00075 
00076 QString KCommonDecoration::defaultButtonsRight() const
00077 {
00078     return KDecorationOptions::defaultTitleButtonsRight();
00079 }
00080 
00081 bool KCommonDecoration::decorationBehaviour(DecorationBehaviour behaviour) const
00082 {
00083     switch (behaviour) {
00084         case DB_MenuClose:
00085             return false;
00086 
00087         case DB_WindowMask:
00088             return false;
00089 
00090         case DB_ButtonHide:
00091             return true;
00092     }
00093 
00094     return false;
00095 }
00096 
00097 int KCommonDecoration::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *button) const
00098 {
00099     switch (lm) {
00100         case LM_BorderLeft:
00101         case LM_BorderRight:
00102         case LM_BorderBottom:
00103         case LM_TitleEdgeTop:
00104         case LM_TitleEdgeBottom:
00105         case LM_TitleEdgeLeft:
00106         case LM_TitleEdgeRight:
00107         case LM_TitleBorderLeft:
00108         case LM_TitleBorderRight:
00109             return 5;
00110 
00111 
00112         case LM_ButtonWidth:
00113         case LM_ButtonHeight:
00114         case LM_TitleHeight:
00115             return 20;
00116 
00117         case LM_ButtonSpacing:
00118             return 5;
00119 
00120         case LM_ButtonMarginTop:
00121             return 0;
00122 
00123         case LM_ExplicitButtonSpacer:
00124             return layoutMetric(LM_ButtonWidth, respectWindowState, button )/2; // half button width by default
00125 
00126         default:
00127             return 0;
00128     }
00129 }
00130 
00131 void KCommonDecoration::init()
00132 {
00133     createMainWidget();
00134 
00135     // for flicker-free redraws
00136     widget()->setAttribute(Qt::WA_NoSystemBackground);
00137 
00138     widget()->installEventFilter( this );
00139 
00140     resetLayout();
00141 
00142     connect(this, SIGNAL(keepAboveChanged(bool) ), SLOT(keepAboveChange(bool) ) );
00143     connect(this, SIGNAL(keepBelowChanged(bool) ), SLOT(keepBelowChange(bool) ) );
00144 
00145     updateCaption();
00146 }
00147 
00148 void KCommonDecoration::reset( unsigned long changed )
00149 {
00150     if (changed & SettingButtons) {
00151         resetLayout();
00152         widget()->update();
00153     }
00154 }
00155 
00156 QRegion KCommonDecoration::cornerShape(WindowCorner)
00157 {
00158     return QRegion();
00159 }
00160 
00161 void KCommonDecoration::updateCaption()
00162 {
00163     // This should be reimplemented in decorations for better efficiency
00164     widget()->update();
00165 }
00166 
00167 void KCommonDecoration::borders( int& left, int& right, int& top, int& bottom ) const
00168 {
00169     left = layoutMetric(LM_BorderLeft);
00170     right = layoutMetric(LM_BorderRight);
00171     bottom = layoutMetric(LM_BorderBottom);
00172     top = layoutMetric(LM_TitleHeight) +
00173             layoutMetric(LM_TitleEdgeTop) +
00174             layoutMetric(LM_TitleEdgeBottom);
00175 
00176     updateLayout(); // TODO!! don't call every time we are in ::borders
00177 }
00178 
00179 void KCommonDecoration::updateLayout() const
00180 {
00181     QRect r = widget()->rect();
00182     int r_x, r_y, r_x2, r_y2;
00183     r.getCoords(&r_x, &r_y, &r_x2, &r_y2);
00184 
00185     // layout preview widget
00186     if (m_previewWidget) {
00187         const int borderLeft = layoutMetric(LM_BorderLeft);
00188         const int borderRight = layoutMetric(LM_BorderRight);
00189         const int borderBottom = layoutMetric(LM_BorderBottom);
00190         const int titleHeight = layoutMetric(LM_TitleHeight);
00191         const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
00192         const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
00193 
00194         int left = r_x+borderLeft;
00195         int top = r_y+titleEdgeTop+titleHeight+titleEdgeBottom;
00196         int width = r_x2-borderRight-left+1;
00197         int height = r_y2-borderBottom-top+1;
00198         m_previewWidget->setGeometry(left, top, width, height);
00199         moveWidget(left,top, m_previewWidget);
00200         resizeWidget(width, height, m_previewWidget);
00201     }
00202 
00203     // resize buttons...
00204     for (int n=0; n<NumButtons; n++) {
00205         if (m_button[n]) {
00206             QSize newSize = QSize(layoutMetric(LM_ButtonWidth, true, m_button[n]),
00207                                   layoutMetric(LM_ButtonHeight, true, m_button[n]) );
00208             if (newSize != m_button[n]->size() )
00209                 m_button[n]->setSize(newSize);
00210         }
00211     }
00212 
00213     // layout buttons
00214     int y = r_y + layoutMetric(LM_TitleEdgeTop) + layoutMetric(LM_ButtonMarginTop);
00215     if (m_buttonsLeft.count() > 0) {
00216         const int buttonSpacing = layoutMetric(LM_ButtonSpacing);
00217         int x = r_x + layoutMetric(LM_TitleEdgeLeft);
00218         for (ButtonContainer::const_iterator it = m_buttonsLeft.begin(); it != m_buttonsLeft.end(); ++it) {
00219             bool elementLayouted = false;
00220             if (*it) {
00221                 if (!(*it)->isHidden() ) {
00222                     moveWidget(x,y, *it);
00223                     x += layoutMetric(LM_ButtonWidth, true, qobject_cast<KCommonDecorationButton*>(*it) );
00224                     elementLayouted = true;
00225                 }
00226             } else {
00227                 x+= layoutMetric(LM_ExplicitButtonSpacer);
00228                 elementLayouted = true;
00229             }
00230             if (elementLayouted && it != m_buttonsLeft.end() )
00231                 x += buttonSpacing;
00232         }
00233     }
00234 
00235     if (m_buttonsRight.count() > 0) {
00236         const int titleEdgeRightLeft = r_x2-layoutMetric(LM_TitleEdgeRight)+1;
00237 
00238         const int buttonSpacing = layoutMetric(LM_ButtonSpacing);
00239         int x = titleEdgeRightLeft - buttonContainerWidth(m_buttonsRight);
00240         for (ButtonContainer::const_iterator it = m_buttonsRight.begin(); it != m_buttonsRight.end(); ++it) {
00241             bool elementLayouted = false;
00242             if (*it) {
00243                 if (!(*it)->isHidden() ) {
00244                     moveWidget(x,y, *it);
00245                     x += layoutMetric(LM_ButtonWidth, true, qobject_cast<KCommonDecorationButton*>(*it) );;
00246                     elementLayouted = true;
00247                 }
00248             } else {
00249                 x += layoutMetric(LM_ExplicitButtonSpacer);
00250                 elementLayouted = true;
00251             }
00252             if (elementLayouted && it != m_buttonsRight.end() )
00253                 x += buttonSpacing;
00254         }
00255     }
00256 }
00257 
00258 void KCommonDecoration::updateButtons() const
00259 {
00260     for (int n=0; n<NumButtons; n++)
00261         if (m_button[n]) m_button[n]->update();
00262 }
00263 
00264 void KCommonDecoration::resetButtons() const
00265 {
00266     for (int n=0; n<NumButtons; n++)
00267         if (m_button[n]) m_button[n]->reset(KCommonDecorationButton::ManualReset);
00268 }
00269 
00270 void KCommonDecoration::resetLayout()
00271 {
00272     for (int n=0; n<NumButtons; n++) {
00273         if (m_button[n]) {
00274             delete m_button[n];
00275             m_button[n] = 0;
00276         }
00277     }
00278     m_buttonsLeft.clear();
00279     m_buttonsRight.clear();
00280 
00281     delete m_previewWidget;
00282     m_previewWidget = 0;
00283 
00284     // shown instead of the window contents in decoration previews
00285     if(isPreview() ) {
00286         m_previewWidget = new QLabel(i18n("<center><b>%1 preview</b></center>", visibleName() ), widget());
00287         m_previewWidget->setAutoFillBackground(true);
00288         m_previewWidget->show();
00289     }
00290 
00291     addButtons(m_buttonsLeft,
00292                options()->customButtonPositions() ? options()->titleButtonsLeft() : defaultButtonsLeft(),
00293                true);
00294     addButtons(m_buttonsRight,
00295                options()->customButtonPositions() ? options()->titleButtonsRight() : defaultButtonsRight(),
00296                false);
00297 
00298     updateLayout();
00299 
00300     const int minTitleBarWidth = 35;
00301     btnHideMinWidth = buttonContainerWidth(m_buttonsLeft,true) + buttonContainerWidth(m_buttonsRight,true) +
00302             layoutMetric(LM_TitleEdgeLeft,false) + layoutMetric(LM_TitleEdgeRight,false) +
00303             layoutMetric(LM_TitleBorderLeft,false) + layoutMetric(LM_TitleBorderRight,false) +
00304             minTitleBarWidth;
00305     btnHideLastWidth = 0;
00306 }
00307 
00308 int KCommonDecoration::buttonsLeftWidth() const
00309 {
00310     return buttonContainerWidth(m_buttonsLeft);
00311 }
00312 
00313 int KCommonDecoration::buttonsRightWidth() const
00314 {
00315     return buttonContainerWidth(m_buttonsRight);
00316 }
00317 
00318 int KCommonDecoration::buttonContainerWidth(const ButtonContainer &btnContainer, bool countHidden) const
00319 {
00320     int explicitSpacer = layoutMetric(LM_ExplicitButtonSpacer);
00321 
00322     int shownElementsCount = 0;
00323 
00324     int w = 0;
00325     for (ButtonContainer::const_iterator it = btnContainer.begin(); it != btnContainer.end(); ++it) {
00326         if (*it) {
00327             if (countHidden || !(*it)->isHidden() ) {
00328                 w += (*it)->width();
00329                 ++shownElementsCount;
00330             }
00331         } else {
00332             w += explicitSpacer;
00333             ++shownElementsCount;
00334         }
00335     }
00336     w += layoutMetric(LM_ButtonSpacing)*(shownElementsCount-1);
00337 
00338     return w;
00339 }
00340 
00341 void KCommonDecoration::addButtons(ButtonContainer &btnContainer, const QString& s, bool isLeft)
00342 {
00343     if (s.length() > 0) {
00344         for (int n=0; n < s.length(); n++) {
00345             KCommonDecorationButton *btn = 0;
00346             switch (s[n].toAscii()) {
00347                 case 'M': // Menu button
00348                     if (!m_button[MenuButton]){
00349                         btn = createButton(MenuButton);
00350                         if (!btn) break;
00351                         btn->setTipText(i18n("Menu") );
00352                         btn->setRealizeButtons(Qt::LeftButton|Qt::RightButton);
00353                         connect(btn, SIGNAL(pressed()), SLOT(menuButtonPressed()));
00354                         connect(btn, SIGNAL(released()), this, SLOT(menuButtonReleased()));
00355 
00356                         m_button[MenuButton] = btn;
00357                     }
00358                     break;
00359                 case 'S': // OnAllDesktops button
00360                     if (!m_button[OnAllDesktopsButton]){
00361                         btn = createButton(OnAllDesktopsButton);
00362                         if (!btn) break;
00363                         const bool oad = isOnAllDesktops();
00364                         btn->setTipText(oad?i18n("Not on all desktops"):i18n("On all desktops") );
00365                         btn->setToggleButton(true);
00366                         btn->setOn( oad );
00367                         connect(btn, SIGNAL(clicked()), SLOT(toggleOnAllDesktops()));
00368 
00369                         m_button[OnAllDesktopsButton] = btn;
00370                     }
00371                     break;
00372                 case 'H': // Help button
00373                     if ((!m_button[HelpButton]) && providesContextHelp()){
00374                         btn = createButton(HelpButton);
00375                         if (!btn) break;
00376                         btn->setTipText(i18n("Help") );
00377                         connect(btn, SIGNAL(clicked()), SLOT(showContextHelp()));
00378 
00379                         m_button[HelpButton] = btn;
00380                     }
00381                     break;
00382                 case 'I': // Minimize button
00383                     if ((!m_button[MinButton]) && isMinimizable()){
00384                         btn = createButton(MinButton);
00385                         if (!btn) break;
00386                         btn->setTipText(i18n("Minimize") );
00387                         connect(btn, SIGNAL(clicked()), SLOT(minimize()));
00388 
00389                         m_button[MinButton] = btn;
00390                     }
00391                     break;
00392                 case 'A': // Maximize button
00393                     if ((!m_button[MaxButton]) && isMaximizable()){
00394                         btn = createButton(MaxButton);
00395                         if (!btn) break;
00396                         btn->setRealizeButtons(Qt::LeftButton|Qt::MidButton|Qt::RightButton);
00397                         const bool max = maximizeMode()==MaximizeFull;
00398                         btn->setTipText(max?i18n("Restore"):i18n("Maximize") );
00399                         btn->setToggleButton(true);
00400                         btn->setOn( max );
00401                         connect(btn, SIGNAL(clicked()), SLOT(slotMaximize()));
00402 
00403                         m_button[MaxButton] = btn;
00404                     }
00405                     break;
00406                 case 'X': // Close button
00407                     if ((!m_button[CloseButton]) && isCloseable()){
00408                         btn = createButton(CloseButton);
00409                         if (!btn) break;
00410                         btn->setTipText(i18n("Close") );
00411                         connect(btn, SIGNAL(clicked()), SLOT(closeWindow()));
00412 
00413                         m_button[CloseButton] = btn;
00414                     }
00415                     break;
00416                 case 'F': // AboveButton button
00417                     if (!m_button[AboveButton]){
00418                         btn = createButton(AboveButton);
00419                         if (!btn) break;
00420                         bool above = keepAbove();
00421                         btn->setTipText(above?i18n("Do not keep above others"):i18n("Keep above others") );
00422                         btn->setToggleButton(true);
00423                         btn->setOn( above );
00424                         connect(btn, SIGNAL(clicked()), SLOT(slotKeepAbove()));
00425 
00426                         m_button[AboveButton] = btn;
00427                     }
00428                     break;
00429                 case 'B': // BelowButton button
00430                     if (!m_button[BelowButton]){
00431                         btn = createButton(BelowButton);
00432                         if (!btn) break;
00433                         bool below = keepBelow();
00434                         btn->setTipText(below?i18n("Do not keep below others"):i18n("Keep below others") );
00435                         btn->setToggleButton(true);
00436                         btn->setOn( below );
00437                         connect(btn, SIGNAL(clicked()), SLOT(slotKeepBelow()));
00438 
00439                         m_button[BelowButton] = btn;
00440                     }
00441                     break;
00442                 case 'L': // Shade button
00443                     if ((!m_button[ShadeButton]) && isShadeable()){
00444                         btn = createButton(ShadeButton);
00445                         if (!btn) break;
00446                         bool shaded = isSetShade();
00447                         btn->setTipText(shaded?i18n("Unshade"):i18n("Shade") );
00448                         btn->setToggleButton(true);
00449                         btn->setOn( shaded );
00450                         connect(btn, SIGNAL(clicked()), SLOT(slotShade()));
00451 
00452                         m_button[ShadeButton] = btn;
00453                     }
00454                     break;
00455                 case '_': // Spacer item
00456                     btnContainer.append(0);
00457             }
00458 
00459 
00460             if (btn) {
00461                 btn->setLeft(isLeft);
00462                 btn->setSize(QSize(layoutMetric(LM_ButtonWidth, true, btn),layoutMetric(LM_ButtonHeight, true, btn)) );
00463                 btn->show();
00464                 btnContainer.append(btn);
00465             }
00466 
00467         }
00468     }
00469 }
00470 
00471 void KCommonDecoration::calcHiddenButtons()
00472 {
00473     if (width() == btnHideLastWidth)
00474         return;
00475 
00476     btnHideLastWidth = width();
00477 
00478     //Hide buttons in the following order:
00479     KCommonDecorationButton* btnArray[] = { m_button[HelpButton], m_button[ShadeButton], m_button[BelowButton],
00480         m_button[AboveButton], m_button[OnAllDesktopsButton], m_button[MaxButton],
00481         m_button[MinButton], m_button[MenuButton], m_button[CloseButton] };
00482     const int buttonsCount = sizeof( btnArray ) / sizeof( btnArray[ 0 ] );
00483 
00484     int current_width = width();
00485     int count = 0;
00486 
00487     // Hide buttons
00488     while (current_width < btnHideMinWidth && count < buttonsCount)
00489     {
00490         if (btnArray[count] ) {
00491             current_width += btnArray[count]->width();
00492             if (btnArray[count]->isVisible() )
00493                 btnArray[count]->hide();
00494         }
00495         count++;
00496     }
00497     // Show the rest of the buttons...
00498     for(int i = count; i < buttonsCount; i++)
00499     {
00500         if (btnArray[i] ) {
00501 
00502             if (! btnArray[i]->isHidden() )
00503                 break; // all buttons shown...
00504 
00505             btnArray[i]->show();
00506         }
00507     }
00508 }
00509 
00510 void KCommonDecoration::show()
00511 {
00512     if (decorationBehaviour(DB_ButtonHide) )
00513         calcHiddenButtons();
00514     widget()->show();
00515 }
00516 
00517 void KCommonDecoration::resize( const QSize& s )
00518 {
00519     widget()->resize( s );
00520 }
00521 
00522 QSize KCommonDecoration::minimumSize() const
00523 {
00524     const int minWidth = qMax(layoutMetric(LM_TitleEdgeLeft), layoutMetric(LM_BorderLeft))
00525             +qMax(layoutMetric(LM_TitleEdgeRight), layoutMetric(LM_BorderRight))
00526             +layoutMetric(LM_TitleBorderLeft)+layoutMetric(LM_TitleBorderRight);
00527     return QSize(minWidth,
00528                  layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)
00529                          +layoutMetric(LM_TitleEdgeBottom)
00530                          +layoutMetric(LM_BorderBottom) );
00531 }
00532 
00533 void KCommonDecoration::maximizeChange()
00534 {
00535     if( m_button[MaxButton] ) {
00536         m_button[MaxButton]->setOn( maximizeMode()==MaximizeFull);
00537         m_button[MaxButton]->setTipText( (maximizeMode()!=MaximizeFull) ?
00538                 i18n("Maximize")
00539             : i18n("Restore"));
00540         m_button[MaxButton]->reset(KCommonDecorationButton::StateChange);
00541     }
00542     updateWindowShape();
00543     widget()->update();
00544 }
00545 
00546 void KCommonDecoration::desktopChange()
00547 {
00548     if ( m_button[OnAllDesktopsButton] ) {
00549         m_button[OnAllDesktopsButton]->setOn( isOnAllDesktops() );
00550         m_button[OnAllDesktopsButton]->setTipText( isOnAllDesktops() ?
00551                 i18n("Not on all desktops")
00552             : i18n("On all desktops"));
00553         m_button[OnAllDesktopsButton]->reset(KCommonDecorationButton::StateChange);
00554     }
00555 }
00556 
00557 void KCommonDecoration::shadeChange()
00558 {
00559     if ( m_button[ShadeButton] ) {
00560         bool shaded = isSetShade();
00561         m_button[ShadeButton]->setOn( shaded );
00562         m_button[ShadeButton]->setTipText( shaded ?
00563                 i18n("Unshade")
00564             : i18n("Shade"));
00565         m_button[ShadeButton]->reset(KCommonDecorationButton::StateChange);
00566     }
00567 }
00568 
00569 void KCommonDecoration::iconChange()
00570 {
00571     if (m_button[MenuButton])
00572     {
00573         m_button[MenuButton]->update();
00574         m_button[MenuButton]->reset(KCommonDecorationButton::IconChange);
00575     }
00576 }
00577 
00578 void KCommonDecoration::activeChange()
00579 {
00580     updateButtons();
00581     widget()->update(); // do something similar to updateCaption here
00582 }
00583 
00584 void KCommonDecoration::captionChange()
00585 {
00586     updateCaption();
00587 }
00588 
00589 void KCommonDecoration::keepAboveChange(bool above)
00590 {
00591     if (m_button[AboveButton])
00592     {
00593         m_button[AboveButton]->setOn(above);
00594         m_button[AboveButton]->setTipText( above?i18n("Do not keep above others"):i18n("Keep above others") );
00595         m_button[AboveButton]->reset(KCommonDecorationButton::StateChange);
00596     }
00597 
00598     if (m_button[BelowButton] && m_button[BelowButton]->isChecked())
00599     {
00600         m_button[BelowButton]->setOn(false);
00601         m_button[BelowButton]->setTipText( i18n("Keep below others") );
00602         m_button[BelowButton]->reset(KCommonDecorationButton::StateChange);
00603     }
00604 }
00605 
00606 void KCommonDecoration::keepBelowChange(bool below)
00607 {
00608     if (m_button[BelowButton])
00609     {
00610         m_button[BelowButton]->setOn(below);
00611         m_button[BelowButton]->setTipText( below?i18n("Do not keep below others"):i18n("Keep below others") );
00612         m_button[BelowButton]->reset(KCommonDecorationButton::StateChange);
00613     }
00614 
00615     if (m_button[AboveButton] && m_button[AboveButton]->isChecked())
00616     {
00617         m_button[AboveButton]->setOn(false);
00618         m_button[AboveButton]->setTipText( i18n("Keep above others") );
00619         m_button[AboveButton]->reset(KCommonDecorationButton::StateChange);
00620     }
00621 }
00622 
00623 void KCommonDecoration::slotMaximize()
00624 {
00625     if (m_button[MaxButton])
00626     {
00627         maximize(m_button[MaxButton]->lastMousePress() );
00628     }
00629 }
00630 
00631 void KCommonDecoration::slotShade()
00632 {
00633     setShade( !isSetShade() );
00634 }
00635 
00636 void KCommonDecoration::slotKeepAbove()
00637 {
00638     setKeepAbove(!keepAbove() );
00639 }
00640 
00641 void KCommonDecoration::slotKeepBelow()
00642 {
00643     setKeepBelow(!keepBelow() );
00644 }
00645 
00646 void KCommonDecoration::menuButtonPressed()
00647 {
00648     static QTime* t = NULL;
00649     static KCommonDecoration* lastClient = NULL;
00650     if (t == NULL)
00651         t = new QTime;
00652     bool dbl = (lastClient==this && t->elapsed() <= QApplication::doubleClickInterval());
00653     lastClient = this;
00654     t->start();
00655     if (!dbl || !decorationBehaviour(DB_MenuClose) ) {
00656         QRect menuRect = m_button[MenuButton]->rect();
00657         QPoint menutop = m_button[MenuButton]->mapToGlobal(menuRect.topLeft());
00658         QPoint menubottom = m_button[MenuButton]->mapToGlobal(menuRect.bottomRight())+QPoint(0,2);
00659         KDecorationFactory* f = factory();
00660         showWindowMenu(QRect(menutop, menubottom));
00661         if( !f->exists( decoration())) // 'this' was deleted
00662             return;
00663         m_button[MenuButton]->setDown(false);
00664     }
00665     else
00666         closing = true;
00667 }
00668 
00669 void KCommonDecoration::menuButtonReleased()
00670 {
00671     if(closing)
00672         closeWindow();
00673 }
00674 
00675 void KCommonDecoration::resizeEvent(QResizeEvent */*e*/)
00676 {
00677     if (decorationBehaviour(DB_ButtonHide) )
00678         calcHiddenButtons();
00679 
00680     updateLayout();
00681 
00682     updateWindowShape();
00683     // FIXME: don't update() here! this would result in two paintEvent()s
00684     // because there is already "something" else triggering the repaint...
00685 //     widget()->update();
00686 }
00687 
00688 void KCommonDecoration::moveWidget(int x, int y, QWidget *widget) const
00689 {
00690     QPoint p = widget->pos();
00691     int oldX = p.y();
00692     int oldY = p.x();
00693 
00694     if (x!=oldX || y!=oldY)
00695         widget->move(x,y);
00696 }
00697 
00698 void KCommonDecoration::resizeWidget(int w, int h, QWidget *widget) const
00699 {
00700     QSize s = widget->size();
00701     int oldW = s.width();
00702     int oldH = s.height();
00703 
00704     if (w!=oldW || h!=oldH)
00705         widget->resize(w,h);
00706 }
00707 
00708 void KCommonDecoration::mouseDoubleClickEvent(QMouseEvent *e)
00709 {
00710     if( e->button() != Qt::LeftButton )
00711         return;
00712 
00713     int tb = layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeBottom);
00714     // when shaded, react on double clicks everywhere to make it easier to unshade. otherwise
00715     // react only on double clicks in the title bar region...
00716     if (isSetShade() || e->pos().y() <= tb )
00717         titlebarDblClickOperation();
00718 }
00719 
00720 void KCommonDecoration::wheelEvent(QWheelEvent *e)
00721 {
00722     int tb = layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeBottom);
00723     if (isSetShade() || e->pos().y() <= tb )
00724         titlebarMouseWheelOperation( e->delta());
00725 }
00726 
00727 KCommonDecoration::Position KCommonDecoration::mousePosition(const QPoint &point) const
00728 {
00729     const int corner = 18+3*layoutMetric(LM_BorderBottom, false)/2;
00730     Position pos = PositionCenter;
00731 
00732     QRect r = widget()->rect();
00733     int r_x, r_y, r_x2, r_y2;
00734     r.getCoords(&r_x, &r_y, &r_x2, &r_y2);
00735     int p_x = point.x();
00736     int p_y = point.y();
00737     const int borderLeft = layoutMetric(LM_BorderLeft);
00738 //     const int borderRight = layoutMetric(LM_BorderRight);
00739     const int borderBottom = layoutMetric(LM_BorderBottom);
00740     const int titleHeight = layoutMetric(LM_TitleHeight);
00741     const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
00742     const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
00743     const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
00744     const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);
00745 
00746     const int borderBottomTop = r_y2-borderBottom+1;
00747     const int borderLeftRight = r_x+borderLeft-1;
00748 //     const int borderRightLeft = r_x2-borderRight+1;
00749     const int titleEdgeLeftRight = r_x+titleEdgeLeft-1;
00750     const int titleEdgeRightLeft = r_x2-titleEdgeRight+1;
00751     const int titleEdgeBottomBottom = r_y+titleEdgeTop+titleHeight+titleEdgeBottom-1;
00752     const int titleEdgeTopBottom = r_y+titleEdgeTop-1;
00753 
00754     if (p_y <= titleEdgeTopBottom) {
00755         if (p_x <= r_x+corner)
00756             pos = PositionTopLeft;
00757         else if (p_x >= r_x2-corner)
00758             pos = PositionTopRight;
00759         else
00760             pos = PositionTop;
00761     } else if (p_y <= titleEdgeBottomBottom) {
00762         if (p_x <= titleEdgeLeftRight)
00763             pos = PositionTopLeft;
00764         else if (p_x >= titleEdgeRightLeft)
00765             pos = PositionTopRight;
00766         else
00767             pos = PositionCenter; // title bar
00768     } else if (p_y < borderBottomTop) {
00769         if      (p_y < r_y2-corner) {
00770             if (p_x <= borderLeftRight)
00771                 pos = PositionLeft;
00772             else
00773                 pos = PositionRight;
00774         } else {
00775             if (p_x <= borderLeftRight)
00776                 pos = PositionBottomLeft;
00777             else
00778                 pos = PositionBottomRight;
00779         }
00780     } else if(p_y >= borderBottomTop) {
00781         if (p_x <= r_x+corner)
00782             pos = PositionBottomLeft;
00783         else if (p_x >= r_x2-corner)
00784             pos = PositionBottomRight;
00785         else
00786             pos = PositionBottom;
00787     }
00788 
00789     return pos;
00790 }
00791 
00792 void KCommonDecoration::updateWindowShape()
00793 {
00794     // don't mask the widget...
00795     if (!decorationBehaviour(DB_WindowMask) )
00796         return;
00797 
00798     int w = widget()->width();
00799     int h = widget()->height();
00800 
00801     bool tl=true,tr=true,bl=true,br=true; // is there a transparent rounded corner in top-left? etc
00802 
00803     // no transparent rounded corners if this window corner lines up with a screen corner
00804     for(int screen=0; screen < Kephal::ScreenUtils::numScreens(); ++screen)
00805     {
00806         QRect fullscreen(Kephal::ScreenUtils::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 
01225 KCommonDecorationUnstable::KCommonDecorationUnstable(KDecorationBridge* bridge, KDecorationFactory* factory)
01226     : KCommonDecoration( bridge, factory )
01227     {
01228     Q_ASSERT( dynamic_cast<const KDecorationUnstable*>( decoration() ));
01229     }
01230 
01231 KCommonDecorationUnstable::~KCommonDecorationUnstable()
01232     {
01233     }
01234 
01235 // All copied from kdecoration.cpp
01236 QList<QRect> KCommonDecorationUnstable::shadowQuads( ShadowType type ) const
01237     {
01238     Q_UNUSED( type );
01239     return QList<QRect>();
01240     }
01241 double KCommonDecorationUnstable::shadowOpacity( ShadowType type ) const
01242     {
01243     if( isActive() && type == ShadowBorderedActive )
01244         return 1.0;
01245     else if( !isActive() && type == ShadowBorderedInactive )
01246         return 1.0;
01247     return 0.0;
01248     }
01249 double KCommonDecorationUnstable::shadowBrightness( ShadowType type ) const
01250     {
01251     Q_UNUSED( type );
01252     return 1.0;
01253     }
01254 double KCommonDecorationUnstable::shadowSaturation( ShadowType type ) const
01255     {
01256     Q_UNUSED( type );
01257     return 1.0;
01258     }
01259 
01260 void KCommonDecorationUnstable::repaintShadow()
01261     {
01262     return static_cast<const KDecorationUnstable*>( decoration() )->repaintShadow();
01263     }
01264 bool KCommonDecorationUnstable::compositingActive() const
01265     {
01266     return static_cast<const KDecorationUnstable*>( decoration() )->compositingActive();
01267     }
01268 bool KCommonDecorationUnstable::shadowsActive() const
01269     {
01270     return static_cast<const KDecorationUnstable*>( decoration() )->shadowsActive();
01271     }
01272 double KCommonDecorationUnstable::opacity() const
01273     {
01274     return static_cast<const KDecorationUnstable*>( decoration() )->opacity();
01275     }
01276 
01277 // kate: space-indent on; indent-width 4; mixedindent off; indent-mode cstyle;
01278 

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
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
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