diff --git a/effects/CMakeLists.txt b/effects/CMakeLists.txt
index c5529674d3..817ea21634 100644
--- a/effects/CMakeLists.txt
+++ b/effects/CMakeLists.txt
@@ -7,7 +7,7 @@ kde4_no_enable_final(kwineffects)
# Adds effect plugin with given name. Sources are given after the name
macro( KWIN4_ADD_EFFECT name )
kde4_add_plugin( kwin4_effect_${name} ${ARGN} )
- target_link_libraries( kwin4_effect_${name} kwineffects ${KDE4_KDEUI_LIBS} kephal )
+ target_link_libraries( kwin4_effect_${name} kwineffects ${KDE4_KDEUI_LIBS} kephal ${KDE4_PLASMA_LIBS} )
install( TARGETS kwin4_effect_${name} DESTINATION ${PLUGIN_INSTALL_DIR} )
endmacro( KWIN4_ADD_EFFECT )
diff --git a/effects/desktopgrid/desktopgrid.cpp b/effects/desktopgrid/desktopgrid.cpp
index 3238a64073..f649ddb5a8 100644
--- a/effects/desktopgrid/desktopgrid.cpp
+++ b/effects/desktopgrid/desktopgrid.cpp
@@ -35,6 +35,9 @@ along with this program. If not, see .
#include
#include
#include
+#include
+#include
+#include
namespace KWin
{
@@ -157,6 +160,22 @@ void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
paintingDesktop = desktop;
effects->paintScreen( mask, region, d );
}
+
+ // paint the add desktop button
+ for( QHash< DesktopButtonsView*, EffectWindow*>::iterator it = m_desktopButtonsViews.begin();
+ it != m_desktopButtonsViews.end(); ++it )
+ {
+ if( !it.value() )
+ it.value() = effects->findWindow( it.key()->winId() );
+ if( it.value() )
+ {
+ WindowPaintData d( it.value() );
+ d.opacity *= timeline.value();
+ effects->drawWindow( it.value(), PAINT_WINDOW_TRANSFORMED | PAINT_WINDOW_TRANSLUCENT,
+ infiniteRegion(), d );
+ }
+ }
+
if( isUsingPresentWindows() && windowMove && wasWindowMove )
{
// the moving window has to be painted on top of all desktops
@@ -176,7 +195,8 @@ void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
{
QRect screenGeom = effects->clientArea( ScreenArea, screen, 0 );
PaintClipper pc( screenGeom ); // TODO: Doesn't work in XRender for some reason?
- for( int desktop = 1; desktop <= effects->numberOfDesktops(); desktop++ )
+ int desktop = 1;
+ foreach( EffectFrame* frame, desktopNames )
{
QPointF posTL( scalePos( screenGeom.topLeft(), desktop, screen ));
QPointF posBR( scalePos( screenGeom.bottomRight(), desktop, screen ));
@@ -196,8 +216,9 @@ void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
y = textArea.bottom();
else
y = textArea.center().y();
- desktopNames[desktop-1]->setPosition( QPoint( x, y ));
- desktopNames[desktop-1]->render( region, timeline.value(), 0.7 );
+ frame->setPosition( QPoint( x, y ));
+ frame->render( region, timeline.value(), 0.7 );
+ ++desktop;
}
}
}
@@ -267,6 +288,8 @@ void DesktopGridEffect::paintWindow( EffectWindow* w, int mask, QRegion region,
{
return; // will be painted on top of all other windows
}
+ if( m_desktopButtonsViews.values().contains( w ) )
+ return; // will be painted on top of all other windows
double xScale = data.xScale;
double yScale = data.yScale;
@@ -393,7 +416,7 @@ void DesktopGridEffect::windowAdded( EffectWindow* w )
void DesktopGridEffect::windowClosed( EffectWindow* w )
{
- if ( !activated )
+ if ( !activated && timeline.value() == 0 )
return;
if( w == windowMove )
{
@@ -418,6 +441,15 @@ void DesktopGridEffect::windowClosed( EffectWindow* w )
m_proxy->calculateWindowTransformations(manager.managedWindows(), w->screen(), manager);
}
}
+ for( QHash< DesktopButtonsView*, EffectWindow*>::iterator it = m_desktopButtonsViews.begin();
+ it != m_desktopButtonsViews.end(); ++it )
+ {
+ if( it.value() && it.value() == w )
+ {
+ w->refWindow();
+ break;
+ }
+ }
effects->addRepaintFull();
}
@@ -454,6 +486,20 @@ void DesktopGridEffect::windowInputMouseEvent( Window, QEvent* e )
|| timeline.value() != 1 ) // Block user input during animations
return;
QMouseEvent* me = static_cast< QMouseEvent* >( e );
+ for( QHash< DesktopButtonsView*, EffectWindow*>::iterator it = m_desktopButtonsViews.begin();
+ it != m_desktopButtonsViews.end(); ++it )
+ {
+ DesktopButtonsView* view = it.key();
+ if( !wasWindowMove && !wasDesktopMove && view->geometry().contains( me->pos() ) )
+ {
+ const QPoint widgetPos = view->mapFromGlobal( me->pos() );
+ const QPointF scenePos = view->mapToScene( widgetPos );
+ QMouseEvent event( me->type(), widgetPos, me->pos(), me->button(), me->buttons(), me->modifiers() );
+ view->windowInputMouseEvent( &event );
+ return;
+ }
+ }
+
if( e->type() == QEvent::MouseMove )
{
int d = posToDesktop( me->pos());
@@ -739,6 +785,12 @@ void DesktopGridEffect::grabbedKeyboardEvent( QKeyEvent* e )
setCurrentDesktop( highlightedDesktop );
setActive( false );
return;
+ case Qt::Key_Plus:
+ slotAddDesktop();
+ break;
+ case Qt::Key_Minus:
+ slotRemoveDesktop();
+ break;
default:
break;
}
@@ -1068,8 +1120,6 @@ void DesktopGridEffect::setActive( bool active )
{
if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this )
return; // Only one fullscreen effect at a time thanks
- if( effects->numberOfDesktops() < 2 )
- return; // No point if there is only one desktop
if( active && isMotionManagerMovingWindows() )
return; // Still moving windows from last usage - don't activate
if( activated == active )
@@ -1092,6 +1142,11 @@ void DesktopGridEffect::setActive( bool active )
}
}
setHighlightedDesktop( effects->currentDesktop() ); // Ensure selected desktop is highlighted
+ for( QHash< DesktopButtonsView*, EffectWindow*>::iterator it = m_desktopButtonsViews.begin();
+ it != m_desktopButtonsViews.end(); ++it )
+ {
+ it.key()->hide();
+ }
}
effects->addRepaintFull();
}
@@ -1117,19 +1172,64 @@ void DesktopGridEffect::setup()
// Create desktop name textures if enabled
if( desktopNameAlignment )
{
- desktopNames = new EffectFrame*[effects->numberOfDesktops()];
QFont font;
font.setBold( true );
font.setPointSize( 12 );
for( int i = 0; i < effects->numberOfDesktops(); i++ )
{
- desktopNames[i] = new EffectFrame( EffectFrame::Unstyled, false );
- desktopNames[i]->setFont( font );
- desktopNames[i]->setText( effects->desktopName( i+1 ));
- desktopNames[i]->setAlignment( desktopNameAlignment );
+ EffectFrame* frame = new EffectFrame( EffectFrame::Unstyled, false );
+ frame->setFont( font );
+ frame->setText( effects->desktopName( i+1 ));
+ frame->setAlignment( desktopNameAlignment );
+ desktopNames.append( frame );
}
}
+ setupGrid();
+ setCurrentDesktop( effects->currentDesktop() );
+ // setup the motion managers
+ if( m_usePresentWindows )
+ m_proxy = static_cast( effects->getProxy( "presentwindows" ) );
+ if( isUsingPresentWindows() )
+ {
+ for( int i=1; i<=effects->numberOfDesktops(); i++ )
+ {
+ for( int j=0; jnumScreens(); j++ )
+ {
+ WindowMotionManager manager;
+ foreach( EffectWindow* w, effects->stackingOrder() )
+ {
+ if( w->isOnDesktop( i ) && w->screen() == j && !w->isDesktop() && !w->isDock() &&
+ w->visibleInClientGroup() )
+ {
+ manager.manage( w );
+ }
+ }
+ m_proxy->calculateWindowTransformations(manager.managedWindows(), j, manager);
+ m_managers.append(manager);
+ }
+ }
+ }
+ bool enableAdd = effects->numberOfDesktops() < 20;
+ bool enableRemove = effects->numberOfDesktops() > 1;
+ for( int i=0; inumScreens(); ++i )
+ {
+ DesktopButtonsView* view = new DesktopButtonsView();
+ view->setAddDesktopEnabled( enableAdd );
+ view->setRemoveDesktopEnabled( enableRemove );
+ connect( view, SIGNAL(addDesktop()), SLOT(slotAddDesktop()));
+ connect( view, SIGNAL(removeDesktop()), SLOT(slotRemoveDesktop()));
+ const QRect screenRect = effects->clientArea( FullScreenArea, i, 1 );
+ view->setGeometry( screenRect.right() + 1 - view->sceneRect().width(),
+ screenRect.bottom() + 1 - view->sceneRect().height(),
+ view->sceneRect().width(), view->sceneRect().height() );
+ view->show();
+ m_desktopButtonsViews.insert( view, NULL );
+ }
+ }
+
+void DesktopGridEffect::setupGrid()
+ {
// We need these variables for every paint so lets cache them
int x, y;
int numDesktops = effects->numberOfDesktops();
@@ -1155,7 +1255,6 @@ void DesktopGridEffect::setup()
gridSize.setHeight( customLayoutRows );
break;
}
- setCurrentDesktop( effects->currentDesktop() );
scale.clear();
unscaledBorder.clear();
scaledSize.clear();
@@ -1182,39 +1281,14 @@ void DesktopGridEffect::setup()
scaledSize.append( size );
scaledOffset.append( offset );
}
-
- // setup the motion managers
- if( m_usePresentWindows )
- m_proxy = static_cast( effects->getProxy( "presentwindows" ) );
- if( isUsingPresentWindows() )
- {
- for( int i=1; i<=effects->numberOfDesktops(); i++ )
- {
- for( int j=0; jnumScreens(); j++ )
- {
- WindowMotionManager manager;
- foreach( EffectWindow* w, effects->stackingOrder() )
- {
- if( w->isOnDesktop( i ) && w->screen() == j && !w->isDesktop() && !w->isDock() &&
- w->visibleInClientGroup() )
- {
- manager.manage( w );
- }
- }
- m_proxy->calculateWindowTransformations(manager.managedWindows(), j, manager);
- m_managers.append(manager);
- }
- }
- }
}
void DesktopGridEffect::finish()
{
if( desktopNameAlignment )
{
- for( int i = 0; i < effects->numberOfDesktops(); i++ )
- delete desktopNames[i];
- delete[] desktopNames;
+ qDeleteAll(desktopNames);
+ desktopNames.clear();
}
if( keyboardGrab )
@@ -1231,6 +1305,15 @@ void DesktopGridEffect::finish()
}
m_proxy = 0;
}
+ while( !m_desktopButtonsViews.isEmpty() )
+ {
+ DesktopButtonsView* view = m_desktopButtonsViews.begin().key();
+ m_desktopButtonsViews[ view ]->unrefWindow();
+ m_desktopButtonsViews[ view ] = 0;
+ m_desktopButtonsViews.remove( view );
+ delete view;
+ view = 0;
+ }
}
void DesktopGridEffect::globalShortcutChanged( const QKeySequence& seq )
@@ -1286,6 +1369,220 @@ QRectF DesktopGridEffect::moveGeometryToDesktop( int desktop ) const
return QRectF( point, m_windowMoveGeometry.size() / scaleFactor );
}
+void DesktopGridEffect::slotAddDesktop()
+ {
+ effects->setNumberOfDesktops( effects->numberOfDesktops() + 1 );
+ }
+
+void DesktopGridEffect::slotRemoveDesktop()
+ {
+ effects->setNumberOfDesktops( effects->numberOfDesktops() - 1 );
+ }
+
+void DesktopGridEffect::numberDesktopsChanged( int old )
+ {
+ if( !activated )
+ return;
+ const int desktop = effects->numberOfDesktops();
+ bool enableAdd = desktop < 20;
+ bool enableRemove = desktop > 1;
+ for( QHash< DesktopButtonsView*, EffectWindow* >::iterator it = m_desktopButtonsViews.begin();
+ it != m_desktopButtonsViews.end(); ++it )
+ {
+ it.key()->setAddDesktopEnabled( enableAdd );
+ it.key()->setRemoveDesktopEnabled( enableRemove );
+ }
+ if( old < desktop )
+ desktopsAdded( old );
+ else
+ desktopsRemoved( old );
+ }
+
+void DesktopGridEffect::desktopsAdded( int old )
+ {
+ const int desktop = effects->numberOfDesktops();
+ for( int i=old; i<=effects->numberOfDesktops(); i++ )
+ {
+ // add a timeline for the new desktop
+ TimeLine newTimeline( animationTime( zoomDuration ));
+ newTimeline.setCurveShape( TimeLine::EaseInOutCurve );
+ hoverTimeline.append( newTimeline );
+ }
+
+ // Create desktop name textures if enabled
+ if( desktopNameAlignment )
+ {
+ QFont font;
+ font.setBold( true );
+ font.setPointSize( 12 );
+ for( int i = old; i < desktop; i++ )
+ {
+ EffectFrame* frame = new EffectFrame( EffectFrame::Unstyled, false );
+ frame->setFont( font );
+ frame->setText( effects->desktopName( i+1 ));
+ frame->setAlignment( desktopNameAlignment );
+ desktopNames.append( frame );
+ }
+ }
+
+ if( isUsingPresentWindows() )
+ {
+ for( int i=old; i<=effects->numberOfDesktops(); i++ )
+ {
+ for( int j=0; jnumScreens(); j++ )
+ {
+ WindowMotionManager manager;
+ foreach( EffectWindow* w, effects->stackingOrder() )
+ {
+ if( w->isOnDesktop( i ) && w->screen() == j && !w->isDesktop() && !w->isDock() &&
+ w->visibleInClientGroup() )
+ {
+ manager.manage( w );
+ }
+ }
+ m_proxy->calculateWindowTransformations(manager.managedWindows(), j, manager);
+ m_managers.append(manager);
+ }
+ }
+ }
+
+ setupGrid();
+
+ // and repaint
+ effects->addRepaintFull();
+ }
+
+void DesktopGridEffect::desktopsRemoved( int old )
+ {
+ const int desktop = effects->numberOfDesktops();
+ for( int i = desktop; i < old; i++ )
+ {
+ hoverTimeline.removeLast();
+ if( desktopNameAlignment )
+ {
+ delete desktopNames.last();
+ desktopNames.removeLast();
+ }
+ if( isUsingPresentWindows() )
+ {
+ for( int j=0; jnumScreens(); ++j )
+ {
+ WindowMotionManager& manager = m_managers.last();
+ manager.unmanageAll();
+ m_managers.removeLast();
+ }
+ }
+ }
+ // add removed windows to the last desktop
+ if( isUsingPresentWindows() )
+ {
+ for( int j=0; jnumScreens(); ++j )
+ {
+ WindowMotionManager& manager = m_managers[ (desktop-1)*(effects->numScreens())+j ];
+ foreach( EffectWindow* w, effects->stackingOrder() )
+ {
+ if( !manager.isManaging( w ) && w->isOnDesktop( desktop ) && w->screen() == j &&
+ !w->isDesktop() && !w->isDock() && w->visibleInClientGroup() )
+ {
+ manager.manage( w );
+ }
+ }
+ m_proxy->calculateWindowTransformations( manager.managedWindows(), j, manager );
+ }
+ }
+
+ setupGrid();
+
+ // and repaint
+ effects->addRepaintFull();
+ }
+
+/************************************************
+* DesktopButtonView
+************************************************/
+DesktopButtonsView::DesktopButtonsView( 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_addDesktopButton = new Plasma::PushButton();
+ m_addDesktopButton->setIcon( KIcon( "list-add" ) );
+ m_removeDesktopButton = new Plasma::PushButton();
+ m_removeDesktopButton->setIcon(KIcon("list-remove"));
+ scene->addItem( m_addDesktopButton );
+ scene->addItem( m_removeDesktopButton );
+ connect( m_addDesktopButton, SIGNAL(clicked()), SIGNAL(addDesktop()));
+ connect( m_removeDesktopButton, SIGNAL(clicked()), SIGNAL(removeDesktop()));
+
+ QGraphicsLinearLayout *layout = new QGraphicsLinearLayout;
+ layout->addItem( m_addDesktopButton );
+ layout->addItem( m_removeDesktopButton );
+
+ QGraphicsWidget *form = new QGraphicsWidget;
+ form->setLayout( layout );
+ form->setGeometry(0, 0, 64*2, 64);
+ 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 ) );
+ form->setPos( left, top );
+ scene->setSceneRect( QRectF( QPointF( 0, 0 ), QSizeF( width, height ) ) );
+ setScene( scene );
+ }
+
+void DesktopButtonsView::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 DesktopButtonsView::setAddDesktopEnabled( bool enable )
+ {
+ m_addDesktopButton->setEnabled( enable );
+ }
+
+void DesktopButtonsView::setRemoveDesktopEnabled( bool enable )
+ {
+ m_removeDesktopButton->setEnabled( enable );
+ }
+
+void DesktopButtonsView::drawBackground( QPainter* painter, const QRectF& rect )
+ {
+ Q_UNUSED( rect )
+ painter->setRenderHint( QPainter::Antialiasing );
+ m_frame->paintFrame( painter );
+ }
+
} // namespace
#include "desktopgrid.moc"
diff --git a/effects/desktopgrid/desktopgrid.h b/effects/desktopgrid/desktopgrid.h
index f6b73a1d1f..4fd3cea203 100644
--- a/effects/desktopgrid/desktopgrid.h
+++ b/effects/desktopgrid/desktopgrid.h
@@ -25,12 +25,38 @@ along with this program. If not, see .
#include
#include
#include
+#include
+
+namespace Plasma
+{
+class PushButton;
+}
namespace KWin
{
class PresentWindowsEffectProxy;
+class DesktopButtonsView : public QGraphicsView
+ {
+ Q_OBJECT
+ public:
+ DesktopButtonsView( QWidget* parent = 0 );
+ void windowInputMouseEvent( QMouseEvent* e );
+ void setAddDesktopEnabled( bool enable );
+ void setRemoveDesktopEnabled( bool enable );
+ virtual void drawBackground( QPainter* painter, const QRectF& rect );
+
+ Q_SIGNALS:
+ void addDesktop();
+ void removeDesktop();
+
+ private:
+ Plasma::PushButton* m_addDesktopButton;
+ Plasma::PushButton* m_removeDesktopButton;
+ Plasma::FrameSvg* m_frame;
+ };
+
class DesktopGridEffect
: public QObject, public Effect
{
@@ -50,6 +76,7 @@ class DesktopGridEffect
virtual void windowInputMouseEvent( Window w, QEvent* e );
virtual void grabbedKeyboardEvent( QKeyEvent* e );
virtual bool borderActivated( ElectricBorder border );
+ virtual void numberDesktopsChanged( int old );
enum { LayoutPager, LayoutAutomatic, LayoutCustom }; // Layout modes
@@ -58,6 +85,8 @@ class DesktopGridEffect
// slots for global shortcut changed
// needed to toggle the effect
void globalShortcutChanged( const QKeySequence& seq );
+ void slotAddDesktop();
+ void slotRemoveDesktop();
private:
QPointF scalePos( const QPoint& pos, int desktop, int screen = -1 ) const;
@@ -72,10 +101,13 @@ class DesktopGridEffect
int desktopDown( int desktop, bool wrap = true ) const;
void setActive( bool active );
void setup();
+ void setupGrid();
void finish();
bool isMotionManagerMovingWindows();
bool isUsingPresentWindows() const;
QRectF moveGeometryToDesktop( int desktop ) const;
+ void desktopsAdded( int old );
+ void desktopsRemoved( int old );
QList borderActivate;
int zoomDuration;
@@ -98,7 +130,7 @@ class DesktopGridEffect
// Soft highlighting
QList hoverTimeline;
- EffectFrame** desktopNames;
+ QList< EffectFrame* > desktopNames;
QSize gridSize;
Qt::Orientation orientation;
@@ -118,6 +150,8 @@ class DesktopGridEffect
QRect m_windowMoveGeometry;
QPoint m_windowMoveStartPoint;
+ QHash< DesktopButtonsView*, EffectWindow* > m_desktopButtonsViews;
+
};
} // namespace