• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kwin/lib
 

kwin/lib

kcommondecoration.cpp
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 <tqapplication.h>
00026 #include <tqcursor.h>
00027 #include <tqdatetime.h>
00028 #include <tqlabel.h>
00029 #include <tqtooltip.h>
00030 #include <tqwidget.h>
00031 
00032 #include <kdebug.h>
00033 
00034 #include <kapplication.h>
00035 #include <kdecorationfactory.h>
00036 #include <klocale.h>
00037 
00038 #include <X11/Xlib.h>
00039 #include <X11/Xatom.h>
00040 
00041 #include "kcommondecoration.h"
00042 #include "kcommondecoration.moc"
00043 
00044 KCommonDecoration::KCommonDecoration(KDecorationBridge* bridge, KDecorationFactory* factory)
00045     : KDecoration (bridge, factory),
00046         m_previewWidget(0),
00047         btnHideMinWidth(200),
00048         btnHideLastWidth(0),
00049         closing(false)
00050 {
00051     // sizeof(...) is calculated at compile time
00052     memset(m_button, 0, sizeof(KCommonDecorationButton *) * NumButtons);
00053 }
00054 
00055 KCommonDecoration::~KCommonDecoration()
00056 {
00057     for (int n=0; n<NumButtons; n++) {
00058         if (m_button[n]) delete m_button[n];
00059     }
00060     delete m_previewWidget;
00061 }
00062 
00063 bool KCommonDecoration::decorationBehaviour(DecorationBehaviour behaviour) const
00064 {
00065     switch (behaviour) {
00066         case DB_MenuClose:
00067             return false;
00068 
00069         case DB_WindowMask:
00070             return false;
00071 
00072         case DB_ButtonHide:
00073             return true;
00074     }
00075 
00076     return false;
00077 }
00078 
00079 int KCommonDecoration::layoutMetric(LayoutMetric lm, bool, const KCommonDecorationButton *) const
00080 {
00081     switch (lm) {
00082         case LM_BorderLeft:
00083         case LM_BorderRight:
00084         case LM_BorderBottom:
00085         case LM_TitleEdgeTop:
00086         case LM_TitleEdgeBottom:
00087         case LM_TitleEdgeLeft:
00088         case LM_TitleEdgeRight:
00089         case LM_TitleBorderLeft:
00090         case LM_TitleBorderRight:
00091             return 5;
00092 
00093 
00094         case LM_ButtonWidth:
00095         case LM_ButtonHeight:
00096         case LM_TitleHeight:
00097             return 20;
00098 
00099         case LM_ButtonSpacing:
00100             return 5;
00101 
00102         case LM_ButtonMarginTop:
00103         case LM_RightButtonsMarginTop:
00104             return 0;
00105 
00106         case LM_ExplicitButtonSpacer:
00107             return 5;
00108 
00109         default:
00110             return 0;
00111     }
00112 }
00113 
00114 void KCommonDecoration::init()
00115 {
00116     createMainWidget(TQt::WNoAutoErase);
00117 
00118     // for flicker-free redraws
00119     widget()->setBackgroundMode(NoBackground);
00120 
00121     widget()->installEventFilter( this );
00122 
00123     resetLayout();
00124 
00125     connect(this, TQT_SIGNAL(keepAboveChanged(bool) ), TQT_SLOT(keepAboveChange(bool) ) );
00126     connect(this, TQT_SIGNAL(keepBelowChanged(bool) ), TQT_SLOT(keepBelowChange(bool) ) );
00127 
00128     updateCaption();
00129 }
00130 
00131 void KCommonDecoration::reset( unsigned long changed )
00132 {
00133     if (changed & SettingButtons) {
00134         resetLayout();
00135         widget()->update();
00136     }
00137 }
00138 
00139 TQRegion KCommonDecoration::cornerShape(WindowCorner)
00140 {
00141     return TQRegion();
00142 }
00143 
00144 void KCommonDecoration::updateCaption()
00145 {
00146     // This should be reimplemented in decorations for better efficiency
00147     widget()->update();
00148 }
00149 
00150 void KCommonDecoration::borders( int& left, int& right, int& top, int& bottom ) const
00151 {
00152     left = layoutMetric(LM_BorderLeft);
00153     right = layoutMetric(LM_BorderRight);
00154     bottom = layoutMetric(LM_BorderBottom);
00155     top = layoutMetric(LM_TitleHeight) +
00156             layoutMetric(LM_TitleEdgeTop) +
00157             layoutMetric(LM_TitleEdgeBottom);
00158 
00159     updateLayout(); // TODO!! don't call everytime we are in ::borders
00160 }
00161 
00162 void KCommonDecoration::updateLayout() const
00163 {
00164     TQRect r = widget()->rect();
00165     int r_x, r_y, r_x2, r_y2;
00166     r.coords(&r_x, &r_y, &r_x2, &r_y2);
00167 
00168     // layout preview widget
00169     if (m_previewWidget) {
00170         const int borderLeft = layoutMetric(LM_BorderLeft);
00171         const int borderRight = layoutMetric(LM_BorderRight);
00172         const int borderBottom = layoutMetric(LM_BorderBottom);
00173         const int titleHeight = layoutMetric(LM_TitleHeight);
00174         const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
00175         const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
00176 
00177         int left = r_x+borderLeft;
00178         int top = r_y+titleEdgeTop+titleHeight+titleEdgeBottom;
00179         int width = r_x2-borderRight-left+1;
00180         int height = r_y2-borderBottom-top+1;
00181         m_previewWidget->setGeometry(left, top, width, height);
00182         moveWidget(left,top, m_previewWidget);
00183         resizeWidget(width, height, m_previewWidget);
00184     }
00185 
00186     // resize buttons...
00187     for (int n=0; n<NumButtons; n++) {
00188         if (m_button[n]) {
00189             TQSize newSize = TQSize(layoutMetric(LM_ButtonWidth, true, m_button[n]),
00190                                   layoutMetric(LM_ButtonHeight, true, m_button[n]) );
00191             if (newSize != m_button[n]->size() )
00192                 m_button[n]->setSize(newSize);
00193         }
00194     }
00195 
00196     // layout buttons
00197     int y = r_y + layoutMetric(LM_TitleEdgeTop) + layoutMetric(LM_ButtonMarginTop);
00198     if (m_buttonsLeft.count() > 0) {
00199         const int buttonSpacing = layoutMetric(LM_ButtonSpacing);
00200         int x = r_x + layoutMetric(LM_TitleEdgeLeft);
00201         for (ButtonContainer::const_iterator it = m_buttonsLeft.begin(); it != m_buttonsLeft.end(); ++it) {
00202             bool elementLayouted = false;
00203             if (*it) {
00204                 if (!(*it)->isHidden() ) {
00205                     moveWidget(x,y, *it);
00206                     x += layoutMetric(LM_ButtonWidth, true, ::tqqt_cast<KCommonDecorationButton*>(*it) );
00207                     elementLayouted = true;
00208                 }
00209             } else {
00210                 x+= layoutMetric(LM_ExplicitButtonSpacer);
00211                 elementLayouted = true;
00212             }
00213             if (elementLayouted && it != m_buttonsLeft.end() )
00214                 x += buttonSpacing;
00215         }
00216     }
00217 
00218     if (m_buttonsRight.count() > 0) {
00219         int y = r_y + layoutMetric(LM_TitleEdgeTop) + layoutMetric(LM_ButtonMarginTop) + layoutMetric(LM_RightButtonsMarginTop);
00220         const int titleEdgeRightLeft = r_x2-layoutMetric(LM_TitleEdgeRight)+1;
00221 
00222         const int buttonSpacing = layoutMetric(LM_ButtonSpacing);
00223         int x = titleEdgeRightLeft - buttonContainerWidth(m_buttonsRight);
00224         for (ButtonContainer::const_iterator it = m_buttonsRight.begin(); it != m_buttonsRight.end(); ++it) {
00225             bool elementLayouted = false;
00226             if (*it) {
00227                 if (!(*it)->isHidden() ) {
00228                     moveWidget(x,y, *it);
00229                     x += layoutMetric(LM_ButtonWidth, true, ::tqqt_cast<KCommonDecorationButton*>(*it) );;
00230                     elementLayouted = true;
00231                 }
00232             } else {
00233                 x += layoutMetric(LM_ExplicitButtonSpacer);
00234                 elementLayouted = true;
00235             }
00236             if (elementLayouted && it != m_buttonsRight.end() )
00237                 x += buttonSpacing;
00238         }
00239     }
00240 }
00241 
00242 void KCommonDecoration::updateButtons() const
00243 {
00244     for (int n=0; n<NumButtons; n++)
00245         if (m_button[n]) m_button[n]->update();
00246 }
00247 
00248 void KCommonDecoration::resetButtons() const
00249 {
00250     for (int n=0; n<NumButtons; n++)
00251         if (m_button[n]) m_button[n]->reset(KCommonDecorationButton::ManualReset);
00252 }
00253 
00254 void KCommonDecoration::resetLayout()
00255 {
00256     for (int n=0; n<NumButtons; n++) {
00257         if (m_button[n]) {
00258             delete m_button[n];
00259             m_button[n] = 0;
00260         }
00261     }
00262     m_buttonsLeft.clear();
00263     m_buttonsRight.clear();
00264 
00265     delete m_previewWidget;
00266     m_previewWidget = 0;
00267 
00268     // shown instead of the window contents in decoration previews
00269     if(isPreview() ) {
00270         m_previewWidget = new TQLabel(i18n("%1 is the name of window decoration style", "<center><b>%1 preview</b></center>").arg(visibleName() ), widget());
00271         m_previewWidget->show();
00272     }
00273 
00274     addButtons(m_buttonsLeft,
00275                options()->customButtonPositions() ? options()->titleButtonsLeft() : defaultButtonsLeft(),
00276                true);
00277     addButtons(m_buttonsRight,
00278                options()->customButtonPositions() ? options()->titleButtonsRight() : defaultButtonsRight(),
00279                false);
00280 
00281     updateLayout();
00282 
00283     const int minTitleBarWidth = 35;
00284     btnHideMinWidth = buttonContainerWidth(m_buttonsLeft,true) + buttonContainerWidth(m_buttonsRight,true) +
00285             layoutMetric(LM_TitleEdgeLeft,false) + layoutMetric(LM_TitleEdgeRight,false) +
00286             layoutMetric(LM_TitleBorderLeft,false) + layoutMetric(LM_TitleBorderRight,false) +
00287             minTitleBarWidth;
00288     btnHideLastWidth = 0;
00289 }
00290 
00291 int KCommonDecoration::buttonsLeftWidth() const
00292 {
00293     return buttonContainerWidth(m_buttonsLeft);
00294 }
00295 
00296 int KCommonDecoration::buttonsRightWidth() const
00297 {
00298     return buttonContainerWidth(m_buttonsRight);
00299 }
00300 
00301 int KCommonDecoration::buttonContainerWidth(const ButtonContainer &btnContainer, bool countHidden) const
00302 {
00303     int explicitSpacer = layoutMetric(LM_ExplicitButtonSpacer);
00304 
00305     int shownElementsCount = 0;
00306 
00307     int w = 0;
00308     for (ButtonContainer::const_iterator it = btnContainer.begin(); it != btnContainer.end(); ++it) {
00309         if (*it) {
00310             if (countHidden || !(*it)->isHidden() ) {
00311                 w += (*it)->width();
00312                 ++shownElementsCount;
00313             }
00314         } else {
00315             w += explicitSpacer;
00316             ++shownElementsCount;
00317         }
00318     }
00319     w += layoutMetric(LM_ButtonSpacing)*(shownElementsCount-1);
00320 
00321     return w;
00322 }
00323 
00324 bool KCommonDecoration::isModalSystemNotification()
00325 {
00326     unsigned char *data = 0;
00327     Atom actual;
00328     int format, result;
00329     unsigned long n, left;
00330     Atom kde_wm_system_modal_notification;
00331     kde_wm_system_modal_notification = XInternAtom(qt_xdisplay(), "_KDE_WM_MODAL_SYS_NOTIFICATION", False);
00332     result = XGetWindowProperty(qt_xdisplay(), windowId(), kde_wm_system_modal_notification, 0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left, /*(unsigned char **)*/ &data);
00333     if (result == Success && data != None && format == 32 )
00334         {
00335         return TRUE;
00336         }
00337     return FALSE;
00338 }
00339 
00340 void KCommonDecoration::addButtons(ButtonContainer &btnContainer, const TQString& s, bool isLeft)
00341 {
00342     if (s.length() > 0) {
00343         for (unsigned n=0; n < s.length(); n++) {
00344             KCommonDecorationButton *btn = 0;
00345             switch (s[n]) {
00346               case 'M': // Menu button
00347                   if (!isModalSystemNotification()) {
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, TQT_SIGNAL(pressed()), TQT_SLOT(menuButtonPressed()));
00354                           connect(btn, TQT_SIGNAL(released()), this, TQT_SLOT(menuButtonReleased()));
00355 
00356                           m_button[MenuButton] = btn;
00357                       }
00358                   }
00359                   break;
00360               case 'S': // OnAllDesktops button
00361                   if (!isModalSystemNotification()) {
00362                       if (!m_button[OnAllDesktopsButton]){
00363                           btn = createButton(OnAllDesktopsButton);
00364                           if (!btn) break;
00365                           const bool oad = isOnAllDesktops();
00366                           btn->setTipText(oad?i18n("Not on all desktops"):i18n("On all desktops") );
00367                           btn->setToggleButton(true);
00368                           btn->setOn( oad );
00369                           connect(btn, TQT_SIGNAL(clicked()), TQT_SLOT(toggleOnAllDesktops()));
00370 
00371                           m_button[OnAllDesktopsButton] = btn;
00372                       }
00373                   }
00374                   break;
00375               case 'H': // Help button
00376                   if ((!m_button[HelpButton]) && providesContextHelp()){
00377                       btn = createButton(HelpButton);
00378                       if (!btn) break;
00379                       btn->setTipText(i18n("Help") );
00380                       connect(btn, TQT_SIGNAL(clicked()), TQT_SLOT(showContextHelp()));
00381 
00382                       m_button[HelpButton] = btn;
00383                   }
00384                   break;
00385               case 'I': // Minimize button
00386                   if ((!m_button[MinButton]) && isMinimizable()){
00387                       btn = createButton(MinButton);
00388                       if (!btn) break;
00389                       btn->setTipText(i18n("Minimize") );
00390                       connect(btn, TQT_SIGNAL(clicked()), TQT_SLOT(minimize()));
00391 
00392                       m_button[MinButton] = btn;
00393                   }
00394                   break;
00395               case 'A': // Maximize button
00396                   if ((!m_button[MaxButton]) && isMaximizable()){
00397                       btn = createButton(MaxButton);
00398                       if (!btn) break;
00399                       btn->setRealizeButtons(Qt::LeftButton|Qt::MidButton|Qt::RightButton);
00400                       const bool max = maximizeMode()==MaximizeFull;
00401                       btn->setTipText(max?i18n("Restore"):i18n("Maximize") );
00402                       btn->setToggleButton(true);
00403                       btn->setOn( max );
00404                       connect(btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotMaximize()));
00405 
00406                       m_button[MaxButton] = btn;
00407                   }
00408                   break;
00409               case 'X': // Close button
00410                   if ((!m_button[CloseButton]) && isCloseable()){
00411                       btn = createButton(CloseButton);
00412                       if (!btn) break;
00413                       btn->setTipText(i18n("Close") );
00414                       connect(btn, TQT_SIGNAL(clicked()), TQT_SLOT(closeWindow()));
00415 
00416                       m_button[CloseButton] = btn;
00417                   }
00418                   break;
00419               case 'F': // AboveButton button
00420                   if (!m_button[AboveButton]){
00421                       btn = createButton(AboveButton);
00422                       if (!btn) break;
00423                       bool above = keepAbove();
00424                       btn->setTipText(above?i18n("Do not keep above others"):i18n("Keep above others") );
00425                       btn->setToggleButton(true);
00426                       btn->setOn( above );
00427                       connect(btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotKeepAbove()));
00428 
00429                       m_button[AboveButton] = btn;
00430                   }
00431                   break;
00432               case 'B': // BelowButton button
00433                   if (!m_button[BelowButton]){
00434                       btn = createButton(BelowButton);
00435                       if (!btn) break;
00436                       bool below = keepBelow();
00437                       btn->setTipText(below?i18n("Do not keep below others"):i18n("Keep below others") );
00438                       btn->setToggleButton(true);
00439                       btn->setOn( below );
00440                       connect(btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotKeepBelow()));
00441 
00442                       m_button[BelowButton] = btn;
00443                   }
00444                   break;
00445               case 'L': // Shade button
00446                   if ((!m_button[ShadeButton]) && isShadeable()){
00447                       btn = createButton(ShadeButton);
00448                       if (!btn) break;
00449                       bool shaded = isSetShade();
00450                       btn->setTipText(shaded?i18n("Unshade"):i18n("Shade") );
00451                       btn->setToggleButton(true);
00452                       btn->setOn( shaded );
00453                       connect(btn, TQT_SIGNAL(clicked()), TQT_SLOT(slotShade()));
00454 
00455                       m_button[ShadeButton] = btn;
00456                   }
00457                   break;
00458               case '_': // Spacer item
00459                   btnContainer.append(0);
00460             }
00461 
00462 
00463             if (btn) {
00464                 btn->setLeft(isLeft);
00465                 btn->setSize(TQSize(layoutMetric(LM_ButtonWidth, true, btn),layoutMetric(LM_ButtonHeight, true, btn)) );
00466                 btn->show();
00467                 btnContainer.append(btn);
00468             }
00469 
00470         }
00471     }
00472 }
00473 
00474 void KCommonDecoration::calcHiddenButtons()
00475 {
00476     if (width() == btnHideLastWidth)
00477         return;
00478 
00479     btnHideLastWidth = width();
00480 
00481     //Hide buttons in the following order:
00482     KCommonDecorationButton* btnArray[] = { m_button[HelpButton], m_button[ShadeButton], m_button[BelowButton],
00483         m_button[AboveButton], m_button[OnAllDesktopsButton], m_button[MaxButton],
00484         m_button[MinButton], m_button[MenuButton], m_button[CloseButton] };
00485     const int buttonsCount = sizeof( btnArray ) / sizeof( btnArray[ 0 ] );
00486 
00487     int current_width = width();
00488     int count = 0;
00489 
00490     // Hide buttons
00491     while (current_width < btnHideMinWidth && count < buttonsCount)
00492     {
00493         if (btnArray[count] ) {
00494             current_width += btnArray[count]->width();
00495             if (btnArray[count]->isVisible() )
00496                 btnArray[count]->hide();
00497         }
00498         count++;
00499     }
00500     // Show the rest of the buttons...
00501     for(int i = count; i < buttonsCount; i++)
00502     {
00503         if (btnArray[i] ) {
00504 
00505             if (! btnArray[i]->isHidden() )
00506                 break; // all buttons shown...
00507 
00508             btnArray[i]->show();
00509         }
00510     }
00511 }
00512 
00513 void KCommonDecoration::show()
00514 {
00515     if (decorationBehaviour(DB_ButtonHide) )
00516         calcHiddenButtons();
00517     widget()->show();
00518 }
00519 
00520 void KCommonDecoration::resize( const TQSize& s )
00521 {
00522     widget()->resize( s );
00523 }
00524 
00525 TQSize KCommonDecoration::minimumSize() const
00526 {
00527     const int minWidth = QMAX(layoutMetric(LM_TitleEdgeLeft), layoutMetric(LM_BorderLeft))
00528             +QMAX(layoutMetric(LM_TitleEdgeRight), layoutMetric(LM_BorderRight))
00529             +layoutMetric(LM_TitleBorderLeft)+layoutMetric(LM_TitleBorderRight);
00530     return TQSize(minWidth,
00531                  layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)
00532                          +layoutMetric(LM_TitleEdgeBottom)
00533                          +layoutMetric(LM_BorderBottom) );
00534 }
00535 
00536 void KCommonDecoration::maximizeChange()
00537 {
00538     if( m_button[MaxButton] ) {
00539         m_button[MaxButton]->setOn( maximizeMode()==MaximizeFull);
00540         m_button[MaxButton]->setTipText( (maximizeMode()!=MaximizeFull) ?
00541                 i18n("Maximize")
00542             : i18n("Restore"));
00543         m_button[MaxButton]->reset(KCommonDecorationButton::StateChange);
00544     }
00545     updateWindowShape();
00546     widget()->update();
00547 }
00548 
00549 void KCommonDecoration::desktopChange()
00550 {
00551     if ( m_button[OnAllDesktopsButton] ) {
00552         m_button[OnAllDesktopsButton]->setOn( isOnAllDesktops() );
00553         m_button[OnAllDesktopsButton]->setTipText( isOnAllDesktops() ?
00554                 i18n("Not on all desktops")
00555             : i18n("On all desktops"));
00556         m_button[OnAllDesktopsButton]->reset(KCommonDecorationButton::StateChange);
00557     }
00558 }
00559 
00560 void KCommonDecoration::shadeChange()
00561 {
00562     if ( m_button[ShadeButton] ) {
00563         bool shaded = isSetShade();
00564         m_button[ShadeButton]->setOn( shaded );
00565         m_button[ShadeButton]->setTipText( shaded ?
00566                 i18n("Unshade")
00567             : i18n("Shade"));
00568         m_button[ShadeButton]->reset(KCommonDecorationButton::StateChange);
00569     }
00570 }
00571 
00572 void KCommonDecoration::iconChange()
00573 {
00574     if (m_button[MenuButton])
00575     {
00576         m_button[MenuButton]->update();
00577         m_button[MenuButton]->reset(KCommonDecorationButton::IconChange);
00578     }
00579 }
00580 
00581 void KCommonDecoration::activeChange()
00582 {
00583     updateButtons();
00584     widget()->update(); // do something similar to updateCaption here
00585 }
00586 
00587 void KCommonDecoration::captionChange()
00588 {
00589     updateCaption();
00590 }
00591 
00592 void KCommonDecoration::keepAboveChange(bool above)
00593 {
00594     if (m_button[AboveButton])
00595     {
00596         m_button[AboveButton]->setOn(above);
00597         m_button[AboveButton]->setTipText( above?i18n("Do not keep above others"):i18n("Keep above others") );
00598         m_button[AboveButton]->reset(KCommonDecorationButton::StateChange);
00599     }
00600 
00601     if (m_button[BelowButton] && m_button[BelowButton]->isOn())
00602     {
00603         m_button[BelowButton]->setOn(false);
00604         m_button[BelowButton]->setTipText( i18n("Keep below others") );
00605         m_button[BelowButton]->reset(KCommonDecorationButton::StateChange);
00606     }
00607 }
00608 
00609 void KCommonDecoration::keepBelowChange(bool below)
00610 {
00611     if (m_button[BelowButton])
00612     {
00613         m_button[BelowButton]->setOn(below);
00614         m_button[BelowButton]->setTipText( below?i18n("Do not keep below others"):i18n("Keep below others") );
00615         m_button[BelowButton]->reset(KCommonDecorationButton::StateChange);
00616     }
00617 
00618     if (m_button[AboveButton] && m_button[AboveButton]->isOn())
00619     {
00620         m_button[AboveButton]->setOn(false);
00621         m_button[AboveButton]->setTipText( i18n("Keep above others") );
00622         m_button[AboveButton]->reset(KCommonDecorationButton::StateChange);
00623     }
00624 }
00625 
00626 void KCommonDecoration::slotMaximize()
00627 {
00628     if (m_button[MaxButton])
00629     {
00630         maximize(m_button[MaxButton]->lastMousePress() );
00631     }
00632 }
00633 
00634 void KCommonDecoration::slotShade()
00635 {
00636     setShade( !isSetShade() );
00637 }
00638 
00639 void KCommonDecoration::slotKeepAbove()
00640 {
00641     setKeepAbove(!keepAbove() );
00642 }
00643 
00644 void KCommonDecoration::slotKeepBelow()
00645 {
00646     setKeepBelow(!keepBelow() );
00647 }
00648 
00649 void KCommonDecoration::menuButtonPressed()
00650 {
00651     static TQTime* t = NULL;
00652     static KCommonDecoration* lastClient = NULL;
00653     if (t == NULL)
00654         t = new TQTime;
00655     bool dbl = (lastClient==this && t->elapsed() <= TQApplication::doubleClickInterval());
00656     lastClient = this;
00657     t->start();
00658     if (!dbl || !decorationBehaviour(DB_MenuClose) ) {
00659         TQRect menuRect = m_button[MenuButton]->rect();
00660         TQPoint menutop = m_button[MenuButton]->mapToGlobal(menuRect.topLeft());
00661         TQPoint menubottom = m_button[MenuButton]->mapToGlobal(menuRect.bottomRight())+TQPoint(0,2);
00662         KDecorationFactory* f = factory();
00663         showWindowMenu(TQRect(menutop, menubottom));
00664         if( !f->exists( this )) // 'this' was deleted
00665             return;
00666         m_button[MenuButton]->setDown(false);
00667     }
00668     else
00669         closing = true;
00670 }
00671 
00672 void KCommonDecoration::menuButtonReleased()
00673 {
00674     if(closing)
00675         closeWindow();
00676 }
00677 
00678 void KCommonDecoration::resizeEvent(TQResizeEvent */*e*/)
00679 {
00680     if (decorationBehaviour(DB_ButtonHide) )
00681         calcHiddenButtons();
00682 
00683     updateLayout();
00684 
00685     updateWindowShape();
00686     // FIXME: don't update() here! this would result in two paintEvent()s
00687     // because there is already "something" else triggering the repaint...
00688 //     widget()->update();
00689 }
00690 
00691 void KCommonDecoration::moveWidget(int x, int y, TQWidget *widget) const
00692 {
00693     TQPoint p = widget->pos();
00694     int oldX = p.y();
00695     int oldY = p.x();
00696 
00697     if (x!=oldX || y!=oldY)
00698         widget->move(x,y);
00699 }
00700 
00701 void KCommonDecoration::resizeWidget(int w, int h, TQWidget *widget) const
00702 {
00703     TQSize s = widget->size();
00704     int oldW = s.width();
00705     int oldH = s.height();
00706 
00707     if (w!=oldW || h!=oldH)
00708         widget->resize(w,h);
00709 }
00710 
00711 void KCommonDecoration::mouseDoubleClickEvent(TQMouseEvent *e)
00712 {
00713     if( e->button() != Qt::LeftButton )
00714         return;
00715 
00716     int tb = layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeBottom);
00717     // when shaded, react on double clicks everywhere to make it easier to unshade. otherwise
00718     // react only on double clicks in the title bar region...
00719     if (isSetShade() || e->pos().y() <= tb )
00720         titlebarDblClickOperation();
00721 }
00722 
00723 void KCommonDecoration::wheelEvent(TQWheelEvent *e)
00724 {
00725     int tb = layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeBottom);
00726     if (isSetShade() || e->pos().y() <= tb )
00727         titlebarMouseWheelOperation( e->delta());
00728 }
00729 
00730 KCommonDecoration::Position KCommonDecoration::mousePosition(const TQPoint &point) const
00731 {
00732     const int corner = 18+3*layoutMetric(LM_BorderBottom, false)/2;
00733     Position pos = PositionCenter;
00734 
00735     TQRect r = widget()->rect();
00736     int r_x, r_y, r_x2, r_y2;
00737     r.coords(&r_x, &r_y, &r_x2, &r_y2);
00738     int p_x = point.x();
00739     int p_y = point.y();
00740     const int borderLeft = layoutMetric(LM_BorderLeft);
00741 //     const int borderRight = layoutMetric(LM_BorderRight);
00742     const int borderBottom = layoutMetric(LM_BorderBottom);
00743     const int titleHeight = layoutMetric(LM_TitleHeight);
00744     const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
00745     const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
00746     const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
00747     const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);
00748 
00749     const int borderBottomTop = r_y2-borderBottom+1;
00750     const int borderLeftRight = r_x+borderLeft-1;
00751 //     const int borderRightLeft = r_x2-borderRight+1;
00752     const int titleEdgeLeftRight = r_x+titleEdgeLeft-1;
00753     const int titleEdgeRightLeft = r_x2-titleEdgeRight+1;
00754     const int titleEdgeBottomBottom = r_y+titleEdgeTop+titleHeight+titleEdgeBottom-1;
00755     const int titleEdgeTopBottom = r_y+titleEdgeTop-1;
00756 
00757     if (p_y <= titleEdgeTopBottom) {
00758         if (p_x <= r_x+corner)
00759             pos = PositionTopLeft;
00760         else if (p_x >= r_x2-corner)
00761             pos = PositionTopRight;
00762         else
00763             pos = PositionTop;
00764     } else if (p_y <= titleEdgeBottomBottom) {
00765         if (p_x <= titleEdgeLeftRight)
00766             pos = PositionTopLeft;
00767         else if (p_x >= titleEdgeRightLeft)
00768             pos = PositionTopRight;
00769         else
00770             pos = PositionCenter; // title bar
00771     } else if (p_y < borderBottomTop) {
00772         if      (p_y < r_y2-corner) {
00773             if (p_x <= borderLeftRight)
00774                 pos = PositionLeft;
00775             else
00776                 pos = PositionRight;
00777         } else {
00778             if (p_x <= borderLeftRight)
00779                 pos = PositionBottomLeft;
00780             else
00781                 pos = PositionBottomRight;
00782         }
00783     } else if(p_y >= borderBottomTop) {
00784         if (p_x <= r_x+corner)
00785             pos = PositionBottomLeft;
00786         else if (p_x >= r_x2-corner)
00787             pos = PositionBottomRight;
00788         else
00789             pos = PositionBottom;
00790     }
00791 
00792     return pos;
00793 }
00794 
00795 void KCommonDecoration::updateWindowShape()
00796 {
00797     // don't mask the widget...
00798     if (!decorationBehaviour(DB_WindowMask) )
00799         return;
00800 
00801     int w = widget()->width();
00802     int h = widget()->height();
00803 
00804     bool tl=true,tr=true,bl=true,br=true; // is there a transparent rounded corner in top-left? etc
00805 
00806     TQDesktopWidget *desktop=KApplication::desktop();
00807     // no transparent rounded corners if this window corner lines up with a screen corner
00808     for(int screen=0; screen < desktop->numScreens(); ++screen)
00809     {
00810         TQRect fullscreen(desktop->screenGeometry(screen));
00811         TQRect window = geometry();
00812 
00813         if(window.topLeft()    == fullscreen.topLeft() ) tl = false;
00814         if(window.topRight()   == fullscreen.topRight() ) tr = false;
00815         if(window.bottomLeft() == fullscreen.bottomLeft() ) bl = false;
00816         if(window.bottomRight()== fullscreen.bottomRight() ) br = false;
00817     }
00818 
00819     TQRegion mask(0, 0, w, h);
00820 
00821     // Remove top-left corner.
00822     if(tl)
00823     {
00824         mask -= cornerShape(WC_TopLeft);
00825     }
00826     // Remove top-right corner.
00827     if(tr)
00828     {
00829         mask -= cornerShape(WC_TopRight);
00830     }
00831         // Remove top-left corner.
00832     if(bl)
00833     {
00834         mask -= cornerShape(WC_BottomLeft);
00835     }
00836     // Remove top-right corner.
00837     if(br)
00838     {
00839         mask -= cornerShape(WC_BottomRight);
00840     }
00841 
00842     setMask( mask );
00843 }
00844 
00845 bool KCommonDecoration::eventFilter( TQObject* o, TQEvent* e )
00846 {
00847     if( TQT_BASE_OBJECT(o) != TQT_BASE_OBJECT(widget()))
00848         return false;
00849     switch( e->type())
00850     {
00851         case TQEvent::Resize:
00852             resizeEvent(TQT_TQRESIZEEVENT(e) );
00853             return true;
00854         case TQEvent::Paint:
00855             paintEvent(TQT_TQPAINTEVENT( e ));
00856             return true;
00857         case TQEvent::MouseButtonDblClick:
00858             mouseDoubleClickEvent(TQT_TQMOUSEEVENT( e ));
00859             return true;
00860         case TQEvent::MouseButtonPress:
00861             processMousePressEvent(TQT_TQMOUSEEVENT( e ));
00862             return true;
00863         case TQEvent::Wheel:
00864             wheelEvent(TQT_TQWHEELEVENT( e ));
00865             return true;
00866         default:
00867             return false;
00868     }
00869 }
00870 
00871 const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
00872         | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask
00873         | NET::UtilityMask | NET::SplashMask;
00874 
00875 bool KCommonDecoration::isToolWindow() const
00876 {
00877     NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK );
00878     return ((type==NET::Toolbar)||(type==NET::Utility)||(type==NET::Menu));
00879 }
00880 
00881 TQRect KCommonDecoration::titleRect() const
00882 {
00883     int r_x, r_y, r_x2, r_y2;
00884     TQT_TQRECT_OBJECT(widget()->rect()).coords(&r_x, &r_y, &r_x2, &r_y2);
00885     const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
00886     const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
00887     const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);
00888     const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
00889     const int titleBorderLeft = layoutMetric(LM_TitleBorderLeft);
00890     const int titleBorderRight = layoutMetric(LM_TitleBorderRight);
00891     const int ttlHeight = layoutMetric(LM_TitleHeight);
00892     const int titleEdgeBottomBottom = r_y+titleEdgeTop+ttlHeight+titleEdgeBottom-1;
00893     return TQRect(r_x+titleEdgeLeft+buttonsLeftWidth()+titleBorderLeft, r_y+titleEdgeTop,
00894               r_x2-titleEdgeRight-buttonsRightWidth()-titleBorderRight-(r_x+titleEdgeLeft+buttonsLeftWidth()+titleBorderLeft),
00895               titleEdgeBottomBottom-(r_y+titleEdgeTop) );
00896 }
00897 
00898 
00899 KCommonDecorationButton::KCommonDecorationButton(ButtonType type, KCommonDecoration *parent, const char *name)
00900     : TQButton(parent->widget(), name),
00901         m_decoration(parent),
00902         m_type(type),
00903         m_realizeButtons(Qt::LeftButton),
00904         m_lastMouse(Qt::NoButton),
00905         m_isLeft(true)
00906 {
00907     setCursor(ArrowCursor);
00908 }
00909 
00910 KCommonDecorationButton::~KCommonDecorationButton()
00911 {
00912 }
00913 
00914 KCommonDecoration *KCommonDecorationButton::decoration() const
00915 {
00916     return m_decoration;
00917 }
00918 
00919 ButtonType KCommonDecorationButton::type() const
00920 {
00921     return m_type;
00922 }
00923 
00924 bool KCommonDecorationButton::isLeft() const
00925 {
00926     return m_isLeft;
00927 }
00928 
00929 void KCommonDecorationButton::setLeft(bool left)
00930 {
00931     m_isLeft = left;
00932 }
00933 
00934 void KCommonDecorationButton::setRealizeButtons(int btns)
00935 {
00936     m_realizeButtons = btns;
00937 }
00938 
00939 void KCommonDecorationButton::setSize(const TQSize &s)
00940 {
00941     if (!m_size.isValid() || s != size() ) {
00942         m_size = s;
00943 
00944         setFixedSize(m_size);
00945         reset(SizeChange);
00946     }
00947 }
00948 
00949 TQSize KCommonDecorationButton::sizeHint() const
00950 {
00951     return m_size;
00952 }
00953 
00954 void KCommonDecorationButton::setTipText(const TQString &tip) {
00955     TQToolTip::remove(this );
00956     TQToolTip::add(this, tip );
00957 }
00958 
00959 void KCommonDecorationButton::setToggleButton(bool toggle)
00960 {
00961     TQButton::setToggleButton(toggle);
00962     reset(ToggleChange);
00963 }
00964 
00965 void KCommonDecorationButton::setOn(bool on)
00966 {
00967     if (on != isOn() ) {
00968         TQButton::setOn(on);
00969         reset(StateChange);
00970     }
00971 }
00972 
00973 void KCommonDecorationButton::mousePressEvent(TQMouseEvent* e)
00974 {
00975     m_lastMouse = e->button();
00976     // pass on event after changing button to LeftButton
00977     TQMouseEvent me(e->type(), e->pos(), e->globalPos(),
00978                    (e->button()&m_realizeButtons)?Qt::LeftButton:Qt::NoButton, e->state());
00979 
00980     TQButton::mousePressEvent(&me);
00981 }
00982 
00983 void KCommonDecorationButton::mouseReleaseEvent(TQMouseEvent* e)
00984 {
00985     m_lastMouse = e->button();
00986     // pass on event after changing button to LeftButton
00987     TQMouseEvent me(e->type(), e->pos(), e->globalPos(),
00988                    (e->button()&m_realizeButtons)?Qt::LeftButton:Qt::NoButton, e->state());
00989 
00990     TQButton::mouseReleaseEvent(&me);
00991 }

kwin/lib

Skip menu "kwin/lib"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kwin/lib

Skip menu "kwin/lib"
  • kate
  • kwin
  •   lib
  • libkonq
Generated for kwin/lib by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. |