Add a plasma based widget to add and remove desktops in desktop grid.

svn path=/trunk/KDE/kdebase/workspace/; revision=1108240
This commit is contained in:
Martin Gräßlin 2010-03-28 09:05:36 +00:00
parent ec8d860c4b
commit 8f82499f21
3 changed files with 372 additions and 41 deletions

View file

@ -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 )

View file

@ -35,6 +35,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QEvent>
#include <QMouseEvent>
#include <kglobalsettings.h>
#include <QtGui/QPainter>
#include <QtGui/QGraphicsLinearLayout>
#include <Plasma/PushButton>
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<PresentWindowsEffectProxy*>( effects->getProxy( "presentwindows" ) );
if( isUsingPresentWindows() )
{
for( int i=1; i<=effects->numberOfDesktops(); i++ )
{
for( int j=0; j<effects->numScreens(); 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; i<effects->numScreens(); ++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<PresentWindowsEffectProxy*>( effects->getProxy( "presentwindows" ) );
if( isUsingPresentWindows() )
{
for( int i=1; i<=effects->numberOfDesktops(); i++ )
{
for( int j=0; j<effects->numScreens(); 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; j<effects->numScreens(); 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; j<effects->numScreens(); ++j )
{
WindowMotionManager& manager = m_managers.last();
manager.unmanageAll();
m_managers.removeLast();
}
}
}
// add removed windows to the last desktop
if( isUsingPresentWindows() )
{
for( int j=0; j<effects->numScreens(); ++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"

View file

@ -25,12 +25,38 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kwineffects.h>
#include <kshortcut.h>
#include <QObject>
#include <QtGui/QGraphicsView>
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<ElectricBorder> borderActivate;
int zoomDuration;
@ -98,7 +130,7 @@ class DesktopGridEffect
// Soft highlighting
QList<TimeLine> 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