not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kwin / lib / kcommondecoration.cpp
blob35a8779f104c281d8003b8ac48bc1667665e2c5c
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"
26 #include "kcommondecoration_p.h"
28 #include <QApplication>
29 #include <QCursor>
30 #include <QDateTime>
31 #include <QLabel>
33 #include <QWidget>
35 #include <kdebug.h>
37 #include <kapplication.h>
38 #include "kdecorationfactory.h"
39 #include <klocale.h>
41 #include <kephal/screens.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 // no transparent rounded corners if this window corner lines up with a screen corner
804 for(int screen=0; screen < Kephal::ScreenUtils::numScreens(); ++screen)
806 QRect fullscreen(Kephal::ScreenUtils::screenGeometry(screen));
807 QRect window = geometry();
809 if(window.topLeft() == fullscreen.topLeft() ) tl = false;
810 if(window.topRight() == fullscreen.topRight() ) tr = false;
811 if(window.bottomLeft() == fullscreen.bottomLeft() ) bl = false;
812 if(window.bottomRight()== fullscreen.bottomRight() ) br = false;
815 QRegion mask(0, 0, w, h);
817 // Remove top-left corner.
818 if(tl)
820 mask -= cornerShape(WC_TopLeft);
822 // Remove top-right corner.
823 if(tr)
825 mask -= cornerShape(WC_TopRight);
827 // Remove top-left corner.
828 if(bl)
830 mask -= cornerShape(WC_BottomLeft);
832 // Remove top-right corner.
833 if(br)
835 mask -= cornerShape(WC_BottomRight);
838 setMask( mask );
841 bool KCommonDecoration::eventFilter( QObject* o, QEvent* e )
843 if( o != widget())
844 return false;
845 switch( e->type())
847 case QEvent::Resize:
848 resizeEvent(static_cast<QResizeEvent*>(e) );
849 return true;
850 case QEvent::Paint:
851 paintEvent( static_cast< QPaintEvent* >( e ));
852 return true;
853 case QEvent::MouseButtonDblClick:
854 mouseDoubleClickEvent( static_cast< QMouseEvent* >( e ));
855 return true;
856 case QEvent::MouseButtonPress:
857 processMousePressEvent( static_cast< QMouseEvent* >( e ));
858 return true;
859 case QEvent::Wheel:
860 wheelEvent( static_cast< QWheelEvent* >( e ));
861 return true;
862 default:
863 return false;
867 const int SUPPORTED_WINDOW_TYPES_MASK = NET::NormalMask | NET::DesktopMask | NET::DockMask
868 | NET::ToolbarMask | NET::MenuMask | NET::DialogMask /*| NET::OverrideMask*/ | NET::TopMenuMask
869 | NET::UtilityMask | NET::SplashMask;
871 bool KCommonDecoration::isToolWindow() const
873 NET::WindowType type = windowType( SUPPORTED_WINDOW_TYPES_MASK );
874 return ((type==NET::Toolbar)||(type==NET::Utility)||(type==NET::Menu));
877 QRect KCommonDecoration::titleRect() const
879 int r_x, r_y, r_x2, r_y2;
880 widget()->rect().getCoords(&r_x, &r_y, &r_x2, &r_y2);
881 const int titleEdgeLeft = layoutMetric(LM_TitleEdgeLeft);
882 const int titleEdgeTop = layoutMetric(LM_TitleEdgeTop);
883 const int titleEdgeRight = layoutMetric(LM_TitleEdgeRight);
884 const int titleEdgeBottom = layoutMetric(LM_TitleEdgeBottom);
885 const int titleBorderLeft = layoutMetric(LM_TitleBorderLeft);
886 const int titleBorderRight = layoutMetric(LM_TitleBorderRight);
887 const int ttlHeight = layoutMetric(LM_TitleHeight);
888 const int titleEdgeBottomBottom = r_y+titleEdgeTop+ttlHeight+titleEdgeBottom-1;
889 return QRect(r_x+titleEdgeLeft+buttonsLeftWidth()+titleBorderLeft, r_y+titleEdgeTop,
890 r_x2-titleEdgeRight-buttonsRightWidth()-titleBorderRight-(r_x+titleEdgeLeft+buttonsLeftWidth()+titleBorderLeft),
891 titleEdgeBottomBottom-(r_y+titleEdgeTop) );
895 KCommonDecorationButton::KCommonDecorationButton(ButtonType type, KCommonDecoration *parent)
896 : QAbstractButton(parent->widget() ),
897 m_decoration(parent),
898 m_type(type),
899 m_realizeButtons(Qt::LeftButton),
900 m_lastMouse(Qt::NoButton),
901 m_isLeft(true)
903 setCursor(Qt::ArrowCursor);
906 KCommonDecorationButton::~KCommonDecorationButton()
910 KCommonDecoration *KCommonDecorationButton::decoration() const
912 return m_decoration;
915 ButtonType KCommonDecorationButton::type() const
917 return m_type;
920 bool KCommonDecorationButton::isLeft() const
922 return m_isLeft;
925 void KCommonDecorationButton::setLeft(bool left)
927 m_isLeft = left;
930 void KCommonDecorationButton::setRealizeButtons(int btns)
932 m_realizeButtons = btns;
935 void KCommonDecorationButton::setSize(const QSize &s)
937 if (!m_size.isValid() || s != size() ) {
938 m_size = s;
940 setFixedSize(m_size);
941 reset(SizeChange);
945 QSize KCommonDecorationButton::sizeHint() const
947 return m_size;
950 void KCommonDecorationButton::setTipText(const QString &tip) {
951 this->setToolTip( tip );
954 void KCommonDecorationButton::setToggleButton(bool toggle)
956 QAbstractButton::setCheckable(toggle);
957 reset(ToggleChange);
960 void KCommonDecorationButton::setOn(bool on)
962 if (on != isChecked() ) {
963 QAbstractButton::setChecked(on);
964 reset(StateChange);
968 void KCommonDecorationButton::mousePressEvent(QMouseEvent* e)
970 m_lastMouse = e->button();
971 // pass on event after changing button to LeftButton
972 QMouseEvent me(e->type(), e->pos(), (e->button()&m_realizeButtons)?Qt::LeftButton : Qt::NoButton, e->buttons(), e->modifiers() );
974 QAbstractButton::mousePressEvent(&me);
977 void KCommonDecorationButton::mouseReleaseEvent(QMouseEvent* e)
979 m_lastMouse = e->button();
980 // pass on event after changing button to LeftButton
981 QMouseEvent me(e->type(), e->pos(), (e->button()&m_realizeButtons)?Qt::LeftButton : Qt::NoButton, e->buttons(), e->modifiers() );
983 QAbstractButton::mouseReleaseEvent(&me);
988 // *** wrap everything from KDecoration *** //
989 bool KCommonDecoration::drawbound( const QRect&, bool )
991 return false;
993 bool KCommonDecoration::windowDocked( Position )
995 return false;
997 const KDecorationOptions* KCommonDecoration::options()
999 return KDecoration::options();
1001 bool KCommonDecoration::isActive() const
1003 return wrapper->isActive();
1005 bool KCommonDecoration::isCloseable() const
1007 return wrapper->isCloseable();
1009 bool KCommonDecoration::isMaximizable() const
1011 return wrapper->isMaximizable();
1013 KCommonDecoration::MaximizeMode KCommonDecoration::maximizeMode() const
1015 return wrapper->maximizeMode();
1017 bool KCommonDecoration::isMinimizable() const
1019 return wrapper->isMinimizable();
1021 bool KCommonDecoration::providesContextHelp() const
1023 return wrapper->providesContextHelp();
1025 int KCommonDecoration::desktop() const
1027 return wrapper->desktop();
1029 bool KCommonDecoration::isOnAllDesktops() const
1031 return wrapper->isOnAllDesktops();
1033 bool KCommonDecoration::isModal() const
1035 return wrapper->isModal();
1037 bool KCommonDecoration::isShadeable() const
1039 return wrapper->isShadeable();
1041 bool KCommonDecoration::isShade() const
1043 return wrapper->isShade();
1045 bool KCommonDecoration::isSetShade() const
1047 return wrapper->isSetShade();
1049 bool KCommonDecoration::keepAbove() const
1051 return wrapper->keepAbove();
1053 bool KCommonDecoration::keepBelow() const
1055 return wrapper->keepBelow();
1057 bool KCommonDecoration::isMovable() const
1059 return wrapper->isMovable();
1061 bool KCommonDecoration::isResizable() const
1063 return wrapper->isResizable();
1065 NET::WindowType KCommonDecoration::windowType( unsigned long supported_types ) const
1067 return wrapper->windowType( supported_types );
1069 QIcon KCommonDecoration::icon() const
1071 return wrapper->icon();
1073 QString KCommonDecoration::caption() const
1075 return wrapper->caption();
1077 void KCommonDecoration::showWindowMenu( const QRect &pos )
1079 return wrapper->showWindowMenu( pos );
1081 void KCommonDecoration::showWindowMenu( QPoint pos )
1083 return wrapper->showWindowMenu( pos );
1085 void KCommonDecoration::performWindowOperation( WindowOperation op )
1087 return wrapper->performWindowOperation( op );
1089 void KCommonDecoration::setMask( const QRegion& reg, int mode )
1091 return wrapper->setMask( reg, mode );
1093 void KCommonDecoration::clearMask()
1095 return wrapper->clearMask();
1097 bool KCommonDecoration::isPreview() const
1099 return wrapper->isPreview();
1101 QRect KCommonDecoration::geometry() const
1103 return wrapper->geometry();
1105 QRect KCommonDecoration::iconGeometry() const
1107 return wrapper->iconGeometry();
1109 QRegion KCommonDecoration::unobscuredRegion( const QRegion& r ) const
1111 return wrapper->unobscuredRegion( r );
1113 WId KCommonDecoration::windowId() const
1115 return wrapper->windowId();
1117 int KCommonDecoration::width() const
1119 return wrapper->width();
1121 int KCommonDecoration::height() const
1123 return wrapper->height();
1125 void KCommonDecoration::processMousePressEvent( QMouseEvent* e )
1127 return wrapper->processMousePressEvent( e );
1129 void KCommonDecoration::setMainWidget( QWidget* w )
1131 return wrapper->setMainWidget( w );
1133 void KCommonDecoration::createMainWidget( Qt::WFlags flags )
1135 return wrapper->createMainWidget( flags );
1137 QWidget* KCommonDecoration::initialParentWidget() const
1139 return wrapper->initialParentWidget();
1141 Qt::WFlags KCommonDecoration::initialWFlags() const
1143 return wrapper->initialWFlags();
1145 QWidget* KCommonDecoration::widget()
1147 return wrapper->widget();
1149 const QWidget* KCommonDecoration::widget() const
1151 return wrapper->widget();
1153 KDecorationFactory* KCommonDecoration::factory() const
1155 return wrapper->factory();
1157 void KCommonDecoration::grabXServer()
1159 return wrapper->grabXServer();
1161 void KCommonDecoration::ungrabXServer()
1163 return wrapper->ungrabXServer();
1165 void KCommonDecoration::closeWindow()
1167 return wrapper->closeWindow();
1169 void KCommonDecoration::maximize( Qt::MouseButtons button )
1171 return wrapper->maximize( button );
1173 void KCommonDecoration::maximize( MaximizeMode mode )
1175 return wrapper->maximize( mode );
1177 void KCommonDecoration::minimize()
1179 return wrapper->minimize();
1181 void KCommonDecoration::showContextHelp()
1183 return wrapper->showContextHelp();
1185 void KCommonDecoration::setDesktop( int desktop )
1187 return wrapper->setDesktop( desktop );
1189 void KCommonDecoration::toggleOnAllDesktops()
1191 return wrapper->toggleOnAllDesktops();
1193 void KCommonDecoration::titlebarDblClickOperation()
1195 return wrapper->titlebarDblClickOperation();
1197 void KCommonDecoration::titlebarMouseWheelOperation( int delta )
1199 return wrapper->titlebarMouseWheelOperation( delta );
1201 void KCommonDecoration::setShade( bool set )
1203 return wrapper->setShade( set );
1205 void KCommonDecoration::setKeepAbove( bool set )
1207 return wrapper->setKeepAbove( set );
1209 void KCommonDecoration::setKeepBelow( bool set )
1211 return wrapper->setKeepBelow( set );
1213 // *** end of wrapping of everything from KDecoration *** //
1215 const KDecoration* KCommonDecoration::decoration() const
1217 return wrapper;
1219 KDecoration* KCommonDecoration::decoration()
1221 return wrapper;
1225 KCommonDecorationUnstable::KCommonDecorationUnstable(KDecorationBridge* bridge, KDecorationFactory* factory)
1226 : KCommonDecoration( bridge, factory )
1228 Q_ASSERT( dynamic_cast<const KDecorationUnstable*>( decoration() ));
1231 KCommonDecorationUnstable::~KCommonDecorationUnstable()
1235 // All copied from kdecoration.cpp
1236 QList<QRect> KCommonDecorationUnstable::shadowQuads( ShadowType type ) const
1238 Q_UNUSED( type );
1239 return QList<QRect>();
1241 double KCommonDecorationUnstable::shadowOpacity( ShadowType type ) const
1243 if( isActive() && type == ShadowBorderedActive )
1244 return 1.0;
1245 else if( !isActive() && type == ShadowBorderedInactive )
1246 return 1.0;
1247 return 0.0;
1249 double KCommonDecorationUnstable::shadowBrightness( ShadowType type ) const
1251 Q_UNUSED( type );
1252 return 1.0;
1254 double KCommonDecorationUnstable::shadowSaturation( ShadowType type ) const
1256 Q_UNUSED( type );
1257 return 1.0;
1260 void KCommonDecorationUnstable::repaintShadow()
1262 return static_cast<const KDecorationUnstable*>( decoration() )->repaintShadow();
1264 bool KCommonDecorationUnstable::compositingActive() const
1266 return static_cast<const KDecorationUnstable*>( decoration() )->compositingActive();
1268 bool KCommonDecorationUnstable::shadowsActive() const
1270 return static_cast<const KDecorationUnstable*>( decoration() )->shadowsActive();
1272 double KCommonDecorationUnstable::opacity() const
1274 return static_cast<const KDecorationUnstable*>( decoration() )->opacity();
1277 // kate: space-indent on; indent-width 4; mixedindent off; indent-mode cstyle;