Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / kwin / lib / kcommondecoration.cpp
blob2109dc68b5ab6557d285c31128b6407cdc963823
1 /*
2 This file is part of the KDE project.
4 Copyright (C) 2005 Sandro Giessl <sandro@giessl.com>
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
25 #include "kcommondecoration.h"
27 #include <QApplication>
28 #include <QCursor>
29 #include <QDateTime>
30 #include <QLabel>
32 #include <QWidget>
34 #include <kdebug.h>
36 #include <kapplication.h>
37 #include "kdecorationfactory.h"
38 #include <klocale.h>
39 #include <QDesktopWidget>
41 #include "kcommondecoration_p.h"
43 #include "kcommondecoration.moc"
45 /** @addtogroup kdecoration */
46 /** @{ */
48 KCommonDecoration::KCommonDecoration(KDecorationBridge* bridge, KDecorationFactory* factory)
49 : m_previewWidget(0),
50 btnHideMinWidth(200),
51 btnHideLastWidth(0),
52 closing(false),
53 wrapper( new KCommonDecorationWrapper( this, bridge, factory ))
56 // sizeof(...) is calculated at compile time
57 memset(m_button, 0, sizeof(KCommonDecorationButton *) * NumButtons);
58 connect( wrapper, SIGNAL( keepAboveChanged( bool )), this, SIGNAL( keepAboveChanged( bool )));
59 connect( wrapper, SIGNAL( keepBelowChanged( bool )), this, SIGNAL( keepBelowChanged( bool )));
62 KCommonDecoration::~KCommonDecoration()
64 for (int n=0; n<NumButtons; n++) {
65 if (m_button[n]) delete m_button[n];
67 delete m_previewWidget;
68 // delete wrapper; - do not do this, this object is actually owned and deleted by the wrapper
71 QString KCommonDecoration::defaultButtonsLeft() const
73 return KDecorationOptions::defaultTitleButtonsLeft();
76 QString KCommonDecoration::defaultButtonsRight() const
78 return KDecorationOptions::defaultTitleButtonsRight();
81 bool KCommonDecoration::decorationBehaviour(DecorationBehaviour behaviour) const
83 switch (behaviour) {
84 case DB_MenuClose:
85 return false;
87 case DB_WindowMask:
88 return false;
90 case DB_ButtonHide:
91 return true;
94 return false;
97 int KCommonDecoration::layoutMetric(LayoutMetric lm, bool respectWindowState, const KCommonDecorationButton *button) const
99 switch (lm) {
100 case LM_BorderLeft:
101 case LM_BorderRight:
102 case LM_BorderBottom:
103 case LM_TitleEdgeTop:
104 case LM_TitleEdgeBottom:
105 case LM_TitleEdgeLeft:
106 case LM_TitleEdgeRight:
107 case LM_TitleBorderLeft:
108 case LM_TitleBorderRight:
109 return 5;
112 case LM_ButtonWidth:
113 case LM_ButtonHeight:
114 case LM_TitleHeight:
115 return 20;
117 case LM_ButtonSpacing:
118 return 5;
120 case LM_ButtonMarginTop:
121 return 0;
123 case LM_ExplicitButtonSpacer:
124 return layoutMetric(LM_ButtonWidth, respectWindowState, button )/2; // half button width by default
126 default:
127 return 0;
131 void KCommonDecoration::init()
133 createMainWidget();
135 // for flicker-free redraws
136 widget()->setAttribute(Qt::WA_NoSystemBackground);
138 widget()->installEventFilter( this );
140 resetLayout();
142 connect(this, SIGNAL(keepAboveChanged(bool) ), SLOT(keepAboveChange(bool) ) );
143 connect(this, SIGNAL(keepBelowChanged(bool) ), SLOT(keepBelowChange(bool) ) );
145 updateCaption();
148 void KCommonDecoration::reset( unsigned long changed )
150 if (changed & SettingButtons) {
151 resetLayout();
152 widget()->update();
156 QRegion KCommonDecoration::cornerShape(WindowCorner)
158 return QRegion();
161 void KCommonDecoration::updateCaption()
163 // This should be reimplemented in decorations for better efficiency
164 widget()->update();
167 void KCommonDecoration::borders( int& left, int& right, int& top, int& bottom ) const
169 left = layoutMetric(LM_BorderLeft);
170 right = layoutMetric(LM_BorderRight);
171 bottom = layoutMetric(LM_BorderBottom);
172 top = layoutMetric(LM_TitleHeight) +
173 layoutMetric(LM_TitleEdgeTop) +
174 layoutMetric(LM_TitleEdgeBottom);
176 updateLayout(); // TODO!! don't call every time we are in ::borders
179 void KCommonDecoration::updateLayout() const
181 QRect r = widget()->rect();
182 int r_x, r_y, r_x2, r_y2;
183 r.getCoords(&r_x, &r_y, &r_x2, &r_y2);
185 // layout preview widget
186 if (m_previewWidget) {
187 const int borderLeft = layoutMetric(LM_BorderLeft);
188 const int borderRight = layoutMetric(LM_BorderRight);
189 const int borderBottom = layoutMetric(LM_BorderBottom);
190 const int titleHeight = layoutMetric(LM_TitleHeight);
191 const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
192 const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
194 int left = r_x+borderLeft;
195 int top = r_y+titleEdgeTop+titleHeight+titleEdgeBottom;
196 int width = r_x2-borderRight-left+1;
197 int height = r_y2-borderBottom-top+1;
198 m_previewWidget->setGeometry(left, top, width, height);
199 moveWidget(left,top, m_previewWidget);
200 resizeWidget(width, height, m_previewWidget);
203 // resize buttons...
204 for (int n=0; n<NumButtons; n++) {
205 if (m_button[n]) {
206 QSize newSize = QSize(layoutMetric(LM_ButtonWidth, true, m_button[n]),
207 layoutMetric(LM_ButtonHeight, true, m_button[n]) );
208 if (newSize != m_button[n]->size() )
209 m_button[n]->setSize(newSize);
213 // layout buttons
214 int y = r_y + layoutMetric(LM_TitleEdgeTop) + layoutMetric(LM_ButtonMarginTop);
215 if (m_buttonsLeft.count() > 0) {
216 const int buttonSpacing = layoutMetric(LM_ButtonSpacing);
217 int x = r_x + layoutMetric(LM_TitleEdgeLeft);
218 for (ButtonContainer::const_iterator it = m_buttonsLeft.begin(); it != m_buttonsLeft.end(); ++it) {
219 bool elementLayouted = false;
220 if (*it) {
221 if (!(*it)->isHidden() ) {
222 moveWidget(x,y, *it);
223 x += layoutMetric(LM_ButtonWidth, true, qobject_cast<KCommonDecorationButton*>(*it) );
224 elementLayouted = true;
226 } else {
227 x+= layoutMetric(LM_ExplicitButtonSpacer);
228 elementLayouted = true;
230 if (elementLayouted && it != m_buttonsLeft.end() )
231 x += buttonSpacing;
235 if (m_buttonsRight.count() > 0) {
236 const int titleEdgeRightLeft = r_x2-layoutMetric(LM_TitleEdgeRight)+1;
238 const int buttonSpacing = layoutMetric(LM_ButtonSpacing);
239 int x = titleEdgeRightLeft - buttonContainerWidth(m_buttonsRight);
240 for (ButtonContainer::const_iterator it = m_buttonsRight.begin(); it != m_buttonsRight.end(); ++it) {
241 bool elementLayouted = false;
242 if (*it) {
243 if (!(*it)->isHidden() ) {
244 moveWidget(x,y, *it);
245 x += layoutMetric(LM_ButtonWidth, true, qobject_cast<KCommonDecorationButton*>(*it) );;
246 elementLayouted = true;
248 } else {
249 x += layoutMetric(LM_ExplicitButtonSpacer);
250 elementLayouted = true;
252 if (elementLayouted && it != m_buttonsRight.end() )
253 x += buttonSpacing;
258 void KCommonDecoration::updateButtons() const
260 for (int n=0; n<NumButtons; n++)
261 if (m_button[n]) m_button[n]->update();
264 void KCommonDecoration::resetButtons() const
266 for (int n=0; n<NumButtons; n++)
267 if (m_button[n]) m_button[n]->reset(KCommonDecorationButton::ManualReset);
270 void KCommonDecoration::resetLayout()
272 for (int n=0; n<NumButtons; n++) {
273 if (m_button[n]) {
274 delete m_button[n];
275 m_button[n] = 0;
278 m_buttonsLeft.clear();
279 m_buttonsRight.clear();
281 delete m_previewWidget;
282 m_previewWidget = 0;
284 // shown instead of the window contents in decoration previews
285 if(isPreview() ) {
286 m_previewWidget = new QLabel(i18n("<center><b>%1 preview</b></center>", visibleName() ), widget());
287 m_previewWidget->setAutoFillBackground(true);
288 m_previewWidget->show();
291 addButtons(m_buttonsLeft,
292 options()->customButtonPositions() ? options()->titleButtonsLeft() : defaultButtonsLeft(),
293 true);
294 addButtons(m_buttonsRight,
295 options()->customButtonPositions() ? options()->titleButtonsRight() : defaultButtonsRight(),
296 false);
298 updateLayout();
300 const int minTitleBarWidth = 35;
301 btnHideMinWidth = buttonContainerWidth(m_buttonsLeft,true) + buttonContainerWidth(m_buttonsRight,true) +
302 layoutMetric(LM_TitleEdgeLeft,false) + layoutMetric(LM_TitleEdgeRight,false) +
303 layoutMetric(LM_TitleBorderLeft,false) + layoutMetric(LM_TitleBorderRight,false) +
304 minTitleBarWidth;
305 btnHideLastWidth = 0;
308 int KCommonDecoration::buttonsLeftWidth() const
310 return buttonContainerWidth(m_buttonsLeft);
313 int KCommonDecoration::buttonsRightWidth() const
315 return buttonContainerWidth(m_buttonsRight);
318 int KCommonDecoration::buttonContainerWidth(const ButtonContainer &btnContainer, bool countHidden) const
320 int explicitSpacer = layoutMetric(LM_ExplicitButtonSpacer);
322 int shownElementsCount = 0;
324 int w = 0;
325 for (ButtonContainer::const_iterator it = btnContainer.begin(); it != btnContainer.end(); ++it) {
326 if (*it) {
327 if (countHidden || !(*it)->isHidden() ) {
328 w += (*it)->width();
329 ++shownElementsCount;
331 } else {
332 w += explicitSpacer;
333 ++shownElementsCount;
336 w += layoutMetric(LM_ButtonSpacing)*(shownElementsCount-1);
338 return w;
341 void KCommonDecoration::addButtons(ButtonContainer &btnContainer, const QString& s, bool isLeft)
343 if (s.length() > 0) {
344 for (int n=0; n < s.length(); n++) {
345 KCommonDecorationButton *btn = 0;
346 switch (s[n].toAscii()) {
347 case 'M': // Menu button
348 if (!m_button[MenuButton]){
349 btn = createButton(MenuButton);
350 if (!btn) break;
351 btn->setTipText(i18n("Menu") );
352 btn->setRealizeButtons(Qt::LeftButton|Qt::RightButton);
353 connect(btn, SIGNAL(pressed()), SLOT(menuButtonPressed()));
354 connect(btn, SIGNAL(released()), this, SLOT(menuButtonReleased()));
356 m_button[MenuButton] = btn;
358 break;
359 case 'S': // OnAllDesktops button
360 if (!m_button[OnAllDesktopsButton]){
361 btn = createButton(OnAllDesktopsButton);
362 if (!btn) break;
363 const bool oad = isOnAllDesktops();
364 btn->setTipText(oad?i18n("Not on all desktops"):i18n("On all desktops") );
365 btn->setToggleButton(true);
366 btn->setOn( oad );
367 connect(btn, SIGNAL(clicked()), SLOT(toggleOnAllDesktops()));
369 m_button[OnAllDesktopsButton] = btn;
371 break;
372 case 'H': // Help button
373 if ((!m_button[HelpButton]) && providesContextHelp()){
374 btn = createButton(HelpButton);
375 if (!btn) break;
376 btn->setTipText(i18n("Help") );
377 connect(btn, SIGNAL(clicked()), SLOT(showContextHelp()));
379 m_button[HelpButton] = btn;
381 break;
382 case 'I': // Minimize button
383 if ((!m_button[MinButton]) && isMinimizable()){
384 btn = createButton(MinButton);
385 if (!btn) break;
386 btn->setTipText(i18n("Minimize") );
387 connect(btn, SIGNAL(clicked()), SLOT(minimize()));
389 m_button[MinButton] = btn;
391 break;
392 case 'A': // Maximize button
393 if ((!m_button[MaxButton]) && isMaximizable()){
394 btn = createButton(MaxButton);
395 if (!btn) break;
396 btn->setRealizeButtons(Qt::LeftButton|Qt::MidButton|Qt::RightButton);
397 const bool max = maximizeMode()==MaximizeFull;
398 btn->setTipText(max?i18n("Restore"):i18n("Maximize") );
399 btn->setToggleButton(true);
400 btn->setOn( max );
401 connect(btn, SIGNAL(clicked()), SLOT(slotMaximize()));
403 m_button[MaxButton] = btn;
405 break;
406 case 'X': // Close button
407 if ((!m_button[CloseButton]) && isCloseable()){
408 btn = createButton(CloseButton);
409 if (!btn) break;
410 btn->setTipText(i18n("Close") );
411 connect(btn, SIGNAL(clicked()), SLOT(closeWindow()));
413 m_button[CloseButton] = btn;
415 break;
416 case 'F': // AboveButton button
417 if (!m_button[AboveButton]){
418 btn = createButton(AboveButton);
419 if (!btn) break;
420 bool above = keepAbove();
421 btn->setTipText(above?i18n("Do not keep above others"):i18n("Keep above others") );
422 btn->setToggleButton(true);
423 btn->setOn( above );
424 connect(btn, SIGNAL(clicked()), SLOT(slotKeepAbove()));
426 m_button[AboveButton] = btn;
428 break;
429 case 'B': // BelowButton button
430 if (!m_button[BelowButton]){
431 btn = createButton(BelowButton);
432 if (!btn) break;
433 bool below = keepBelow();
434 btn->setTipText(below?i18n("Do not keep below others"):i18n("Keep below others") );
435 btn->setToggleButton(true);
436 btn->setOn( below );
437 connect(btn, SIGNAL(clicked()), SLOT(slotKeepBelow()));
439 m_button[BelowButton] = btn;
441 break;
442 case 'L': // Shade button
443 if ((!m_button[ShadeButton]) && isShadeable()){
444 btn = createButton(ShadeButton);
445 if (!btn) break;
446 bool shaded = isSetShade();
447 btn->setTipText(shaded?i18n("Unshade"):i18n("Shade") );
448 btn->setToggleButton(true);
449 btn->setOn( shaded );
450 connect(btn, SIGNAL(clicked()), SLOT(slotShade()));
452 m_button[ShadeButton] = btn;
454 break;
455 case '_': // Spacer item
456 btnContainer.append(0);
460 if (btn) {
461 btn->setLeft(isLeft);
462 btn->setSize(QSize(layoutMetric(LM_ButtonWidth, true, btn),layoutMetric(LM_ButtonHeight, true, btn)) );
463 btn->show();
464 btnContainer.append(btn);
471 void KCommonDecoration::calcHiddenButtons()
473 if (width() == btnHideLastWidth)
474 return;
476 btnHideLastWidth = width();
478 //Hide buttons in the following order:
479 KCommonDecorationButton* btnArray[] = { m_button[HelpButton], m_button[ShadeButton], m_button[BelowButton],
480 m_button[AboveButton], m_button[OnAllDesktopsButton], m_button[MaxButton],
481 m_button[MinButton], m_button[MenuButton], m_button[CloseButton] };
482 const int buttonsCount = sizeof( btnArray ) / sizeof( btnArray[ 0 ] );
484 int current_width = width();
485 int count = 0;
487 // Hide buttons
488 while (current_width < btnHideMinWidth && count < buttonsCount)
490 if (btnArray[count] ) {
491 current_width += btnArray[count]->width();
492 if (btnArray[count]->isVisible() )
493 btnArray[count]->hide();
495 count++;
497 // Show the rest of the buttons...
498 for(int i = count; i < buttonsCount; i++)
500 if (btnArray[i] ) {
502 if (! btnArray[i]->isHidden() )
503 break; // all buttons shown...
505 btnArray[i]->show();
510 void KCommonDecoration::show()
512 if (decorationBehaviour(DB_ButtonHide) )
513 calcHiddenButtons();
514 widget()->show();
517 void KCommonDecoration::resize( const QSize& s )
519 widget()->resize( s );
522 QSize KCommonDecoration::minimumSize() const
524 const int minWidth = qMax(layoutMetric(LM_TitleEdgeLeft), layoutMetric(LM_BorderLeft))
525 +qMax(layoutMetric(LM_TitleEdgeRight), layoutMetric(LM_BorderRight))
526 +layoutMetric(LM_TitleBorderLeft)+layoutMetric(LM_TitleBorderRight);
527 return QSize(minWidth,
528 layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)
529 +layoutMetric(LM_TitleEdgeBottom)
530 +layoutMetric(LM_BorderBottom) );
533 void KCommonDecoration::maximizeChange()
535 if( m_button[MaxButton] ) {
536 m_button[MaxButton]->setOn( maximizeMode()==MaximizeFull);
537 m_button[MaxButton]->setTipText( (maximizeMode()!=MaximizeFull) ?
538 i18n("Maximize")
539 : i18n("Restore"));
540 m_button[MaxButton]->reset(KCommonDecorationButton::StateChange);
542 updateWindowShape();
543 widget()->update();
546 void KCommonDecoration::desktopChange()
548 if ( m_button[OnAllDesktopsButton] ) {
549 m_button[OnAllDesktopsButton]->setOn( isOnAllDesktops() );
550 m_button[OnAllDesktopsButton]->setTipText( isOnAllDesktops() ?
551 i18n("Not on all desktops")
552 : i18n("On all desktops"));
553 m_button[OnAllDesktopsButton]->reset(KCommonDecorationButton::StateChange);
557 void KCommonDecoration::shadeChange()
559 if ( m_button[ShadeButton] ) {
560 bool shaded = isSetShade();
561 m_button[ShadeButton]->setOn( shaded );
562 m_button[ShadeButton]->setTipText( shaded ?
563 i18n("Unshade")
564 : i18n("Shade"));
565 m_button[ShadeButton]->reset(KCommonDecorationButton::StateChange);
569 void KCommonDecoration::iconChange()
571 if (m_button[MenuButton])
573 m_button[MenuButton]->update();
574 m_button[MenuButton]->reset(KCommonDecorationButton::IconChange);
578 void KCommonDecoration::activeChange()
580 updateButtons();
581 widget()->update(); // do something similar to updateCaption here
584 void KCommonDecoration::captionChange()
586 updateCaption();
589 void KCommonDecoration::keepAboveChange(bool above)
591 if (m_button[AboveButton])
593 m_button[AboveButton]->setOn(above);
594 m_button[AboveButton]->setTipText( above?i18n("Do not keep above others"):i18n("Keep above others") );
595 m_button[AboveButton]->reset(KCommonDecorationButton::StateChange);
598 if (m_button[BelowButton] && m_button[BelowButton]->isChecked())
600 m_button[BelowButton]->setOn(false);
601 m_button[BelowButton]->setTipText( i18n("Keep below others") );
602 m_button[BelowButton]->reset(KCommonDecorationButton::StateChange);
606 void KCommonDecoration::keepBelowChange(bool below)
608 if (m_button[BelowButton])
610 m_button[BelowButton]->setOn(below);
611 m_button[BelowButton]->setTipText( below?i18n("Do not keep below others"):i18n("Keep below others") );
612 m_button[BelowButton]->reset(KCommonDecorationButton::StateChange);
615 if (m_button[AboveButton] && m_button[AboveButton]->isChecked())
617 m_button[AboveButton]->setOn(false);
618 m_button[AboveButton]->setTipText( i18n("Keep above others") );
619 m_button[AboveButton]->reset(KCommonDecorationButton::StateChange);
623 void KCommonDecoration::slotMaximize()
625 if (m_button[MaxButton])
627 maximize(m_button[MaxButton]->lastMousePress() );
631 void KCommonDecoration::slotShade()
633 setShade( !isSetShade() );
636 void KCommonDecoration::slotKeepAbove()
638 setKeepAbove(!keepAbove() );
641 void KCommonDecoration::slotKeepBelow()
643 setKeepBelow(!keepBelow() );
646 void KCommonDecoration::menuButtonPressed()
648 static QTime* t = NULL;
649 static KCommonDecoration* lastClient = NULL;
650 if (t == NULL)
651 t = new QTime;
652 bool dbl = (lastClient==this && t->elapsed() <= QApplication::doubleClickInterval());
653 lastClient = this;
654 t->start();
655 if (!dbl || !decorationBehaviour(DB_MenuClose) ) {
656 QRect menuRect = m_button[MenuButton]->rect();
657 QPoint menutop = m_button[MenuButton]->mapToGlobal(menuRect.topLeft());
658 QPoint menubottom = m_button[MenuButton]->mapToGlobal(menuRect.bottomRight())+QPoint(0,2);
659 KDecorationFactory* f = factory();
660 showWindowMenu(QRect(menutop, menubottom));
661 if( !f->exists( decoration())) // 'this' was deleted
662 return;
663 m_button[MenuButton]->setDown(false);
665 else
666 closing = true;
669 void KCommonDecoration::menuButtonReleased()
671 if(closing)
672 closeWindow();
675 void KCommonDecoration::resizeEvent(QResizeEvent */*e*/)
677 if (decorationBehaviour(DB_ButtonHide) )
678 calcHiddenButtons();
680 updateLayout();
682 updateWindowShape();
683 // FIXME: don't update() here! this would result in two paintEvent()s
684 // because there is already "something" else triggering the repaint...
685 // widget()->update();
688 void KCommonDecoration::moveWidget(int x, int y, QWidget *widget) const
690 QPoint p = widget->pos();
691 int oldX = p.y();
692 int oldY = p.x();
694 if (x!=oldX || y!=oldY)
695 widget->move(x,y);
698 void KCommonDecoration::resizeWidget(int w, int h, QWidget *widget) const
700 QSize s = widget->size();
701 int oldW = s.width();
702 int oldH = s.height();
704 if (w!=oldW || h!=oldH)
705 widget->resize(w,h);
708 void KCommonDecoration::mouseDoubleClickEvent(QMouseEvent *e)
710 if( e->button() != Qt::LeftButton )
711 return;
713 int tb = layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeBottom);
714 // when shaded, react on double clicks everywhere to make it easier to unshade. otherwise
715 // react only on double clicks in the title bar region...
716 if (isSetShade() || e->pos().y() <= tb )
717 titlebarDblClickOperation();
720 void KCommonDecoration::wheelEvent(QWheelEvent *e)
722 int tb = layoutMetric(LM_TitleEdgeTop)+layoutMetric(LM_TitleHeight)+layoutMetric(LM_TitleEdgeBottom);
723 if (isSetShade() || e->pos().y() <= tb )
724 titlebarMouseWheelOperation( e->delta());
727 KCommonDecoration::Position KCommonDecoration::mousePosition(const QPoint &point) const
729 const int corner = 18+3*layoutMetric(LM_BorderBottom, false)/2;
730 Position pos = PositionCenter;
732 QRect r = widget()->rect();
733 int r_x, r_y, r_x2, r_y2;
734 r.getCoords(&r_x, &r_y, &r_x2, &r_y2);
735 int p_x = point.x();
736 int p_y = point.y();
737 const int borderLeft = layoutMetric(LM_BorderLeft);
738 // const int borderRight = layoutMetric(LM_BorderRight);
739 const int borderBottom = layoutMetric(LM_BorderBottom);
740 const int titleHeight = layoutMetric(LM_TitleHeight);
741 const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
742 const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
743 const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
744 const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);
746 const int borderBottomTop = r_y2-borderBottom+1;
747 const int borderLeftRight = r_x+borderLeft-1;
748 // const int borderRightLeft = r_x2-borderRight+1;
749 const int titleEdgeLeftRight = r_x+titleEdgeLeft-1;
750 const int titleEdgeRightLeft = r_x2-titleEdgeRight+1;
751 const int titleEdgeBottomBottom = r_y+titleEdgeTop+titleHeight+titleEdgeBottom-1;
752 const int titleEdgeTopBottom = r_y+titleEdgeTop-1;
754 if (p_y <= titleEdgeTopBottom) {
755 if (p_x <= r_x+corner)
756 pos = PositionTopLeft;
757 else if (p_x >= r_x2-corner)
758 pos = PositionTopRight;
759 else
760 pos = PositionTop;
761 } else if (p_y <= titleEdgeBottomBottom) {
762 if (p_x <= titleEdgeLeftRight)
763 pos = PositionTopLeft;
764 else if (p_x >= titleEdgeRightLeft)
765 pos = PositionTopRight;
766 else
767 pos = PositionCenter; // title bar
768 } else if (p_y < borderBottomTop) {
769 if (p_y < r_y2-corner) {
770 if (p_x <= borderLeftRight)
771 pos = PositionLeft;
772 else
773 pos = PositionRight;
774 } else {
775 if (p_x <= borderLeftRight)
776 pos = PositionBottomLeft;
777 else
778 pos = PositionBottomRight;
780 } else if(p_y >= borderBottomTop) {
781 if (p_x <= r_x+corner)
782 pos = PositionBottomLeft;
783 else if (p_x >= r_x2-corner)
784 pos = PositionBottomRight;
785 else
786 pos = PositionBottom;
789 return pos;
792 void KCommonDecoration::updateWindowShape()
794 // don't mask the widget...
795 if (!decorationBehaviour(DB_WindowMask) )
796 return;
798 int w = widget()->width();
799 int h = widget()->height();
801 bool tl=true,tr=true,bl=true,br=true; // is there a transparent rounded corner in top-left? etc
803 QDesktopWidget *desktop=KApplication::desktop();
804 // no transparent rounded corners if this window corner lines up with a screen corner
805 for(int screen=0; screen < desktop->numScreens(); ++screen)
807 QRect fullscreen(desktop->screenGeometry(screen));
808 QRect window = geometry();
810 if(window.topLeft() == fullscreen.topLeft() ) tl = false;
811 if(window.topRight() == fullscreen.topRight() ) tr = false;
812 if(window.bottomLeft() == fullscreen.bottomLeft() ) bl = false;
813 if(window.bottomRight()== fullscreen.bottomRight() ) br = false;
816 QRegion mask(0, 0, w, h);
818 // Remove top-left corner.
819 if(tl)
821 mask -= cornerShape(WC_TopLeft);
823 // Remove top-right corner.
824 if(tr)
826 mask -= cornerShape(WC_TopRight);
828 // Remove top-left corner.
829 if(bl)
831 mask -= cornerShape(WC_BottomLeft);
833 // Remove top-right corner.
834 if(br)
836 mask -= cornerShape(WC_BottomRight);
839 setMask( mask );
842 bool KCommonDecoration::eventFilter( QObject* o, QEvent* e )
844 if( o != widget())
845 return false;
846 switch( e->type())
848 case QEvent::Resize:
849 resizeEvent(static_cast<QResizeEvent*>(e) );
850 return true;
851 case QEvent::Paint:
852 paintEvent( static_cast< QPaintEvent* >( e ));
853 return true;
854 case QEvent::MouseButtonDblClick:
855 mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ));
856 return true;
857 case QEvent::MouseButtonPress:
858 processMousePressEvent( static_cast< QMouseEvent* >( e ));
859 return true;
860 case QEvent::Wheel:
861 wheelEvent( static_cast< QWheelEvent* >( e ));
862 return true;
863 default:
864 return false;
868 const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
869 | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask
870 | NET::UtilityMask | NET::SplashMask;
872 bool KCommonDecoration::isToolWindow() const
874 NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK );
875 return ((type==NET::Toolbar)||(type==NET::Utility)||(type==NET::Menu));
878 QRect KCommonDecoration::titleRect() const
880 int r_x, r_y, r_x2, r_y2;
881 widget()->rect().getCoords(&r_x, &r_y, &r_x2, &r_y2);
882 const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
883 const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
884 const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);
885 const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
886 const int titleBorderLeft = layoutMetric(LM_TitleBorderLeft);
887 const int titleBorderRight = layoutMetric(LM_TitleBorderRight);
888 const int ttlHeight = layoutMetric(LM_TitleHeight);
889 const int titleEdgeBottomBottom = r_y+titleEdgeTop+ttlHeight+titleEdgeBottom-1;
890 return QRect(r_x+titleEdgeLeft+buttonsLeftWidth()+titleBorderLeft, r_y+titleEdgeTop,
891 r_x2-titleEdgeRight-buttonsRightWidth()-titleBorderRight-(r_x+titleEdgeLeft+buttonsLeftWidth()+titleBorderLeft),
892 titleEdgeBottomBottom-(r_y+titleEdgeTop) );
896 KCommonDecorationButton::KCommonDecorationButton(ButtonType type, KCommonDecoration *parent)
897 : QAbstractButton(parent->widget() ),
898 m_decoration(parent),
899 m_type(type),
900 m_realizeButtons(Qt::LeftButton),
901 m_lastMouse(Qt::NoButton),
902 m_isLeft(true)
904 setCursor(Qt::ArrowCursor);
907 KCommonDecorationButton::~KCommonDecorationButton()
911 KCommonDecoration *KCommonDecorationButton::decoration() const
913 return m_decoration;
916 ButtonType KCommonDecorationButton::type() const
918 return m_type;
921 bool KCommonDecorationButton::isLeft() const
923 return m_isLeft;
926 void KCommonDecorationButton::setLeft(bool left)
928 m_isLeft = left;
931 void KCommonDecorationButton::setRealizeButtons(int btns)
933 m_realizeButtons = btns;
936 void KCommonDecorationButton::setSize(const QSize &s)
938 if (!m_size.isValid() || s != size() ) {
939 m_size = s;
941 setFixedSize(m_size);
942 reset(SizeChange);
946 QSize KCommonDecorationButton::sizeHint() const
948 return m_size;
951 void KCommonDecorationButton::setTipText(const QString &tip) {
952 this->setToolTip( tip );
955 void KCommonDecorationButton::setToggleButton(bool toggle)
957 QAbstractButton::setCheckable(toggle);
958 reset(ToggleChange);
961 void KCommonDecorationButton::setOn(bool on)
963 if (on != isChecked() ) {
964 QAbstractButton::setChecked(on);
965 reset(StateChange);
969 void KCommonDecorationButton::mousePressEvent(QMouseEvent* e)
971 m_lastMouse = e->button();
972 // pass on event after changing button to LeftButton
973 QMouseEvent me(e->type(), e->pos(), (e->button()&m_realizeButtons)?Qt::LeftButton : Qt::NoButton, e->buttons(), e->modifiers() );
975 QAbstractButton::mousePressEvent(&me);
978 void KCommonDecorationButton::mouseReleaseEvent(QMouseEvent* e)
980 m_lastMouse = e->button();
981 // pass on event after changing button to LeftButton
982 QMouseEvent me(e->type(), e->pos(), (e->button()&m_realizeButtons)?Qt::LeftButton : Qt::NoButton, e->buttons(), e->modifiers() );
984 QAbstractButton::mouseReleaseEvent(&me);
989 // *** wrap everything from KDecoration *** //
990 bool KCommonDecoration::drawbound( const QRect&, bool )
992 return false;
994 bool KCommonDecoration::windowDocked( Position )
996 return false;
998 const KDecorationOptions* KCommonDecoration::options()
1000 return KDecoration::options();
1002 bool KCommonDecoration::isActive() const
1004 return wrapper->isActive();
1006 bool KCommonDecoration::isCloseable() const
1008 return wrapper->isCloseable();
1010 bool KCommonDecoration::isMaximizable() const
1012 return wrapper->isMaximizable();
1014 KCommonDecoration::MaximizeMode KCommonDecoration::maximizeMode() const
1016 return wrapper->maximizeMode();
1018 bool KCommonDecoration::isMinimizable() const
1020 return wrapper->isMinimizable();
1022 bool KCommonDecoration::providesContextHelp() const
1024 return wrapper->providesContextHelp();
1026 int KCommonDecoration::desktop() const
1028 return wrapper->desktop();
1030 bool KCommonDecoration::isOnAllDesktops() const
1032 return wrapper->isOnAllDesktops();
1034 bool KCommonDecoration::isModal() const
1036 return wrapper->isModal();
1038 bool KCommonDecoration::isShadeable() const
1040 return wrapper->isShadeable();
1042 bool KCommonDecoration::isShade() const
1044 return wrapper->isShade();
1046 bool KCommonDecoration::isSetShade() const
1048 return wrapper->isSetShade();
1050 bool KCommonDecoration::keepAbove() const
1052 return wrapper->keepAbove();
1054 bool KCommonDecoration::keepBelow() const
1056 return wrapper->keepBelow();
1058 bool KCommonDecoration::isMovable() const
1060 return wrapper->isMovable();
1062 bool KCommonDecoration::isResizable() const
1064 return wrapper->isResizable();
1066 NET::WindowType KCommonDecoration::windowType( unsigned long supported_types ) const
1068 return wrapper->windowType( supported_types );
1070 QIcon KCommonDecoration::icon() const
1072 return wrapper->icon();
1074 QString KCommonDecoration::caption() const
1076 return wrapper->caption();
1078 void KCommonDecoration::showWindowMenu( const QRect &pos )
1080 return wrapper->showWindowMenu( pos );
1082 void KCommonDecoration::showWindowMenu( QPoint pos )
1084 return wrapper->showWindowMenu( pos );
1086 void KCommonDecoration::performWindowOperation( WindowOperation op )
1088 return wrapper->performWindowOperation( op );
1090 void KCommonDecoration::setMask( const QRegion& reg, int mode )
1092 return wrapper->setMask( reg, mode );
1094 void KCommonDecoration::clearMask()
1096 return wrapper->clearMask();
1098 bool KCommonDecoration::isPreview() const
1100 return wrapper->isPreview();
1102 QRect KCommonDecoration::geometry() const
1104 return wrapper->geometry();
1106 QRect KCommonDecoration::iconGeometry() const
1108 return wrapper->iconGeometry();
1110 QRegion KCommonDecoration::unobscuredRegion( const QRegion& r ) const
1112 return wrapper->unobscuredRegion( r );
1114 WId KCommonDecoration::windowId() const
1116 return wrapper->windowId();
1118 int KCommonDecoration::width() const
1120 return wrapper->width();
1122 int KCommonDecoration::height() const
1124 return wrapper->height();
1126 void KCommonDecoration::processMousePressEvent( QMouseEvent* e )
1128 return wrapper->processMousePressEvent( e );
1130 void KCommonDecoration::setMainWidget( QWidget* w )
1132 return wrapper->setMainWidget( w );
1134 void KCommonDecoration::createMainWidget( Qt::WFlags flags )
1136 return wrapper->createMainWidget( flags );
1138 QWidget* KCommonDecoration::initialParentWidget() const
1140 return wrapper->initialParentWidget();
1142 Qt::WFlags KCommonDecoration::initialWFlags() const
1144 return wrapper->initialWFlags();
1146 QWidget* KCommonDecoration::widget()
1148 return wrapper->widget();
1150 const QWidget* KCommonDecoration::widget() const
1152 return wrapper->widget();
1154 KDecorationFactory* KCommonDecoration::factory() const
1156 return wrapper->factory();
1158 void KCommonDecoration::grabXServer()
1160 return wrapper->grabXServer();
1162 void KCommonDecoration::ungrabXServer()
1164 return wrapper->ungrabXServer();
1166 void KCommonDecoration::closeWindow()
1168 return wrapper->closeWindow();
1170 void KCommonDecoration::maximize( Qt::MouseButtons button )
1172 return wrapper->maximize( button );
1174 void KCommonDecoration::maximize( MaximizeMode mode )
1176 return wrapper->maximize( mode );
1178 void KCommonDecoration::minimize()
1180 return wrapper->minimize();
1182 void KCommonDecoration::showContextHelp()
1184 return wrapper->showContextHelp();
1186 void KCommonDecoration::setDesktop( int desktop )
1188 return wrapper->setDesktop( desktop );
1190 void KCommonDecoration::toggleOnAllDesktops()
1192 return wrapper->toggleOnAllDesktops();
1194 void KCommonDecoration::titlebarDblClickOperation()
1196 return wrapper->titlebarDblClickOperation();
1198 void KCommonDecoration::titlebarMouseWheelOperation( int delta )
1200 return wrapper->titlebarMouseWheelOperation( delta );
1202 void KCommonDecoration::setShade( bool set )
1204 return wrapper->setShade( set );
1206 void KCommonDecoration::setKeepAbove( bool set )
1208 return wrapper->setKeepAbove( set );
1210 void KCommonDecoration::setKeepBelow( bool set )
1212 return wrapper->setKeepBelow( set );
1214 // *** end of wrapping of everything from KDecoration *** //
1216 const KDecoration* KCommonDecoration::decoration() const
1218 return wrapper;
1220 KDecoration* KCommonDecoration::decoration()
1222 return wrapper;
1225 // kate: space-indent on; indent-width 4; mixedindent off; indent-mode cstyle;