diff --git a/effects/presentwindows/presentwindows.cpp b/effects/presentwindows/presentwindows.cpp index d634a69ad7..d2c4b89e17 100644 --- a/effects/presentwindows/presentwindows.cpp +++ b/effects/presentwindows/presentwindows.cpp @@ -33,6 +33,10 @@ along with this program. If not, see . #endif #include +#include +#include +#include +#include #include #include @@ -54,6 +58,7 @@ PresentWindowsEffect::PresentWindowsEffect() , m_managerWindow( NULL ) , m_highlightedWindow( NULL ) , m_filterFrame( effects->effectFrame( EffectFrameStyled, false ) ) + , m_closeView( NULL ) { m_atomDesktop = XInternAtom( display(), "_KDE_PRESENT_WINDOWS_DESKTOP", False ); m_atomWindows = XInternAtom( display(), "_KDE_PRESENT_WINDOWS_GROUP", False ); @@ -107,6 +112,7 @@ PresentWindowsEffect::~PresentWindowsEffect() effects->unreserveElectricBorder( border ); } delete m_filterFrame; + delete m_closeView; } void PresentWindowsEffect::reconfigure( ReconfigureFlags ) @@ -277,7 +283,7 @@ void PresentWindowsEffect::prePaintWindow( EffectWindow *w, WindowPrePaintData & data.setTranslucent(); // Calculate window's brightness - if( w == m_highlightedWindow || !m_activated ) + if( w == m_highlightedWindow || w == m_closeWindow || !m_activated ) m_windowData[w].highlight = qMin( 1.0, m_windowData[w].highlight + time / m_fadeDuration ); else m_windowData[w].highlight = qMax( 0.0, m_windowData[w].highlight - time / m_fadeDuration ); @@ -394,6 +400,12 @@ void PresentWindowsEffect::windowAdded( EffectWindow *w ) m_motionManager.manage( w ); rearrangeWindows(); } + if( w == effects->findWindow( m_closeView->winId() ) ) + { + m_windowData[w].visible = true; + m_windowData[w].highlight = 1.0; + m_closeWindow = w; + } } void PresentWindowsEffect::windowClosed( EffectWindow *w ) @@ -408,6 +420,8 @@ void PresentWindowsEffect::windowClosed( EffectWindow *w ) if( m_highlightedWindow == w ) setHighlightedWindow( findFirstWindow() ); rearrangeWindows(); + if( m_closeWindow == w ) + m_closeWindow = 0; } void PresentWindowsEffect::windowDeleted( EffectWindow *w ) @@ -448,6 +462,20 @@ void PresentWindowsEffect::windowInputMouseEvent( Window w, QEvent *e ) assert( w == m_input ); Q_UNUSED( w ); + QMouseEvent* me = static_cast< QMouseEvent* >( e ); + if( m_closeView->geometry().contains( me->pos() ) ) + { + if( !m_closeView->isVisible() ) + { + updateCloseWindow(); + return; + } + const QPoint widgetPos = m_closeView->mapFromGlobal( me->pos() ); + const QPointF scenePos = m_closeView->mapToScene( widgetPos ); + QMouseEvent event( me->type(), widgetPos, me->pos(), me->button(), me->buttons(), me->modifiers() ); + m_closeView->windowInputMouseEvent( &event ); + return; + } // Which window are we hovering over? Always trigger as we don't always get move events before clicking // We cannot use m_motionManager.windowAtPoint() as the window might not be visible EffectWindowList windows = m_motionManager.managedWindows(); @@ -464,11 +492,14 @@ void PresentWindowsEffect::windowInputMouseEvent( Window w, QEvent *e ) break; } } + if( m_motionManager.transformedGeometry( m_highlightedWindow ).contains( me->pos() ) ) + updateCloseWindow(); + else + m_closeView->hide(); if( e->type() != QEvent::MouseButtonPress ) return; - QMouseEvent* me = static_cast( e ); if( me->button() == Qt::LeftButton ) { if( hovering ) @@ -842,6 +873,7 @@ void PresentWindowsEffect::rearrangeWindows() return; effects->addRepaintFull(); // Trigger the first repaint + m_closeView->hide(); // Work out which windows are on which screens EffectWindowList windowlist; @@ -1542,6 +1574,9 @@ void PresentWindowsEffect::setActive( bool active, bool closingTab ) m_highlightedWindow = NULL; m_windowFilter.clear(); + m_closeView = new CloseWindowView(); + connect( m_closeView, SIGNAL(close()), SLOT(closeWindow()) ); + // Add every single window to m_windowData (Just calling [w] creates it) foreach( EffectWindow *w, effects->stackingOrder() ) { @@ -1643,6 +1678,8 @@ void PresentWindowsEffect::setActive( bool active, bool closingTab ) m_windowData[w].visible = ( w->isOnDesktop( desktop ) || w->isOnAllDesktops() ) && !w->isMinimized() && ( w->visibleInClientGroup() || m_windowData[w].visible ); } + delete m_closeView; + m_closeView = 0; // Move all windows back to their original position foreach( EffectWindow *w, m_motionManager.managedWindows() ) @@ -1724,6 +1761,7 @@ void PresentWindowsEffect::setHighlightedWindow( EffectWindow *w ) if( w == m_highlightedWindow || ( w != NULL && !m_motionManager.isManaging( w ))) return; + m_closeView->hide(); if( m_highlightedWindow ) m_highlightedWindow->addRepaintFull(); // Trigger the first repaint m_highlightedWindow = w; @@ -1732,6 +1770,31 @@ void PresentWindowsEffect::setHighlightedWindow( EffectWindow *w ) if( m_tabBoxEnabled && m_highlightedWindow ) effects->setTabBoxWindow( w ); + updateCloseWindow(); + } + +void PresentWindowsEffect::updateCloseWindow() + { + if( m_closeView->isVisible() ) + return; + if( !m_highlightedWindow ) + { + m_closeView->hide(); + return; + } + const QRectF rect = m_motionManager.targetGeometry( m_highlightedWindow ); + m_closeView->setGeometry( rect.x() + rect.width() - m_closeView->sceneRect().width(), rect.y(), + m_closeView->sceneRect().width(), m_closeView->sceneRect().height() ); + if( rect.contains( effects->cursorPos() ) ) + m_closeView->show(); + else + m_closeView->hide(); + } + +void PresentWindowsEffect::closeWindow() + { + if( m_highlightedWindow ) + m_highlightedWindow->closeWindow(); } EffectWindow* PresentWindowsEffect::relativeWindow( EffectWindow *w, int xdiff, int ydiff, bool wrap ) const @@ -1933,6 +1996,78 @@ void PresentWindowsEffect::globalShortcutChangedClass( const QKeySequence& seq ) shortcutClass = KShortcut( seq ); } +/************************************************ +* CloseWindowView +************************************************/ +CloseWindowView::CloseWindowView( QWidget* parent ) + : QGraphicsView(parent) + { + setWindowFlags( Qt::X11BypassWindowManagerHint ); + setAttribute( Qt::WA_TranslucentBackground ); + setFrameShape( QFrame::NoFrame ); + QPalette pal = palette(); + pal.setColor( backgroundRole(), Qt::transparent ); + setPalette( pal ); + setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); + setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff ); + + // setup the scene + QGraphicsScene* scene = new QGraphicsScene( this ); + m_closeButton = new Plasma::PushButton(); + m_closeButton->setIcon( KIcon( "window-close" ) ); + scene->addItem( m_closeButton ); + connect( m_closeButton, SIGNAL(clicked()), SIGNAL(close())); + + QGraphicsLinearLayout *layout = new QGraphicsLinearLayout; + layout->addItem( m_closeButton ); + + QGraphicsWidget *form = new QGraphicsWidget; + form->setLayout( layout ); + form->setGeometry(0, 0, 32, 32); + scene->addItem( form ); + + m_frame = new Plasma::FrameSvg( this ); + m_frame->setImagePath( "dialogs/background" ); + m_frame->setCacheAllRenderedFrames( true ); + m_frame->setEnabledBorders( Plasma::FrameSvg::AllBorders ); + qreal left, top, right, bottom; + m_frame->getMargins( left, top, right, bottom ); + qreal width = form->size().width() + left + right; + qreal height = form->size().height() + top + bottom; + m_frame->resizeFrame( QSizeF( width, height ) ); + Plasma::WindowEffects::enableBlurBehind( winId(), true, m_frame->mask() ); + form->setPos( left, top ); + scene->setSceneRect( QRectF( QPointF( 0, 0 ), QSizeF( width, height ) ) ); + setScene( scene ); + } + +void CloseWindowView::windowInputMouseEvent( QMouseEvent* e ) + { + if( e->type() == QEvent::MouseMove ) + { + mouseMoveEvent( e ); + } + else if( e->type() == QEvent::MouseButtonPress ) + { + mousePressEvent( e ); + } + else if( e->type() == QEvent::MouseButtonDblClick ) + { + mouseDoubleClickEvent( e ); + } + else if( e->type() == QEvent::MouseButtonRelease ) + { + mouseReleaseEvent( e ); + } + } + +void CloseWindowView::drawBackground( QPainter* painter, const QRectF& rect ) + { + Q_UNUSED( rect ) + painter->setRenderHint( QPainter::Antialiasing ); + m_frame->paintFrame( painter ); + } + } // namespace #include "presentwindows.moc" diff --git a/effects/presentwindows/presentwindows.h b/effects/presentwindows/presentwindows.h index 24bc1a0da0..aa89e0309e 100644 --- a/effects/presentwindows/presentwindows.h +++ b/effects/presentwindows/presentwindows.h @@ -26,10 +26,32 @@ along with this program. If not, see . #include #include +#include + +namespace Plasma +{ +class PushButton; +} namespace KWin { +class CloseWindowView : public QGraphicsView + { + Q_OBJECT + public: + CloseWindowView( QWidget* parent = 0 ); + void windowInputMouseEvent( QMouseEvent* e ); + virtual void drawBackground( QPainter* painter, const QRectF& rect ); + + Q_SIGNALS: + void close(); + + private: + Plasma::PushButton* m_closeButton; + Plasma::FrameSvg* m_frame; + }; + /** * Expose-like effect which shows all windows on current desktop side-by-side, * letting the user select active window. @@ -132,6 +154,9 @@ class PresentWindowsEffect void globalShortcutChangedAll( const QKeySequence& seq ); void globalShortcutChangedClass( const QKeySequence& seq ); + private slots: + void closeWindow(); + protected: // Window rearranging void rearrangeWindows(); @@ -164,6 +189,7 @@ class PresentWindowsEffect void setHighlightedWindow( EffectWindow *w ); EffectWindow* relativeWindow( EffectWindow *w, int xdiff, int ydiff, bool wrap ) const; EffectWindow* findFirstWindow() const; + void updateCloseWindow(); // Helper functions for mouse actions void mouseActionWindow( WindowMouseAction& action ); @@ -230,6 +256,9 @@ class PresentWindowsEffect DesktopMouseAction m_leftButtonDesktop; DesktopMouseAction m_middleButtonDesktop; DesktopMouseAction m_rightButtonDesktop; + + CloseWindowView* m_closeView; + EffectWindow* m_closeWindow; }; } // namespace