Desktop Grid uses Present Windows to lay out the windows on a desktop

FEATURE: 165745

svn path=/trunk/KDE/kdebase/workspace/; revision=1049548
This commit is contained in:
Martin Gräßlin 2009-11-15 12:38:26 +00:00
parent 72c3a553ca
commit 3859fff0de
8 changed files with 349 additions and 121 deletions

View file

@ -57,6 +57,7 @@ DesktopGridEffect::DesktopGridEffect()
, unscaledBorder()
, scaledSize()
, scaledOffset()
, m_proxy( 0 )
{
// Load shortcuts
KActionCollection* actionCollection = new KActionCollection( this );
@ -105,6 +106,7 @@ void DesktopGridEffect::reconfigure( ReconfigureFlags )
desktopNameAlignment = Qt::Alignment( conf.readEntry( "DesktopNameAlignment", 0 ));
layoutMode = conf.readEntry( "LayoutMode", int( LayoutPager ));
customLayoutRows = conf.readEntry( "CustomLayoutRows", 2 );
m_usePresentWindows = conf.readEntry( "PresentWindows", true );
}
//-----------------------------------------------------------------------------
@ -112,7 +114,7 @@ void DesktopGridEffect::reconfigure( ReconfigureFlags )
void DesktopGridEffect::prePaintScreen( ScreenPrePaintData& data, int time )
{
if( timeline.value() != 0 || activated )
if( timeline.value() != 0 || activated || (isUsingPresentWindows() && isMotionManagerMovingWindows()) )
{
if( activated )
timeline.addTime(time);
@ -125,11 +127,17 @@ void DesktopGridEffect::prePaintScreen( ScreenPrePaintData& data, int time )
else
hoverTimeline[i].removeTime(time);
}
if( isUsingPresentWindows() )
{
QList<WindowMotionManager>::iterator i;
for( i = m_managers.begin(); i != m_managers.end(); ++i )
(*i).calculate( 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( timeline.value() != 0 )
if( timeline.value() != 0 || (isUsingPresentWindows() && isMotionManagerMovingWindows()) )
data.mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
if( !activated && timeline.value() == 0 )
if( !activated && timeline.value() == 0 && !(isUsingPresentWindows() && isMotionManagerMovingWindows()) )
finish();
}
effects->prePaintScreen( data, time );
@ -137,7 +145,7 @@ void DesktopGridEffect::prePaintScreen( ScreenPrePaintData& data, int time )
void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
{
if( timeline.value() == 0 )
if( timeline.value() == 0 && !isUsingPresentWindows() )
{
effects->paintScreen( mask, region, data );
return;
@ -184,7 +192,8 @@ void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
void DesktopGridEffect::postPaintScreen()
{
if( activated ? timeline.value() != 1 : timeline.value() != 0 )
if( activated ? timeline.value() != 1 :
(timeline.value() != 0 || (isUsingPresentWindows() && isMotionManagerMovingWindows())) )
effects->addRepaintFull(); // Repaint during zoom
if( activated )
{
@ -205,7 +214,7 @@ void DesktopGridEffect::postPaintScreen()
void DesktopGridEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
if( timeline.value() != 0 )
if( timeline.value() != 0 || (isUsingPresentWindows() && isMotionManagerMovingWindows()) )
{
if( w->isOnDesktop( paintingDesktop ))
{
@ -234,7 +243,7 @@ void DesktopGridEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& dat
void DesktopGridEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
if( timeline.value() != 0 )
if( timeline.value() != 0 || (isUsingPresentWindows() && isMotionManagerMovingWindows()) )
{
double xScale = data.xScale;
double yScale = data.yScale;
@ -242,7 +251,7 @@ void DesktopGridEffect::paintWindow( EffectWindow* w, int mask, QRegion region,
// Don't change brightness of windows on all desktops as this causes flickering
if( !w->isOnAllDesktops() || w->isDesktop() )
data.brightness *= 1.0 - ( 0.3 * ( 1.0 - hoverTimeline[paintingDesktop - 1].value() ));
for( int screen = 0; screen < effects->numScreens(); screen++ )
{
// Assume desktop windows can never be on two screens at once (Plasma makes one window per screen)
@ -250,26 +259,44 @@ void DesktopGridEffect::paintWindow( EffectWindow* w, int mask, QRegion region,
screen = w->screen();
QRect screenGeom = effects->clientArea( ScreenArea, screen, 0 );
QRectF transformedGeo = w->geometry();
// Display all quads on the same screen on the same pass
WindowQuadList screenQuads;
foreach( const WindowQuad &quad, data.quads )
bool quadsAdded = false;
if( isUsingPresentWindows() )
{
QRect quadRect(
w->x() + quad.left(), w->y() + quad.top(),
quad.right() - quad.left(), quad.bottom() - quad.top()
);
if( quadRect.intersects( screenGeom ))
screenQuads.append( quad );
WindowMotionManager& manager = m_managers[ (paintingDesktop-1)*(effects->numScreens())+screen ];
if( manager.isManaging( w ) )
{
foreach( const WindowQuad &quad, data.quads )
screenQuads.append( quad );
transformedGeo = manager.transformedGeometry( w );
quadsAdded = true;
}
else if( w->screen() != screen )
quadsAdded = true; // we don't want parts of overlapping windows on the other screen
}
if( !quadsAdded )
{
foreach( const WindowQuad &quad, data.quads )
{
QRect quadRect(
w->x() + quad.left(), w->y() + quad.top(),
quad.right() - quad.left(), quad.bottom() - quad.top()
);
if( quadRect.intersects( screenGeom ) )
screenQuads.append( quad );
}
}
if( screenQuads.isEmpty() )
continue; // Nothing is being displayed, don't bother
WindowPaintData d = data;
d.quads = screenQuads;
QPointF newPos = scalePos( QPoint( w->x(), w->y() ), paintingDesktop, screen);
QPointF newPos = scalePos( transformedGeo.topLeft().toPoint(), paintingDesktop, screen);
double progress = timeline.value();
d.xScale = interpolate( 1, xScale * scale[screen], progress);
d.yScale = interpolate( 1, yScale * scale[screen], progress);
d.xScale = interpolate( 1, xScale * scale[screen] * (float)transformedGeo.width()/(float)w->geometry().width(), progress);
d.yScale = interpolate( 1, yScale * scale[screen] * (float)transformedGeo.height()/(float)w->geometry().height(), progress);
d.xTranslate += qRound( newPos.x() - w->x() );
d.yTranslate += qRound( newPos.y() - w->y() );
@ -304,13 +331,47 @@ void DesktopGridEffect::paintWindow( EffectWindow* w, int mask, QRegion region,
//-----------------------------------------------------------------------------
// User interaction
void DesktopGridEffect::windowAdded( EffectWindow* w )
{
if( !activated )
return;
if( isUsingPresentWindows() )
{
WindowMotionManager& manager = m_managers[ (w->desktop()-1)*effects->numScreens()+w->screen() ];
manager.manage( w );
m_proxy->calculateWindowTransformations( manager.managedWindows(), w->screen(), manager );
}
effects->addRepaintFull();
}
void DesktopGridEffect::windowClosed( EffectWindow* w )
{
if ( !activated )
return;
if( w == windowMove )
{
effects->setElevatedWindow( windowMove, false );
windowMove = NULL;
}
if( isUsingPresentWindows() )
{
if( w->isOnAllDesktops() )
{
for( int i=0; i<effects->numberOfDesktops(); i++ )
{
WindowMotionManager& manager = m_managers[i*effects->numScreens()+w->screen()];
manager.unmanage(w);
m_proxy->calculateWindowTransformations(manager.managedWindows(), w->screen(), manager);
}
}
else
{
WindowMotionManager& manager = m_managers[(w->desktop()-1)*effects->numScreens()+w->screen()];
manager.unmanage(w);
m_proxy->calculateWindowTransformations(manager.managedWindows(), w->screen(), manager);
}
}
effects->addRepaintFull();
}
void DesktopGridEffect::windowInputMouseEvent( Window, QEvent* e )
@ -330,13 +391,28 @@ void DesktopGridEffect::windowInputMouseEvent( Window, QEvent* e )
if( !wasWindowMove ) // Activate on move
effects->activateWindow( windowMove );
wasWindowMove = true;
if( windowMove->isMovable() )
if( windowMove->isMovable() && !isUsingPresentWindows() )
{
int screen = effects->screenNumber( me->pos() );
effects->moveWindow( windowMove, unscalePos( me->pos(), NULL ) + windowMoveDiff, true, 1.0 / scale[screen] );
}
if( d != highlightedDesktop && !windowMove->isOnAllDesktops() )
{
const int oldDesktop = windowMove->desktop();
effects->windowToDesktop( windowMove, d ); // Not true all desktop move
if( isUsingPresentWindows() )
{
// TODO: move window to other screen
WindowMotionManager& oldManager =
m_managers[ (oldDesktop-1)*(effects->numScreens())+windowMove->screen() ];
WindowMotionManager& newManager =
m_managers[ (d-1)*(effects->numScreens())+windowMove->screen() ];
oldManager.unmanage( windowMove );
newManager.manage( windowMove );
m_proxy->calculateWindowTransformations( oldManager.managedWindows(), windowMove->screen(), oldManager );
m_proxy->calculateWindowTransformations( newManager.managedWindows(), windowMove->screen(), newManager );
}
}
}
if( d != highlightedDesktop ) // Highlight desktop
{
@ -350,12 +426,37 @@ void DesktopGridEffect::windowInputMouseEvent( Window, QEvent* e )
if( w->isOnAllDesktops() )
continue;
if( w->isOnDesktop( highlightedDesktop ) )
{
effects->windowToDesktop( w, d );
if( isUsingPresentWindows() )
{
m_managers[ (d-1)*(effects->numScreens()) + w->screen() ].manage( w );
m_managers[ (highlightedDesktop-1)*(effects->numScreens()) + w->screen() ].unmanage( w );
}
}
else if( w->isOnDesktop( d ) )
stack << w;
}
foreach( EffectWindow* w, stack )
{
effects->windowToDesktop( w, highlightedDesktop );
if( isUsingPresentWindows() )
{
m_managers[ (d-1)*(effects->numScreens()) + w->screen() ].unmanage( w );
m_managers[ (highlightedDesktop-1)*(effects->numScreens()) + w->screen() ].manage( w );
}
}
if( isUsingPresentWindows() )
{
for( int i=0; i<effects->numScreens(); i++ )
{
WindowMotionManager& manager = m_managers[ (d-1)*(effects->numScreens()) + i ];
WindowMotionManager& manager2 = m_managers[ (highlightedDesktop-1)*(effects->numScreens()) + i ];
m_proxy->calculateWindowTransformations( manager.managedWindows(), i, manager );
m_proxy->calculateWindowTransformations( manager2.managedWindows(), i, manager2 );
}
effects->addRepaintFull();
}
}
setHighlightedDesktop( d );
}
@ -386,9 +487,39 @@ void DesktopGridEffect::windowInputMouseEvent( Window, QEvent* e )
if( w != NULL )
{
if( w->isOnAllDesktops())
effects->windowToDesktop( w, posToDesktop( me->pos()));
{
const int desktop = posToDesktop( me->pos() );
effects->windowToDesktop( w, desktop );
if( isUsingPresentWindows() )
{
for( int i=0; i<effects->numberOfDesktops(); i++ )
{
if( i != desktop - 1 )
{
WindowMotionManager& manager = m_managers[ i*effects->numScreens() + w->screen() ];
manager.unmanage( w );
m_proxy->calculateWindowTransformations( manager.managedWindows(), w->screen(), manager );
}
}
}
}
else
{
if( isUsingPresentWindows() )
{
const int desktop = w->desktop();
for( int i=0; i<effects->numberOfDesktops(); i++ )
{
if( i != desktop - 1 )
{
WindowMotionManager& manager = m_managers[ i*effects->numScreens() + w->screen() ];
manager.manage( w );
m_proxy->calculateWindowTransformations( manager.managedWindows(), w->screen(), manager );
}
}
}
effects->windowToDesktop( w, NET::OnAllDesktops );
}
effects->addRepaintFull();
}
}
@ -617,9 +748,27 @@ EffectWindow* DesktopGridEffect::windowAt( QPoint pos ) const
int desktop;
pos = unscalePos( pos, &desktop );
foreach( EffectWindow* w, windows )
if( w->isOnDesktop( desktop ) && !w->isMinimized() && w->geometry().contains( pos ))
if( isUsingPresentWindows() )
{
const int screen = effects->screenNumber( pos );
EffectWindow *w =
m_managers.at((desktop-1)*(effects->numScreens())+screen).windowAtPoint( pos, false );
if( w )
return w;
foreach( EffectWindow* w, windows )
{
if( w->isOnDesktop( desktop ) && w->isDesktop() && w->geometry().contains( pos ))
return w;
}
}
else
{
foreach( EffectWindow* w, windows )
{
if( w->isOnDesktop( desktop ) && !w->isMinimized() && w->geometry().contains( pos ))
return w;
}
}
return NULL;
}
@ -780,20 +929,24 @@ void DesktopGridEffect::setActive( bool active )
if( activated == active )
return; // Already in that state
// Example proxy code, TODO: Use or remove
//PresentWindowsEffectProxy* proxy =
// static_cast<PresentWindowsEffectProxy*>( effects->getProxy( "presentwindows" ));
//if( proxy )
// kDebug() << "Retrieved PresentWindowsEffectProxy, is present windows activate?"
// << proxy->isActive();
//else
// kDebug() << "Failed to retrieve PresentWindowsEffectProxy. Maybe present windows isn't enabled?";
activated = active;
if( activated && timeline.value() == 0 )
setup();
if( !activated )
{
if( isUsingPresentWindows() )
{
QList<WindowMotionManager>::iterator it;
for( it = m_managers.begin(); it != m_managers.end(); it++ )
{
foreach( EffectWindow* w, (*it).managedWindows() )
{
(*it).moveWindow( w, w->geometry() );
}
}
}
setHighlightedDesktop( effects->currentDesktop() ); // Ensure selected desktop is highlighted
}
effects->addRepaintFull();
}
@ -883,6 +1036,29 @@ 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() )
{
manager.manage( w );
}
}
m_proxy->calculateWindowTransformations(manager.managedWindows(), j, manager);
m_managers.append(manager);
}
}
}
}
void DesktopGridEffect::finish()
@ -899,6 +1075,15 @@ void DesktopGridEffect::finish()
keyboardGrab = false;
effects->destroyInputWindow( input );
effects->setActiveFullScreenEffect( 0 );
if( isUsingPresentWindows() )
{
while( !m_managers.isEmpty() )
{
m_managers.first().unmanageAll();
m_managers.removeFirst();
}
m_proxy = 0;
}
}
void DesktopGridEffect::globalShortcutChanged( const QKeySequence& seq )
@ -906,6 +1091,25 @@ void DesktopGridEffect::globalShortcutChanged( const QKeySequence& seq )
shortcut = KShortcut( seq );
}
bool DesktopGridEffect::isMotionManagerMovingWindows()
{
if( isUsingPresentWindows() )
{
QList<WindowMotionManager>::iterator it;
for( it = m_managers.begin(); it != m_managers.end(); it++ )
{
if( (*it).areWindowsMoving() )
return true;
}
}
return false;
}
bool DesktopGridEffect::isUsingPresentWindows() const
{
return (m_proxy != NULL);
}
} // namespace
#include "desktopgrid.moc"

View file

@ -29,6 +29,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
namespace KWin
{
class PresentWindowsEffectProxy;
class DesktopGridEffect
: public QObject, public Effect
{
@ -43,6 +45,7 @@ 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 windowAdded( EffectWindow* w );
virtual void windowInputMouseEvent( Window w, QEvent* e );
virtual void grabbedKeyboardEvent( QKeyEvent* e );
virtual bool borderActivated( ElectricBorder border );
@ -69,6 +72,8 @@ class DesktopGridEffect
void setActive( bool active );
void setup();
void finish();
bool isMotionManagerMovingWindows();
bool isUsingPresentWindows() const;
QList<ElectricBorder> borderActivate;
int zoomDuration;
@ -105,6 +110,10 @@ class DesktopGridEffect
// Shortcut - needed to toggle the effect
KShortcut shortcut;
PresentWindowsEffectProxy* m_proxy;
QList<WindowMotionManager> m_managers;
bool m_usePresentWindows;
};
} // namespace

View file

@ -88,6 +88,7 @@ DesktopGridEffectConfig::DesktopGridEffectConfig(QWidget* parent, const QVariant
connect( m_ui->layoutCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( layoutSelectionChanged() ));
connect( m_ui->layoutRowsSpin, SIGNAL( valueChanged( int )), this, SLOT( changed() ));
connect( m_ui->shortcutEditor, SIGNAL( keyChange() ), this, SLOT( changed() ));
connect( m_ui->presentWindowsCheckBox, SIGNAL( stateChanged( int )), this, SLOT( changed() ));
load();
}
@ -119,6 +120,8 @@ void DesktopGridEffectConfig::load()
m_ui->layoutRowsSpin->setValue( conf.readEntry( "CustomLayoutRows", 2 ));
m_ui->layoutRowsSpin->setSuffix( ki18np( " row", " rows"));
m_ui->presentWindowsCheckBox->setChecked( conf.readEntry( "PresentWindows", true ));
emit changed(false);
}
@ -140,6 +143,8 @@ void DesktopGridEffectConfig::save()
conf.writeEntry( "CustomLayoutRows", m_ui->layoutRowsSpin->value() );
conf.writeEntry( "PresentWindows", m_ui->presentWindowsCheckBox->isChecked() );
m_ui->shortcutEditor->save();
conf.sync();
@ -156,6 +161,7 @@ void DesktopGridEffectConfig::defaults()
m_ui->layoutCombo->setCurrentIndex( int( DesktopGridEffect::LayoutPager ));
m_ui->layoutRowsSpin->setValue( 2 );
m_ui->shortcutEditor->allDefault();
m_ui->presentWindowsCheckBox->setChecked( true );
emit changed(true);
}

View file

@ -1,181 +1,182 @@
<ui version="4.0" >
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>KWin::DesktopGridEffectConfigForm</class>
<widget class="QWidget" name="KWin::DesktopGridEffectConfigForm" >
<property name="geometry" >
<widget class="QWidget" name="KWin::DesktopGridEffectConfigForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>574</width>
<height>216</height>
<height>250</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2" >
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Appearance</string>
</property>
<layout class="QGridLayout" name="gridLayout" >
<item row="0" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Zoom &amp;duration:</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>zoomDurationSpin</cstring>
</property>
</widget>
</item>
<item row="0" column="1" >
<widget class="KIntSpinBox" name="zoomDurationSpin" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<item row="0" column="1">
<widget class="KIntSpinBox" name="zoomDurationSpin">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="specialValueText" >
<property name="specialValueText">
<string comment="Duration of zoom">Default</string>
</property>
<property name="maximum" >
<property name="maximum">
<number>5000</number>
</property>
<property name="singleStep" >
<property name="singleStep">
<number>10</number>
</property>
</widget>
</item>
<item row="1" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>&amp;Border width:</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>borderWidthSpin</cstring>
</property>
</widget>
</item>
<item row="1" column="1" >
<widget class="KIntSpinBox" name="borderWidthSpin" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<item row="1" column="1">
<widget class="KIntSpinBox" name="borderWidthSpin">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximum" >
<property name="maximum">
<number>100</number>
</property>
<property name="value" >
<property name="value">
<number>10</number>
</property>
</widget>
</item>
<item row="2" column="0" >
<widget class="QLabel" name="label_6" >
<property name="text" >
<item row="2" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Desktop &amp;name alignment:</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>desktopNameAlignmentCombo</cstring>
</property>
</widget>
</item>
<item row="2" column="1" >
<widget class="QComboBox" name="desktopNameAlignmentCombo" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<item row="2" column="1">
<widget class="QComboBox" name="desktopNameAlignmentCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="3" column="0" >
<widget class="QLabel" name="label_7" >
<property name="text" >
<item row="3" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>&amp;Layout mode:</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>layoutCombo</cstring>
</property>
</widget>
</item>
<item row="3" column="1" >
<widget class="QComboBox" name="layoutCombo" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<item row="3" column="1">
<widget class="QComboBox" name="layoutCombo">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text" >
<property name="text">
<string>Pager</string>
</property>
</item>
<item>
<property name="text" >
<property name="text">
<string>Automatic</string>
</property>
</item>
<item>
<property name="text" >
<property name="text">
<string>Custom</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0" >
<widget class="QLabel" name="layoutRowsLabel" >
<property name="text" >
<item row="4" column="0">
<widget class="QLabel" name="layoutRowsLabel">
<property name="text">
<string>Number of &amp;rows:</string>
</property>
<property name="alignment" >
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy" >
<property name="buddy">
<cstring>layoutRowsSpin</cstring>
</property>
</widget>
</item>
<item row="4" column="1" >
<widget class="KIntSpinBox" name="layoutRowsSpin" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Fixed" hsizetype="Expanding" >
<item row="4" column="1">
<widget class="KIntSpinBox" name="layoutRowsSpin">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimum" >
<property name="minimum">
<number>1</number>
</property>
<property name="maximum" >
<property name="maximum">
<number>20</number>
</property>
<property name="value" >
<property name="value">
<number>2</number>
</property>
</widget>
</item>
<item row="5" column="0" colspan="2" >
<spacer name="verticalSpacer" >
<property name="orientation" >
<item row="7" column="0" colspan="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0" >
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
@ -183,19 +184,26 @@
</property>
</spacer>
</item>
<item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="presentWindowsCheckBox">
<property name="text">
<string>Use Present Windows effect to layout the windows</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2" >
<property name="title" >
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Activation</string>
</property>
<layout class="QGridLayout" name="gridLayout_2" >
<item row="0" column="0" colspan="2" >
<widget class="KWin::GlobalShortcutsEditor" native="1" name="shortcutEditor" >
<property name="sizePolicy" >
<sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0" colspan="2">
<widget class="KWin::GlobalShortcutsEditor" name="shortcutEditor" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@ -216,7 +224,7 @@
<customwidget>
<class>KWin::GlobalShortcutsEditor</class>
<extends>QWidget</extends>
<header location="global" >kwineffects.h</header>
<header location="global">kwineffects.h</header>
<container>1</container>
</customwidget>
</customwidgets>

View file

@ -893,7 +893,7 @@ void PresentWindowsEffect::rearrangeWindows()
else if( m_layoutMode == LayoutFlexibleGrid )
calculateWindowTransformationsKompose( windows, screen );
else
calculateWindowTransformationsNatural( windows, screen );
calculateWindowTransformationsNatural( windows, screen, m_motionManager );
}
// Resize text frames if required
@ -1139,21 +1139,21 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose( EffectWindowLi
}
}
void PresentWindowsEffect::calculateWindowTransformationsNatural( EffectWindowList windowlist, int screen )
void PresentWindowsEffect::calculateWindowTransformationsNatural( EffectWindowList windowlist, int screen, WindowMotionManager& motionManager )
{
// If windows do not overlap they scale into nothingness, fix by resetting. To reproduce
// just have a single window on a Xinerama screen or have two windows that do not touch.
// TODO: Work out why this happens, is most likely a bug in the manager.
foreach( EffectWindow *w, windowlist )
if( m_motionManager.transformedGeometry( w ) == w->geometry() )
m_motionManager.reset( w );
if( motionManager.transformedGeometry( w ) == w->geometry() )
motionManager.reset( w );
if( windowlist.count() == 1 )
{
// Just move the window to its original location to save time
if( effects->clientArea( FullScreenArea, windowlist[0] ).contains( windowlist[0]->geometry() ) )
{
m_motionManager.moveWindow( windowlist[0], windowlist[0]->geometry() );
motionManager.moveWindow( windowlist[0], windowlist[0]->geometry() );
return;
}
}
@ -1168,13 +1168,14 @@ void PresentWindowsEffect::calculateWindowTransformationsNatural( EffectWindowLi
QRect bounds = area;
int direction = 0;
QHash<EffectWindow*, QRect> targets;
QHash<EffectWindow*, int> directions;
foreach( EffectWindow *w, windowlist )
{
bounds = bounds.united( w->geometry() );
targets[w] = w->geometry();
// Reuse the unused "slot" as a preferred direction attribute. This is used when the window
// is on the edge of the screen to try to use as much screen real estate as possible.
m_windowData[w].slot = direction;
directions[w] = direction;
direction++;
if( direction == 4 )
direction = 0;
@ -1227,9 +1228,9 @@ void PresentWindowsEffect::calculateWindowTransformationsNatural( EffectWindowLi
if( xSection != 1 || ySection != 1 ) // Remove this if you want the center to pull as well
{
if( xSection == 1 )
xSection = ( m_windowData[w].slot / 2 ? 2 : 0 );
xSection = ( directions[w] / 2 ? 2 : 0 );
if( ySection == 1 )
ySection = ( m_windowData[w].slot % 2 ? 2 : 0 );
ySection = ( directions[w] % 2 ? 2 : 0 );
}
if( xSection == 0 && ySection == 0 )
diff = QPoint( bounds.topLeft() - targets[w].center() );
@ -1373,7 +1374,7 @@ void PresentWindowsEffect::calculateWindowTransformationsNatural( EffectWindowLi
// Notify the motion manager of the targets
foreach( EffectWindow *w, windowlist )
m_motionManager.moveWindow( w, targets[w] );
motionManager.moveWindow( w, targets[w] );
}
//-----------------------------------------------------------------------------

View file

@ -136,7 +136,7 @@ class PresentWindowsEffect
void rearrangeWindows();
void calculateWindowTransformationsClosest( EffectWindowList windowlist, int screen );
void calculateWindowTransformationsKompose( EffectWindowList windowlist, int screen );
void calculateWindowTransformationsNatural( EffectWindowList windowlist, int screen );
void calculateWindowTransformationsNatural( EffectWindowList windowlist, int screen, WindowMotionManager& motionManager );
// Helper functions for window rearranging
inline double aspectRatio( EffectWindow *w )

View file

@ -33,9 +33,9 @@ PresentWindowsEffectProxy::~PresentWindowsEffectProxy()
{
}
bool PresentWindowsEffectProxy::isActive() const
void PresentWindowsEffectProxy::calculateWindowTransformations(EffectWindowList windows, int screen, WindowMotionManager& manager)
{
return m_effect->m_activated;
return m_effect->calculateWindowTransformationsNatural( windows, screen, manager );
}
} // namespace

View file

@ -20,20 +20,20 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef KWIN_PRESENTWINDOWS_PROXY_H
#define KWIN_PRESENTWINDOWS_PROXY_H
#include <kwineffects.h>
namespace KWin
{
class PresentWindowsEffect;
// Example proxy code, TODO: Use or remove
class PresentWindowsEffectProxy
{
public:
PresentWindowsEffectProxy( PresentWindowsEffect* effect );
~PresentWindowsEffectProxy();
bool isActive() const;
void calculateWindowTransformations(EffectWindowList windows, int screen, WindowMotionManager& manager);
private:
PresentWindowsEffect* m_effect;