Improved the desktop grid effect.

FEATURE: 163104, 167265, 168557
CCBUG: 156247, 157196, 158787

svn path=/trunk/KDE/kdebase/workspace/; revision=845893
This commit is contained in:
Lucas Murray 2008-08-12 15:22:06 +00:00
parent ff13bd5ed5
commit fe4c100195
11 changed files with 1148 additions and 551 deletions

View file

@ -229,7 +229,6 @@ Effects TODO
/ desktopgrid
+ - there's a bug that causes overlapping windows be shown also on desktops painted sooner than the window's desktop
- needs clipping (and that probably needs support for cumulating clipping)
! - make desktop borders distinctive (i.e. paint a grid), to make it more visible that desktops are still separate
Performance

View file

@ -51,6 +51,7 @@ SET(kwin4_effect_builtins_sources
shadow.cpp
showfps.cpp
showpaint.cpp
slide.cpp
taskbarthumbnail.cpp
thumbnailaside.cpp
zoom.cpp
@ -74,6 +75,7 @@ install( FILES
shadow.desktop
showfps.desktop
showpaint.desktop
slide.desktop
taskbarthumbnail.desktop
thumbnailaside.desktop
zoom.desktop
@ -82,6 +84,7 @@ install( FILES
# config modules
SET(kwin4_effect_builtins_config_sources
desktopgrid_config.cpp
desktopgrid_config.ui
diminactive_config.cpp
diminactive_config.ui
maketransparent_config.cpp

File diff suppressed because it is too large Load diff

View file

@ -115,10 +115,10 @@ Comment[zh_TW]=將桌面以格狀佈局呈現的桌面切換器
Type=Service
X-KDE-ServiceTypes=KWin/Effect
X-KDE-PluginInfo-Author=Luboš Luňák
X-KDE-PluginInfo-Email=l.lunak@kde.org
X-KDE-PluginInfo-Author=Luboš Luňák & Lucas Murray
X-KDE-PluginInfo-Email=l.lunak@kde.org & lmurray@undefinedfire.com
X-KDE-PluginInfo-Name=kwin4_effect_desktopgrid
X-KDE-PluginInfo-Version=0.1.0
X-KDE-PluginInfo-Version=0.2.0
X-KDE-PluginInfo-Category=Window Management
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL

View file

@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
Copyright (C) 2008 Lucas Murray <lmurray@undefinedfire.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -40,40 +41,50 @@ class DesktopGridEffect
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void windowClosed( EffectWindow* w );
virtual void desktopChanged( int old );
virtual void windowInputMouseEvent( Window w, QEvent* e );
virtual void grabbedKeyboardEvent( QKeyEvent* e );
virtual bool borderActivated( ElectricBorder border );
private slots:
void toggle();
private:
QRect desktopRect( int desktop, bool scaled ) const;
QPointF scalePos( const QPoint& pos, int desktop, int screen = -1 ) const;
QPoint unscalePos( const QPoint& pos, int* desktop = NULL ) const;
int posToDesktop( const QPoint& pos ) const;
QRect windowRect( EffectWindow* w ) const; // returns always scaled
EffectWindow* windowAt( const QPoint& pos, QRect* rect = NULL ) const;
EffectWindow* windowAt( QPoint pos ) const;
void setCurrentDesktop( int desktop );
void setHighlightedDesktop( int desktop );
void setActive( bool active );
void setup();
void finish();
void paintSlide( int mask, QRegion region, const ScreenPaintData& data );
void paintScreenDesktop( int desktop, int mask, QRegion region, ScreenPaintData data );
void slideDesktopChanged( int old );
void setHighlightedDesktop( int desktop );
bool activated;
TimeLine mTimeLine;
int painting_desktop;
int highlighted_desktop;
Window input;
bool keyboard_grab;
bool was_window_move;
EffectWindow* window_move;
QPoint window_move_diff;
QPoint window_move_pos;
bool slideEnabled;
bool slide;
QPoint slide_start_pos;
bool slide_painting_sticky;
QPoint slide_painting_diff;
ElectricBorder borderActivate;
int zoomDuration;
int border;
Qt::Alignment desktopNameAlignment;
bool customLayout;
int customLayoutRows;
bool activated;
TimeLine timeline;
int paintingDesktop;
int highlightedDesktop;
Window input;
bool keyboardGrab;
bool wasWindowMove;
EffectWindow* windowMove;
QPoint windowMoveDiff;
// Soft highlighting
QList<TimeLine> hoverTimeline;
QSize gridSize;
Qt::Orientation orientation;
QPoint activeCell;
// Per screen variables
QList<double> scale; // Because the border isn't a ratio each screen is different
QList<double> unscaledBorder;
QList<QSizeF> scaledSize;
QList<QPointF> scaledOffset;
};

View file

@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
Copyright (C) 2008 Lucas Murray <lmurray@undefinedfire.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -19,123 +20,178 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "desktopgrid_config.h"
#include <kwineffects.h>
#include <klocale.h>
#include <kdebug.h>
#include <kconfiggroup.h>
#include <KActionCollection>
#include <kaction.h>
#include <KShortcutsEditor>
#include <kconfiggroup.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QCheckBox>
#include <QComboBox>
#include <QLabel>
#include <QColor>
#ifndef KDE_USE_FINAL
KWIN_EFFECT_CONFIG_FACTORY
#endif
namespace KWin
{
DesktopGridEffectConfig::DesktopGridEffectConfig(QWidget* parent, const QVariantList& args) :
KCModule(EffectFactory::componentData(), parent, args)
DesktopGridEffectConfigForm::DesktopGridEffectConfigForm(QWidget* parent) : QWidget(parent)
{
setupUi(this);
}
DesktopGridEffectConfig::DesktopGridEffectConfig(QWidget* parent, const QVariantList& args)
: KCModule( EffectFactory::componentData(), parent, args )
{
kDebug() ;
m_ui = new DesktopGridEffectConfigForm( this );
QVBoxLayout* layout = new QVBoxLayout(this);
QVBoxLayout* layout = new QVBoxLayout( this );
mSlide = new QCheckBox(i18n("Animate desktop changes"), this);
connect(mSlide, SIGNAL(toggled(bool)), this, SLOT(changed()));
layout->addWidget(mSlide);
layout->addWidget( m_ui );
QHBoxLayout* comboLayout = new QHBoxLayout();
QLabel* label = new QLabel(i18n("Activate when cursor is at a specific edge "
"or corner of the screen:"), this);
m_actionCollection = new KActionCollection( this, componentData() );
m_actionCollection->setConfigGroup( "DesktopGrid" );
m_actionCollection->setConfigGlobal( true );
mActivateCombo = new QComboBox;
mActivateCombo->addItem(i18n("Top"));
mActivateCombo->addItem(i18n("Top-right"));
mActivateCombo->addItem(i18n("Right"));
mActivateCombo->addItem(i18n("Bottom-right"));
mActivateCombo->addItem(i18n("Bottom"));
mActivateCombo->addItem(i18n("Bottom-left"));
mActivateCombo->addItem(i18n("Left"));
mActivateCombo->addItem(i18n("Top-left"));
mActivateCombo->addItem(i18n("None"));
connect(mActivateCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed()));
comboLayout->addWidget(label);
comboLayout->addWidget(mActivateCombo);
layout->addLayout(comboLayout);
KAction* a = (KAction*) m_actionCollection->addAction( "ShowDesktopGrid" );
a->setText( i18n( "Show Desktop Grid" ));
a->setProperty( "isConfigurationAction", true );
a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F8 ));
KActionCollection* actionCollection = new KActionCollection( this, componentData() );
KAction* show = static_cast<KAction*>(actionCollection->addAction( "ShowDesktopGrid" ));
show->setText( i18n("Show Desktop Grid" ));
show->setProperty("isConfigurationAction", true);
show->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F8 ));
m_ui->shortcutEditor->addCollection( m_actionCollection );
mShortcutEditor = new KShortcutsEditor(actionCollection, this,
KShortcutsEditor::GlobalAction, KShortcutsEditor::LetterShortcutsDisallowed);
connect(mShortcutEditor, SIGNAL(keyChange()), this, SLOT(changed()));
layout->addWidget(mShortcutEditor);
m_ui->screenEdgeCombo->addItem( i18n( "Top" ));
m_ui->screenEdgeCombo->addItem( i18n( "Top-right" ));
m_ui->screenEdgeCombo->addItem( i18n( "Right" ));
m_ui->screenEdgeCombo->addItem( i18n( "Bottom-right" ));
m_ui->screenEdgeCombo->addItem( i18n( "Bottom" ));
m_ui->screenEdgeCombo->addItem( i18n( "Bottom-left" ));
m_ui->screenEdgeCombo->addItem( i18n( "Left" ));
m_ui->screenEdgeCombo->addItem( i18n( "Top-left" ));
m_ui->screenEdgeCombo->addItem( i18n( "None" ));
layout->addStretch();
m_alignmentItems.append( Qt::Alignment( 0 ));
m_ui->desktopNameAlignmentCombo->addItem( i18n( "Disabled" ));
m_alignmentItems.append( Qt::AlignHCenter | Qt::AlignTop );
m_ui->desktopNameAlignmentCombo->addItem( i18n( "Top" ));
m_alignmentItems.append( Qt::AlignRight | Qt::AlignTop );
m_ui->desktopNameAlignmentCombo->addItem( i18n( "Top-right" ));
m_alignmentItems.append( Qt::AlignRight | Qt::AlignVCenter );
m_ui->desktopNameAlignmentCombo->addItem( i18n( "Right" ));
m_alignmentItems.append( Qt::AlignRight | Qt::AlignBottom );
m_ui->desktopNameAlignmentCombo->addItem( i18n( "Bottom-right" ));
m_alignmentItems.append( Qt::AlignHCenter | Qt::AlignBottom );
m_ui->desktopNameAlignmentCombo->addItem( i18n( "Bottom" ));
m_alignmentItems.append( Qt::AlignLeft | Qt::AlignBottom );
m_ui->desktopNameAlignmentCombo->addItem( i18n( "Bottom-left" ));
m_alignmentItems.append( Qt::AlignLeft | Qt::AlignVCenter );
m_ui->desktopNameAlignmentCombo->addItem( i18n( "Left" ));
m_alignmentItems.append( Qt::AlignLeft | Qt::AlignTop );
m_ui->desktopNameAlignmentCombo->addItem( i18n( "Top-left" ));
m_alignmentItems.append( Qt::AlignCenter );
m_ui->desktopNameAlignmentCombo->addItem( i18n( "Center" ));
connect( m_ui->screenEdgeCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() ));
connect( m_ui->zoomDurationSpin, SIGNAL( valueChanged( int )), this, SLOT( changed() ));
connect( m_ui->borderWidthSpin, SIGNAL( valueChanged( int )), this, SLOT( changed() ));
connect( m_ui->desktopNameAlignmentCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() ));
connect( m_ui->layoutBox, SIGNAL( stateChanged( int )), this, SLOT( changed() ));
connect( m_ui->layoutBox, SIGNAL( stateChanged( int )), this, SLOT( layoutSelectionChanged() ));
connect( m_ui->layoutRowsSpin, SIGNAL( valueChanged( int )), this, SLOT( changed() ));
connect( m_ui->shortcutEditor, SIGNAL( keyChange() ), this, SLOT( changed() ));
load();
}
DesktopGridEffectConfig::~DesktopGridEffectConfig()
{
kDebug();
// Undo (only) unsaved changes to global key shortcuts
mShortcutEditor->undoChanges();
// If save() is called undoChanges() has no effect
m_ui->shortcutEditor->undoChanges();
}
void DesktopGridEffectConfig::load()
{
kDebug();
KCModule::load();
KConfigGroup conf = EffectsHandler::effectConfig("DesktopGrid");
mSlide->setChecked(conf.readEntry("Slide", true));
int activateBorder = conf.readEntry("BorderActivate", (int)ElectricNone);
if(activateBorder == (int)ElectricNone)
KConfigGroup conf = EffectsHandler::effectConfig( "DesktopGrid" );
int activateBorder = conf.readEntry( "BorderActivate", int( ElectricNone ));
if( activateBorder == int( ElectricNone ))
activateBorder--;
mActivateCombo->setCurrentIndex(activateBorder);
m_ui->screenEdgeCombo->setCurrentIndex( activateBorder );
m_ui->zoomDurationSpin->setValue( conf.readEntry( "ZoomDuration", 500 ));
m_ui->borderWidthSpin->setValue( conf.readEntry( "BorderWidth", 10 ));
Qt::Alignment alignment = Qt::Alignment( conf.readEntry( "DesktopNameAlignment", 0 ));
m_ui->desktopNameAlignmentCombo->setCurrentIndex( m_alignmentItems.indexOf( alignment ));
if( conf.readEntry( "CustomLayout", false ))
m_ui->layoutBox->setCheckState( Qt::Checked );
else
m_ui->layoutBox->setCheckState( Qt::Unchecked );
layoutSelectionChanged();
m_ui->layoutRowsSpin->setValue( conf.readEntry( "CustomLayoutRows", 2 ));
emit changed(false);
}
void DesktopGridEffectConfig::save()
{
kDebug() ;
KCModule::save();
KConfigGroup conf = EffectsHandler::effectConfig("DesktopGrid");
conf.writeEntry("Slide", mSlide->isChecked());
KConfigGroup conf = EffectsHandler::effectConfig( "DesktopGrid" );
int activateBorder = m_ui->screenEdgeCombo->currentIndex();
if( activateBorder == int( ELECTRIC_COUNT ))
activateBorder = int( ElectricNone );
conf.writeEntry( "BorderActivate", activateBorder );
conf.writeEntry( "ZoomDuration", m_ui->zoomDurationSpin->value() );
conf.writeEntry( "BorderWidth", m_ui->borderWidthSpin->value() );
int alignment = m_ui->desktopNameAlignmentCombo->currentIndex();
alignment = int( m_alignmentItems[alignment] );
conf.writeEntry( "DesktopNameAlignment", alignment );
conf.writeEntry( "CustomLayout", m_ui->layoutBox->checkState() == Qt::Checked ? 1 : 0 );
conf.writeEntry( "CustomLayoutRows", m_ui->layoutRowsSpin->value() );
m_ui->shortcutEditor->save();
int activateBorder = mActivateCombo->currentIndex();
if(activateBorder == (int)ELECTRIC_COUNT)
activateBorder = (int)ElectricNone;
conf.writeEntry("BorderActivate", activateBorder);
conf.sync();
mShortcutEditor->save(); // undo() will restore to this state from now on
emit changed(false);
EffectsHandler::sendReloadMessage( "desktopgrid" );
}
void DesktopGridEffectConfig::defaults()
{
kDebug() ;
mSlide->setChecked(true);
mActivateCombo->setCurrentIndex( (int)ElectricNone -1 );
mShortcutEditor->allDefault();
m_ui->screenEdgeCombo->setCurrentIndex( int( ElectricNone - 1 ));
m_ui->zoomDurationSpin->setValue( 500 );
m_ui->borderWidthSpin->setValue( 10 );
m_ui->desktopNameAlignmentCombo->setCurrentIndex( 0 );
m_ui->layoutBox->setCheckState( Qt::Unchecked );
m_ui->layoutRowsSpin->setValue( 2 );
m_ui->shortcutEditor->allDefault();
emit changed(true);
}
void DesktopGridEffectConfig::layoutSelectionChanged()
{
if( m_ui->layoutBox->checkState() == Qt::Checked )
{
m_ui->layoutRowsLabel->setEnabled( true );
m_ui->layoutRowsSpin->setEnabled( true );
}
else
{
m_ui->layoutRowsLabel->setEnabled( false );
m_ui->layoutRowsSpin->setEnabled( false );
}
}
} // namespace
#include "desktopgrid_config.moc"

View file

@ -3,6 +3,7 @@
This file is part of the KDE project.
Copyright (C) 2007 Rivo Laks <rivolaks@hot.ee>
Copyright (C) 2008 Lucas Murray <lmurray@undefinedfire.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -23,13 +24,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kcmodule.h>
class QComboBox;
class QCheckBox;
class KShortcutsEditor;
#include "ui_desktopgrid_config.h"
namespace KWin
{
class DesktopGridEffectConfigForm : public QWidget, public Ui::DesktopGridEffectConfigForm
{
Q_OBJECT
public:
explicit DesktopGridEffectConfigForm(QWidget* parent);
};
class DesktopGridEffectConfig : public KCModule
{
Q_OBJECT
@ -42,10 +48,13 @@ class DesktopGridEffectConfig : public KCModule
virtual void load();
virtual void defaults();
private slots:
void layoutSelectionChanged();
private:
QCheckBox* mSlide;
QComboBox* mActivateCombo;
KShortcutsEditor *mShortcutEditor;
DesktopGridEffectConfigForm* m_ui;
KActionCollection* m_actionCollection;
QList<Qt::Alignment> m_alignmentItems;
};
} // namespace

View file

@ -0,0 +1,178 @@
<ui version="4.0" >
<class>KWin::DesktopGridEffectConfigForm</class>
<widget class="QWidget" name="KWin::DesktopGridEffectConfigForm" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>508</width>
<height>221</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2" >
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>Appearance</string>
</property>
<layout class="QGridLayout" name="gridLayout_3" >
<item row="2" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>Zoom &amp;duration:</string>
</property>
<property name="buddy" >
<cstring>zoomDurationSpin</cstring>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="QSpinBox" name="zoomDurationSpin" >
<property name="suffix" >
<string> msec</string>
</property>
<property name="maximum" >
<number>5000</number>
</property>
<property name="value" >
<number>500</number>
</property>
</widget>
</item>
<item row="4" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>&amp;Border width:</string>
</property>
<property name="buddy" >
<cstring>borderWidthSpin</cstring>
</property>
</widget>
</item>
<item row="4" column="1" >
<widget class="QSpinBox" name="borderWidthSpin" >
<property name="suffix" >
<string> pixels</string>
</property>
<property name="maximum" >
<number>100</number>
</property>
<property name="value" >
<number>10</number>
</property>
</widget>
</item>
<item row="6" column="0" >
<widget class="QLabel" name="label_6" >
<property name="text" >
<string>Desktop &amp;name alignment:</string>
</property>
<property name="buddy" >
<cstring>desktopNameAlignmentCombo</cstring>
</property>
</widget>
</item>
<item row="6" column="1" >
<widget class="QComboBox" name="desktopNameAlignmentCombo" />
</item>
<item row="7" column="0" >
<widget class="QCheckBox" name="layoutBox" >
<property name="text" >
<string>Custom grid &amp;layout</string>
</property>
</widget>
</item>
<item row="8" column="0" >
<widget class="QLabel" name="layoutRowsLabel" >
<property name="text" >
<string>Number of &amp;rows:</string>
</property>
<property name="buddy" >
<cstring>layoutRowsSpin</cstring>
</property>
</widget>
</item>
<item row="8" column="1" >
<widget class="QSpinBox" name="layoutRowsSpin" >
<property name="suffix" >
<string> rows</string>
</property>
<property name="minimum" >
<number>1</number>
</property>
<property name="maximum" >
<number>20</number>
</property>
<property name="value" >
<number>2</number>
</property>
</widget>
</item>
<item row="9" column="0" colspan="2" >
<spacer name="verticalSpacer" >
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0" >
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2" >
<property name="title" >
<string>Activation</string>
</property>
<layout class="QGridLayout" name="gridLayout_2" >
<item row="0" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>Active screen &amp;edge:</string>
</property>
<property name="buddy" >
<cstring>screenEdgeCombo</cstring>
</property>
</widget>
</item>
<item row="0" column="1" >
<widget class="QComboBox" name="screenEdgeCombo" />
</item>
<item row="1" column="0" colspan="2" >
<widget class="KWin::GlobalShortcutsEditor" native="1" name="shortcutEditor" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KWin::GlobalShortcutsEditor</class>
<extends>QWidget</extends>
<header location="global" >kwineffects.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>zoomDurationSpin</tabstop>
<tabstop>borderWidthSpin</tabstop>
<tabstop>desktopNameAlignmentCombo</tabstop>
<tabstop>layoutBox</tabstop>
<tabstop>layoutRowsSpin</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>

266
effects/slide.cpp Normal file
View file

@ -0,0 +1,266 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
Copyright (C) 2008 Lucas Murray <admin@undefinedfire.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#include "slide.h"
#include <math.h>
namespace KWin
{
KWIN_EFFECT( slide, SlideEffect )
SlideEffect::SlideEffect()
: slide( false )
{
mTimeLine.setCurveShape(TimeLine::EaseInOutCurve);
}
void SlideEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( slide )
{
mTimeLine.addTime(time);
// PAINT_SCREEN_BACKGROUND_FIRST is needed because screen will be actually painted more than once,
// so with normal screen painting second screen paint would erase parts of the first paint
if( mTimeLine.value() != 1 )
data.mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
else
{
slide = false;
mTimeLine.setProgress(0);
}
}
effects->prePaintScreen( data, time );
}
void SlideEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( slide )
{
if( w->isOnAllDesktops())
{
if( slide_painting_sticky )
data.setTransformed();
else
w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
}
else if( w->isOnDesktop( painting_desktop ))
w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
else
w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
}
effects->prePaintWindow( w, data, time );
}
void SlideEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
if( mTimeLine.value() == 0 )
{
effects->paintScreen( mask, region, data );
return;
}
/*
Transformations are done by remembering starting position of the change and the progress
of it, the destination is computed from the current desktop. Positions of desktops
are done using their topleft corner.
*/
QPoint destPos = desktopRect( effects->currentDesktop(), false ).topLeft();
QPoint diffPos = destPos - slide_start_pos;
int w = 0;
int h = 0;
if( effects->optionRollOverDesktops())
{
int x, y;
Qt::Orientation orientation;
effects->calcDesktopLayout( &x, &y, &orientation );
w = x * displayWidth();
h = y * displayHeight();
// wrap around if shorter
if( diffPos.x() > 0 && diffPos.x() > w / 2 )
diffPos.setX( diffPos.x() - w );
if( diffPos.x() < 0 && abs( diffPos.x()) > w / 2 )
diffPos.setX( diffPos.x() + w );
if( diffPos.y() > 0 && diffPos.y() > h / 2 )
diffPos.setY( diffPos.y() - h );
if( diffPos.y() < 0 && abs( diffPos.y()) > h / 2 )
diffPos.setY( diffPos.y() + h );
}
QPoint currentPos = slide_start_pos + mTimeLine.value() * diffPos;
QSize displaySize( displayWidth(), displayHeight());
QRegion currentRegion = QRect( currentPos, displaySize );
if( effects->optionRollOverDesktops())
{
currentRegion |= ( currentRegion & QRect( -w, 0, w, h )).translated( w, 0 );
currentRegion |= ( currentRegion & QRect( 0, -h, w, h )).translated( 0, h );
currentRegion |= ( currentRegion & QRect( w, 0, w, h )).translated( -w, 0 );
currentRegion |= ( currentRegion & QRect( 0, h, w, h )).translated( 0, -h );
}
bool do_sticky = true;
for( int desktop = 1;
desktop <= effects->numberOfDesktops();
++desktop )
{
QRect rect = desktopRect( desktop, false );
if( currentRegion.contains( rect )) // part of the desktop needs painting
{
painting_desktop = desktop;
slide_painting_sticky = do_sticky;
slide_painting_diff = rect.topLeft() - currentPos;
if( effects->optionRollOverDesktops())
{
if( slide_painting_diff.x() > displayWidth())
slide_painting_diff.setX( slide_painting_diff.x() - w );
if( slide_painting_diff.x() < -displayWidth())
slide_painting_diff.setX( slide_painting_diff.x() + w );
if( slide_painting_diff.y() > displayHeight())
slide_painting_diff.setY( slide_painting_diff.y() - h );
if( slide_painting_diff.y() < -displayHeight())
slide_painting_diff.setY( slide_painting_diff.y() + h );
}
do_sticky = false; // paint on-all-desktop windows only once
ScreenPaintData d = data;
d.xTranslate += slide_painting_diff.x();
d.yTranslate += slide_painting_diff.y();
// TODO mask parts that are not visible?
effects->paintScreen( mask, region, d );
}
}
}
void SlideEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
if( slide )
{ // don't move windows on all desktops (compensate screen transformation)
if( w->isOnAllDesktops()) // TODO also fix 'Workspace::movingClient'
{
data.xTranslate -= slide_painting_diff.x();
data.yTranslate -= slide_painting_diff.y();
}
}
effects->paintWindow( w, mask, region, data );
}
void SlideEffect::postPaintScreen()
{
if( slide )
effects->addRepaintFull();
effects->postPaintScreen();
}
// Gives a position of the given desktop when all desktops are arranged in a grid
QRect SlideEffect::desktopRect( int desktop, bool scaled ) const
{
int x, y;
Qt::Orientation orientation;
effects->calcDesktopLayout( &x, &y, &orientation );
--desktop; // make it start with 0
QRect rect;
if( orientation == Qt::Horizontal )
rect = QRect(( desktop % x ) * displayWidth(), ( desktop / x ) * displayHeight(),
displayWidth(), displayHeight());
else
rect = QRect(( desktop / y ) * displayWidth(), ( desktop % y ) * displayHeight(),
displayWidth(), displayHeight());
if( !scaled )
return rect;
QRect current = desktopRect( effects->currentDesktop(), false );
double progress = mTimeLine.value();
rect = QRect( qRound( interpolate( rect.x() - current.x(), rect.x() / double( x ), progress )),
qRound( interpolate( rect.y() - current.y(), rect.y() / double( y ), progress )),
qRound( interpolate( rect.width(), displayWidth() / double( x ), progress )),
qRound( interpolate( rect.height(), displayHeight() / double( y ), progress )));
return rect;
}
void SlideEffect::desktopChanged( int old )
{
if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this )
return;
if( slide ) // old slide still in progress
{
QPoint diffPos = desktopRect( old, false ).topLeft() - slide_start_pos;
int w = 0;
int h = 0;
if( effects->optionRollOverDesktops())
{
int x, y;
Qt::Orientation orientation;
effects->calcDesktopLayout( &x, &y, &orientation );
w = x * displayWidth();
h = y * displayHeight();
// wrap around if shorter
if( diffPos.x() > 0 && diffPos.x() > w / 2 )
diffPos.setX( diffPos.x() - w );
if( diffPos.x() < 0 && abs( diffPos.x()) > w / 2 )
diffPos.setX( diffPos.x() + w );
if( diffPos.y() > 0 && diffPos.y() > h / 2 )
diffPos.setY( diffPos.y() - h );
if( diffPos.y() < 0 && abs( diffPos.y()) > h / 2 )
diffPos.setY( diffPos.y() + h );
}
QPoint currentPos = slide_start_pos + mTimeLine.value() * diffPos;
QRegion currentRegion = QRect( currentPos, QSize( displayWidth(), displayHeight()));
if( effects->optionRollOverDesktops())
{
currentRegion |= ( currentRegion & QRect( -w, 0, w, h )).translated( w, 0 );
currentRegion |= ( currentRegion & QRect( 0, -h, w, h )).translated( 0, h );
currentRegion |= ( currentRegion & QRect( w, 0, w, h )).translated( -w, 0 );
currentRegion |= ( currentRegion & QRect( 0, h, w, h )).translated( 0, -h );
}
QRect rect = desktopRect( effects->currentDesktop(), false );
if( currentRegion.contains( rect ))
{ // current position is in new current desktop (e.g. quickly changing back),
// don't do full progress
if( abs( currentPos.x() - rect.x()) > abs( currentPos.y() - rect.y()))
mTimeLine.setProgress(1 - abs( currentPos.x() - rect.x()) / double( displayWidth()));
else
mTimeLine.setProgress(1 - abs( currentPos.y() - rect.y()) / double( displayHeight()));
}
else // current position is not on current desktop, do full progress
mTimeLine.setProgress(0);
diffPos = rect.topLeft() - currentPos;
if( mTimeLine.value() <= 0 )
{
// Compute starting point for this new move (given current and end positions)
slide_start_pos = rect.topLeft() - diffPos * 1 / ( 1 - mTimeLine.value() );
}
else
{ // at the end, stop
slide = false;
mTimeLine.setProgress(0);
}
}
else
{
mTimeLine.setProgress(0);
slide_start_pos = desktopRect( old, false ).topLeft();
slide = true;
}
effects->addRepaintFull();
}
} // namespace
#include "slide.moc"

17
effects/slide.desktop Normal file
View file

@ -0,0 +1,17 @@
[Desktop Entry]
Name=Slide
Icon=preferences-system-windows-effect-slide
Comment=Slide windows when switching desktops
Type=Service
X-KDE-ServiceTypes=KWin/Effect
X-KDE-PluginInfo-Author=Luboš Luňák
X-KDE-PluginInfo-Email=l.lunak@kde.org
X-KDE-PluginInfo-Name=kwin4_effect_slide
X-KDE-PluginInfo-Version=0.1.0
X-KDE-PluginInfo-Category=Appearance
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
X-KDE-Library=kwin4_effect_builtins
X-KDE-Ordering=50

56
effects/slide.h Normal file
View file

@ -0,0 +1,56 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
Copyright (C) 2008 Lucas Murray <admin@undefinedfire.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************/
#ifndef KWIN_SLIDE_H
#define KWIN_SLIDE_H
#include <kwineffects.h>
#include <QObject>
namespace KWin
{
class SlideEffect
: public QObject, public Effect
{
Q_OBJECT
public:
SlideEffect();
virtual void prePaintScreen( ScreenPrePaintData& data, int time );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void postPaintScreen();
virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time );
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
virtual void desktopChanged( int old );
private:
QRect desktopRect( int desktop, bool scaled ) const;
TimeLine mTimeLine;
int painting_desktop;
bool slide;
QPoint slide_start_pos;
bool slide_painting_sticky;
QPoint slide_painting_diff;
};
} // namespace
#endif