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 <tdeapplication.h> 00035 #include <kdecorationfactory.h> 00036 #include <tdelocale.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(tqt_xdisplay(), "_TDE_WM_MODAL_SYS_NOTIFICATION", False); 00332 result = XGetWindowProperty(tqt_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 = TQMAX(layoutMetric(LM_TitleEdgeLeft), layoutMetric(LM_BorderLeft)) 00528 +TQMAX(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=TDEApplication::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 }