FEATURE: Two new layout modes for the present windows effect
BUG: Keyboard operation now works correctly in present windows on multi-monitor setups svn path=/trunk/KDE/kdebase/workspace/; revision=852066
This commit is contained in:
parent
a59111148c
commit
255889ca65
7 changed files with 838 additions and 184 deletions
|
@ -90,6 +90,7 @@ SET(kwin4_effect_builtins_config_sources
|
|||
maketransparent_config.cpp
|
||||
maketransparent_config.ui
|
||||
presentwindows_config.cpp
|
||||
presentwindows_config.ui
|
||||
shadow_config.cpp
|
||||
showfps_config.cpp
|
||||
showfps_config.ui
|
||||
|
|
|
@ -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
|
||||
|
@ -55,26 +56,30 @@ PresentWindowsEffect::PresentWindowsEffect()
|
|||
|
||||
KActionCollection* actionCollection = new KActionCollection( this );
|
||||
KAction* a = (KAction*)actionCollection->addAction( "Expose" );
|
||||
a->setText( i18n("Toggle Expose Effect" ));
|
||||
a->setText( i18n("Toggle Present Windows (Current desktop)" ));
|
||||
a->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F9));
|
||||
connect(a, SIGNAL(triggered(bool)), this, SLOT(toggleActive()));
|
||||
KAction* b = (KAction*)actionCollection->addAction( "ExposeAll" );
|
||||
b->setText( i18n("Toggle Expose Effect (incl. other desktops)" ));
|
||||
b->setText( i18n("Toggle Present Windows (All desktops)" ));
|
||||
b->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F10));
|
||||
connect(b, SIGNAL(triggered(bool)), this, SLOT(toggleActiveAllDesktops()));
|
||||
|
||||
borderActivate = (ElectricBorder)conf.readEntry("BorderActivate", (int)ElectricNone);
|
||||
borderActivateAll = (ElectricBorder)conf.readEntry("BorderActivateAll", (int)ElectricTopLeft);
|
||||
layoutMode = conf.readEntry( "LayoutMode", int( LayoutNatural ));
|
||||
drawWindowCaptions = conf.readEntry("DrawWindowCaptions", true);
|
||||
drawWindowIcons = conf.readEntry("DrawWindowIcons", true);
|
||||
tabBox = conf.readEntry("TabBox", false);
|
||||
accuracy = conf.readEntry("Accuracy", 1) * 20;
|
||||
fillGaps = conf.readEntry("FillGaps", true);
|
||||
|
||||
effects->reserveElectricBorder( borderActivate );
|
||||
effects->reserveElectricBorder( borderActivateAll );
|
||||
|
||||
mActiveness.setCurveShape( TimeLine::EaseInOutCurve );
|
||||
mActiveness.setDuration( 250 );
|
||||
mActiveness.setDuration( conf.readEntry( "RearrangeDuration", 250 ));
|
||||
mRearranging.setCurveShape( TimeLine::EaseInOutCurve );
|
||||
mRearranging.setDuration( 250 );
|
||||
mRearranging.setDuration( conf.readEntry( "RearrangeDuration", 250 ));
|
||||
mRearranging.setProgress( 1.0 );
|
||||
}
|
||||
|
||||
|
@ -205,7 +210,8 @@ void PresentWindowsEffect::paintWindow( EffectWindow* w, int mask, QRegion regio
|
|||
if(mActiveness.value() > 0.0 && mWindowData.contains(w))
|
||||
{
|
||||
const WindowData& windata = mWindowData[w];
|
||||
paintWindowIcon( w, data );
|
||||
if (drawWindowIcons)
|
||||
paintWindowIcon( w, data );
|
||||
|
||||
if (drawWindowCaptions)
|
||||
{
|
||||
|
@ -453,25 +459,39 @@ void PresentWindowsEffect::rearrangeWindows()
|
|||
newScreenGridSizes.append( GridSize() );
|
||||
|
||||
// Do not rearrange if filtering only removed windows, so that the remaining ones don't possibly
|
||||
// jump into the freed slots if they'd be a better match.
|
||||
// jump into the freed slots if they'd be a better match. This only works with the regular grid
|
||||
// This can probably still lead to such things when removing the filter again, but that'd need
|
||||
// more complex remembering of window positions.
|
||||
newNumOfWindows[i] = windowlists[i].count();
|
||||
newScreenGridSizes[i].columns = int( ceil( sqrt( (double)windowlists[i].count())));
|
||||
newScreenGridSizes[i].rows = int( ceil( windowlists[i].count() / double( newScreenGridSizes[i].columns )));
|
||||
if( newNumOfWindows[i] && ( firstTime || newNumOfWindows[i] > numOfWindows[i] ||
|
||||
( newNumOfWindows[i] < numOfWindows[i] && ( newScreenGridSizes[i].rows != screenGridSizes[i].rows ||
|
||||
newScreenGridSizes[i].columns != screenGridSizes[i].columns ))))
|
||||
bool doRearrange = false;
|
||||
if( layoutMode != LayoutRegularGrid )
|
||||
doRearrange = true;
|
||||
else
|
||||
{
|
||||
newNumOfWindows[i] = windowlists[i].count();
|
||||
newScreenGridSizes[i].columns = int( ceil( sqrt( (double)windowlists[i].count())));
|
||||
newScreenGridSizes[i].rows = int( ceil( windowlists[i].count() / double( newScreenGridSizes[i].columns )));
|
||||
if( newNumOfWindows[i] && ( firstTime || newNumOfWindows[i] > numOfWindows[i] ||
|
||||
( newNumOfWindows[i] < numOfWindows[i] && ( newScreenGridSizes[i].rows != screenGridSizes[i].rows ||
|
||||
newScreenGridSizes[i].columns != screenGridSizes[i].columns ))))
|
||||
doRearrange = true;
|
||||
}
|
||||
if( doRearrange )
|
||||
{
|
||||
if( !firstTime && !rearranging )
|
||||
{
|
||||
rearranging = true;
|
||||
prepareToRearrange();
|
||||
}
|
||||
// No point calculating if there is no windows
|
||||
if( !windowlists[i].size() )
|
||||
continue;
|
||||
// Calculate new positions and scales for windows
|
||||
// calculateWindowTransformationsDumb( windowlist ); // Haven't added screen support to these yet
|
||||
// calculateWindowTransformationsKompose( windowlist );
|
||||
calculateWindowTransformationsClosest( windowlists[i], i );
|
||||
if( layoutMode == LayoutRegularGrid )
|
||||
calculateWindowTransformationsClosest( windowlists[i], i );
|
||||
else if( layoutMode == LayoutFlexibleGrid )
|
||||
calculateWindowTransformationsKompose( windowlists[i], i );
|
||||
else
|
||||
calculateWindowTransformationsNatural( windowlists[i], i );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -499,43 +519,6 @@ void PresentWindowsEffect::prepareToRearrange()
|
|||
mRearranging.setProgress(0.0); // start animation again
|
||||
}
|
||||
|
||||
void PresentWindowsEffect::calculateWindowTransformationsDumb(EffectWindowList windowlist)
|
||||
{
|
||||
// Calculate number of rows/cols
|
||||
int rows = windowlist.count() / 4 + 1;
|
||||
int cols = windowlist.count() / rows + windowlist.count() % rows;
|
||||
// Get rect which we can use on current desktop. This excludes e.g. panels
|
||||
QRect placementRect = effects->clientArea( PlacementArea, effects->activeScreen(), effects->currentDesktop());
|
||||
// Size of one cell
|
||||
int cellwidth = placementRect.width() / cols;
|
||||
int cellheight = placementRect.height() / rows;
|
||||
kDebug(1212) << "Got " << windowlist.count() << " clients, using " << rows << "x" << cols << " grid";
|
||||
|
||||
// Calculate position and scale factor for each window
|
||||
int i = 0;
|
||||
foreach( EffectWindow* window, windowlist )
|
||||
{
|
||||
|
||||
// Row/Col of this window
|
||||
int r = i / cols;
|
||||
int c = i % cols;
|
||||
mWindowData[window].slot = i;
|
||||
mWindowData[window].x = c;
|
||||
mWindowData[window].y = r;
|
||||
mWindowData[window].highlight = 0.0f;
|
||||
mWindowData[window].scale = qMin(cellwidth / (double)window->width(), cellheight / (double)window->height());
|
||||
mWindowData[window].area.setLeft(placementRect.left() + cellwidth * c);
|
||||
mWindowData[window].area.setTop(placementRect.top() + cellheight * r);
|
||||
mWindowData[window].area.setWidth((int)(window->width() * mWindowData[window].scale));
|
||||
mWindowData[window].area.setHeight((int)(window->height() * mWindowData[window].scale));
|
||||
|
||||
kDebug(1212) << "Window '" << window->caption() << "' gets moved to (" <<
|
||||
mWindowData[window].area.left() << "; " << mWindowData[window].area.right() <<
|
||||
"), scale: " << mWindowData[window].scale << endl;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
double PresentWindowsEffect::windowAspectRatio(EffectWindow* c)
|
||||
{
|
||||
return c->width() / (double)c->height();
|
||||
|
@ -551,10 +534,10 @@ int PresentWindowsEffect::windowHeightForWidth(EffectWindow* c, int w)
|
|||
return (int)((w / (double)c->width()) * c->height());
|
||||
}
|
||||
|
||||
void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowList windowlist)
|
||||
void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowList windowlist, int screen)
|
||||
{
|
||||
// Get rect which we can use on current desktop. This excludes e.g. panels
|
||||
QRect availRect = effects->clientArea( PlacementArea, effects->activeScreen(), effects->currentDesktop());
|
||||
QRect availRect = effects->clientArea( ScreenArea, screen, effects->currentDesktop());
|
||||
qSort( windowlist ); // The location of the windows should not depend on the stacking order
|
||||
|
||||
// Following code is taken from Kompose 0.5.4, src/komposelayout.cpp
|
||||
|
||||
|
@ -572,7 +555,7 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowLis
|
|||
rows = (int)ceil( sqrt((double)windowlist.count()) );
|
||||
columns = (int)ceil( (double)windowlist.count() / (double)rows );
|
||||
}
|
||||
kDebug(1212) << "Using " << rows << " rows & " << columns << " columns for " << windowlist.count() << " clients";
|
||||
//kDebug(1212) << "Using " << rows << " rows & " << columns << " columns for " << windowlist.count() << " clients";
|
||||
|
||||
// Calculate width & height
|
||||
int w = (availRect.width() - (columns+1) * spacing ) / columns;
|
||||
|
@ -641,6 +624,12 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowLis
|
|||
widgeth = usableH;
|
||||
widgetw = (int)widthForHeight;
|
||||
}
|
||||
// Don't upscale large-ish windows
|
||||
if( widgetw > window->width() && ( window->width() > 300 || window->height() > 300 ))
|
||||
{
|
||||
widgetw = window->width();
|
||||
widgeth = window->height();
|
||||
}
|
||||
}
|
||||
|
||||
// Set the Widget's size
|
||||
|
@ -684,9 +673,9 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowLis
|
|||
mWindowData[window].scale = geom.width() / (double)window->width();
|
||||
mWindowData[window].highlight = 0.0f;
|
||||
|
||||
kDebug(1212) << "Window '" << window->caption() << "' gets moved to (" <<
|
||||
mWindowData[window].area.left() << "; " << mWindowData[window].area.right() <<
|
||||
"), scale: " << mWindowData[window].scale << endl;
|
||||
//kDebug(1212) << "Window '" << window->caption() << "' gets moved to (" <<
|
||||
// mWindowData[window].area.left() << "; " << mWindowData[window].area.right() <<
|
||||
// "), scale: " << mWindowData[window].scale << endl;
|
||||
}
|
||||
if ( maxRowHeights[i]-h > 0 )
|
||||
topOffset += maxRowHeights[i]-h;
|
||||
|
@ -695,7 +684,7 @@ void PresentWindowsEffect::calculateWindowTransformationsKompose(EffectWindowLis
|
|||
|
||||
void PresentWindowsEffect::calculateWindowTransformationsClosest(EffectWindowList windowlist, int screen)
|
||||
{
|
||||
QRect area = effects->clientArea( PlacementArea, screen, effects->currentDesktop());
|
||||
QRect area = effects->clientArea( ScreenArea, screen, effects->currentDesktop());
|
||||
int columns = int( ceil( sqrt( (double)windowlist.count())));
|
||||
int rows = int( ceil( windowlist.count() / double( columns )));
|
||||
foreach( EffectWindow* w, windowlist )
|
||||
|
@ -742,7 +731,6 @@ void PresentWindowsEffect::calculateWindowTransformationsClosest(EffectWindowLis
|
|||
if( scale > 2.0 || ( scale > 1.0 && ( w->width() > 300 || w->height() > 300 )))
|
||||
{
|
||||
scale = ( w->width() > 300 || w->height() > 300 ) ? 1.0 : 2.0;
|
||||
QPoint center = geom.center();
|
||||
geom = QRect( geom.center().x() - int( w->width() * scale ) / 2, geom.center().y() - int( w->height() * scale ) / 2,
|
||||
scale * w->width(), scale * w->height() );
|
||||
}
|
||||
|
@ -781,7 +769,7 @@ void PresentWindowsEffect::assignSlots( EffectWindowList windowlist, const QRect
|
|||
pos.setY( area.top());
|
||||
if( pos.y() > area.bottom())
|
||||
pos.setY( area.bottom());
|
||||
int distance = INT_MAX;
|
||||
//int distance = INT_MAX;
|
||||
int xdiff = pos.x() - ( area.x() + slotwidth * x + slotwidth / 2 ); // slotwidth/2 for center
|
||||
int ydiff = pos.y() - ( area.y() + slotheight * y + slotheight / 2 );
|
||||
int dist = int( sqrt( (double)(xdiff * xdiff + ydiff * ydiff) ));
|
||||
|
@ -851,6 +839,254 @@ void PresentWindowsEffect::getBestAssignments( EffectWindowList windowlist )
|
|||
}
|
||||
}
|
||||
|
||||
void PresentWindowsEffect::calculateWindowTransformationsNatural(EffectWindowList windowlist, int screen)
|
||||
{
|
||||
// As we are using pseudo-random movement (See "slot") we need to make sure the list
|
||||
// is always sorted the same way no matter which window is currently active.
|
||||
qSort( windowlist );
|
||||
|
||||
QRect area = effects->clientArea( ScreenArea, screen, effects->currentDesktop());
|
||||
QRect bounds = area;//mWindowData[0].area;
|
||||
int direction = 0;
|
||||
foreach( EffectWindow* w, windowlist )
|
||||
{
|
||||
bounds = bounds.united( w->geometry() );
|
||||
mWindowData[ w ].area = w->geometry();
|
||||
mWindowData[ w ].scale = 1.0;
|
||||
// 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.
|
||||
mWindowData[ w ].slot = direction;
|
||||
direction++;
|
||||
if( direction == 4 )
|
||||
direction = 0;
|
||||
}
|
||||
|
||||
// Iterate over all windows, if two overlap push them apart _slightly_ as we try to
|
||||
// brute-force the most optimal positions over many iterations.
|
||||
bool overlap;
|
||||
do
|
||||
{
|
||||
overlap = false;
|
||||
foreach( EffectWindow* w, windowlist )
|
||||
{
|
||||
foreach( EffectWindow* e, windowlist )
|
||||
{
|
||||
if( w != e && mWindowData[ w ].area.adjusted( -5, -5, 5, 5 ).intersects(
|
||||
mWindowData[ e ].area.adjusted( -5, -5, 5, 5 )))
|
||||
{
|
||||
overlap = true;
|
||||
|
||||
// Determine pushing direction
|
||||
QPoint diff( mWindowData[ e ].area.center() - mWindowData[ w ].area.center() );
|
||||
// Prevent dividing by zero and non-movement
|
||||
if( diff.x() == 0 && diff.y() == 0 )
|
||||
diff.setX( 1 );
|
||||
// Try to keep screen aspect ratio
|
||||
//if( bounds.height() / bounds.width() > area.height() / area.width() )
|
||||
// diff.setY( diff.y() / 2 );
|
||||
//else
|
||||
// diff.setX( diff.x() / 2 );
|
||||
// Approximate a vector of between 10px and 20px in magnitude in the same direction
|
||||
diff *= accuracy / double( diff.manhattanLength() );
|
||||
// Move both windows apart
|
||||
mWindowData[ w ].area.translate( -diff );
|
||||
mWindowData[ e ].area.translate( diff );
|
||||
|
||||
// Try to keep the bounding rect the same aspect as the screen so that more
|
||||
// screen real estate is utilised. We do this by splitting the screen into nine
|
||||
// equal sections, if the window center is in any of the corner sections pull the
|
||||
// window towards the outer corner. If it is in any of the other edge sections
|
||||
// alternate between each corner on that edge. We don't want to determine it
|
||||
// randomly as it will not produce consistant locations when using the filter.
|
||||
// Only move one window so we don't cause large amounts of unnecessary zooming
|
||||
// in some situations. We only need to do this if we are not expanding later.
|
||||
// (We are using an old bounding rect for this, hopefully it doesn't matter)
|
||||
if( !fillGaps )
|
||||
{
|
||||
int xSection = ( mWindowData[ w ].area.x() - bounds.x() ) / ( bounds.width() / 3 );
|
||||
int ySection = ( mWindowData[ w ].area.y() - bounds.y() ) / ( bounds.height() / 3 );
|
||||
diff = QPoint( 0, 0 );
|
||||
if( xSection != 1 || ySection != 1 ) // Remove this if you want the center to pull as well
|
||||
{
|
||||
if( xSection == 1 )
|
||||
xSection = ( mWindowData[ w ].slot / 2 ? 2 : 0 );
|
||||
if( ySection == 1 )
|
||||
ySection = ( mWindowData[ w ].slot % 2 ? 2 : 0 );
|
||||
}
|
||||
if( xSection == 0 && ySection == 0 )
|
||||
diff = QPoint( bounds.topLeft() - mWindowData[ w ].area.center() );
|
||||
if( xSection == 2 && ySection == 0 )
|
||||
diff = QPoint( bounds.topRight() - mWindowData[ w ].area.center() );
|
||||
if( xSection == 2 && ySection == 2 )
|
||||
diff = QPoint( bounds.bottomRight() - mWindowData[ w ].area.center() );
|
||||
if( xSection == 0 && ySection == 2 )
|
||||
diff = QPoint( bounds.bottomLeft() - mWindowData[ w ].area.center() );
|
||||
if( diff.x() != 0 || diff.y() != 0 )
|
||||
{
|
||||
diff *= accuracy / double( diff.manhattanLength() );
|
||||
mWindowData[ w ].area.translate( diff );
|
||||
}
|
||||
}
|
||||
|
||||
// Update bounding rect
|
||||
bounds = bounds.united( mWindowData[ w ].area );
|
||||
bounds = bounds.united( mWindowData[ e ].area );
|
||||
}
|
||||
}
|
||||
}
|
||||
} while( overlap );
|
||||
|
||||
// Work out scaling by getting the most top-left and most bottom-right window coords.
|
||||
// The 20's and 10's are so that the windows don't touch the edge of the screen.
|
||||
double scale;
|
||||
if( bounds == area )
|
||||
scale = 1.0; // Don't add borders to the screen
|
||||
else if( area.width() / double( bounds.width() ) < area.height() / double( bounds.height() ))
|
||||
scale = ( area.width() - 20 ) / double( bounds.width() );
|
||||
else
|
||||
scale = ( area.height() - 20 ) / double( bounds.height() );
|
||||
// Make bounding rect fill the screen size for later steps
|
||||
bounds = QRect(
|
||||
bounds.x() - ( area.width() - 20 - bounds.width() * scale ) / 2 - 10 / scale,
|
||||
bounds.y() - ( area.height() - 20 - bounds.height() * scale ) / 2 - 10 / scale,
|
||||
area.width() / scale,
|
||||
area.height() / scale
|
||||
);
|
||||
|
||||
// Move all windows back onto the screen and set their scale
|
||||
foreach( EffectWindow* w, windowlist )
|
||||
{
|
||||
mWindowData[ w ].scale = scale;
|
||||
mWindowData[ w ].area = QRect(
|
||||
( mWindowData[ w ].area.x() - bounds.x() ) * scale + area.x(),
|
||||
( mWindowData[ w ].area.y() - bounds.y() ) * scale + area.y(),
|
||||
mWindowData[ w ].area.width() * scale,
|
||||
mWindowData[ w ].area.height() * scale
|
||||
);
|
||||
}
|
||||
|
||||
// Try to fill the gaps by enlarging windows if they have the space
|
||||
if( fillGaps )
|
||||
{
|
||||
// Don't expand onto or over the border
|
||||
QRegion borderRegion( area.adjusted( -200, -200, 200, 200 ));
|
||||
borderRegion ^= area.adjusted( 10 / scale, 10 / scale, -10 / scale, -10 / scale );
|
||||
|
||||
bool moved;
|
||||
do
|
||||
{
|
||||
moved = false;
|
||||
foreach( EffectWindow* w, windowlist )
|
||||
{
|
||||
QRect oldRect;
|
||||
// This may cause some slight distortion if the windows are enlarged a large amount
|
||||
int widthDiff = accuracy;
|
||||
int heightDiff = windowHeightForWidth( w, mWindowData[ w ].area.width() + widthDiff ) - mWindowData[ w ].area.height();
|
||||
int xDiff = widthDiff / 2; // Also move a bit in the direction of the enlarge, allows the
|
||||
int yDiff = heightDiff / 2; // center windows to be enlarged if there is gaps on the side.
|
||||
|
||||
// Attempt enlarging to the top-right
|
||||
oldRect = mWindowData[ w ].area;
|
||||
mWindowData[ w ].area = QRect(
|
||||
mWindowData[ w ].area.x() + xDiff,
|
||||
mWindowData[ w ].area.y() - yDiff - heightDiff,
|
||||
mWindowData[ w ].area.width() + widthDiff,
|
||||
mWindowData[ w ].area.height() + heightDiff
|
||||
);
|
||||
if( isOverlappingAny( w, windowlist, borderRegion ))
|
||||
mWindowData[ w ].area = oldRect;
|
||||
else
|
||||
{
|
||||
mWindowData[ w ].scale = mWindowData[ w ].area.width() / double( w->width() );
|
||||
moved = true;
|
||||
}
|
||||
|
||||
// Attempt enlarging to the bottom-right
|
||||
oldRect = mWindowData[ w ].area;
|
||||
mWindowData[ w ].area = QRect(
|
||||
mWindowData[ w ].area.x() + xDiff,
|
||||
mWindowData[ w ].area.y() + yDiff,
|
||||
mWindowData[ w ].area.width() + widthDiff,
|
||||
mWindowData[ w ].area.height() + heightDiff
|
||||
);
|
||||
if( isOverlappingAny( w, windowlist, borderRegion ))
|
||||
mWindowData[ w ].area = oldRect;
|
||||
else
|
||||
{
|
||||
mWindowData[ w ].scale = mWindowData[ w ].area.width() / double( w->width() );
|
||||
moved = true;
|
||||
}
|
||||
|
||||
// Attempt enlarging to the bottom-left
|
||||
oldRect = mWindowData[ w ].area;
|
||||
mWindowData[ w ].area = QRect(
|
||||
mWindowData[ w ].area.x() - xDiff - widthDiff,
|
||||
mWindowData[ w ].area.y() + yDiff,
|
||||
mWindowData[ w ].area.width() + widthDiff,
|
||||
mWindowData[ w ].area.height() + heightDiff
|
||||
);
|
||||
if( isOverlappingAny( w, windowlist, borderRegion ))
|
||||
mWindowData[ w ].area = oldRect;
|
||||
else
|
||||
{
|
||||
mWindowData[ w ].scale = mWindowData[ w ].area.width() / double( w->width() );
|
||||
moved = true;
|
||||
}
|
||||
|
||||
// Attempt enlarging to the top-left
|
||||
oldRect = mWindowData[ w ].area;
|
||||
mWindowData[ w ].area = QRect(
|
||||
mWindowData[ w ].area.x() - xDiff - widthDiff,
|
||||
mWindowData[ w ].area.y() - yDiff - heightDiff,
|
||||
mWindowData[ w ].area.width() + widthDiff,
|
||||
mWindowData[ w ].area.height() + heightDiff
|
||||
);
|
||||
if( isOverlappingAny( w, windowlist, borderRegion ))
|
||||
mWindowData[ w ].area = oldRect;
|
||||
else
|
||||
{
|
||||
mWindowData[ w ].scale = mWindowData[ w ].area.width() / double( w->width() );
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
} while( moved );
|
||||
|
||||
// The expanding code above can actually enlarge windows over 1.0/2.0 scale, we don't like this
|
||||
// We can't add this to the loop above as it would cause a never-ending loop so we have to make
|
||||
// do with the less-than-optimal space usage with using this method.
|
||||
foreach( EffectWindow* w, windowlist )
|
||||
{
|
||||
if( mWindowData[ w ].scale > 2.0 ||
|
||||
( mWindowData[ w ].scale > 1.0 && ( w->width() > 300 || w->height() > 300 )))
|
||||
{
|
||||
mWindowData[ w ].scale = ( w->width() > 300 || w->height() > 300 ) ? 1.0 : 2.0;
|
||||
mWindowData[ w ].area = QRect(
|
||||
mWindowData[ w ].area.center().x() - int( w->width() * mWindowData[ w ].scale ) / 2,
|
||||
mWindowData[ w ].area.center().y() - int( w->height() * mWindowData[ w ].scale ) / 2,
|
||||
w->width() * mWindowData[ w ].scale,
|
||||
w->height() * mWindowData[ w ].scale
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PresentWindowsEffect::isOverlappingAny( EffectWindow* w, const EffectWindowList& windowlist, const QRegion& border )
|
||||
{
|
||||
if( border.intersects( mWindowData[ w ].area ))
|
||||
return true;
|
||||
// Is there a better way to do this?
|
||||
foreach( EffectWindow* e, windowlist )
|
||||
{
|
||||
if( w == e )
|
||||
continue;
|
||||
if( mWindowData[ w ].area.adjusted( -5, -5, 5, 5 ).intersects(
|
||||
mWindowData[ e ].area.adjusted( -5, -5, 5, 5 )))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PresentWindowsEffect::borderActivated( ElectricBorder border )
|
||||
{
|
||||
if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this )
|
||||
|
@ -946,6 +1182,140 @@ void PresentWindowsEffect::setHighlightedWindow( EffectWindow* w )
|
|||
|
||||
// returns a window which is to relative position <xdiff,ydiff> from the given window
|
||||
EffectWindow* PresentWindowsEffect::relativeWindow( EffectWindow* w, int xdiff, int ydiff, bool wrap ) const
|
||||
{
|
||||
// Using the grid to determine the window only works on grid layouts and only have one screen.
|
||||
// On multi-screen setups the grid coords are reused on each screen and each screen may also
|
||||
// have a different grid size.
|
||||
if( layoutMode != LayoutNatural && effects->numScreens() < 2 )
|
||||
return relativeWindowGrid( w, xdiff, ydiff, wrap );
|
||||
|
||||
// Attempt to find the window from its rect instead
|
||||
EffectWindow* next;
|
||||
QRect area = effects->clientArea( FullArea, 0, effects->currentDesktop() );
|
||||
QRect detectRect;
|
||||
|
||||
// Detect across the width of the desktop
|
||||
if( xdiff != 0 )
|
||||
{
|
||||
if( xdiff > 0 )
|
||||
{ // Detect right
|
||||
for( int i = 0; i < xdiff; i++ )
|
||||
{
|
||||
detectRect = QRect( 0, mWindowData[ w ].area.y(), area.width(), mWindowData[ w ].area.height() );
|
||||
next = NULL;
|
||||
foreach( EffectWindow* e, mWindowsToPresent )
|
||||
{
|
||||
if( mWindowData[ e ].area.intersects( detectRect ) &&
|
||||
mWindowData[ e ].area.x() > mWindowData[ w ].area.x() )
|
||||
{
|
||||
if( next == NULL )
|
||||
next = e;
|
||||
else if( mWindowData[ e ].area.x() < mWindowData[ next ].area.x() )
|
||||
next = e;
|
||||
}
|
||||
}
|
||||
if( next == NULL )
|
||||
{
|
||||
if( wrap ) // We are at the right-most window, now get the left-most one to wrap
|
||||
return relativeWindow( w, -1000, 0, false );
|
||||
break; // No more windows to the right
|
||||
}
|
||||
w = next;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
else
|
||||
{ // Detect left
|
||||
for( int i = 0; i < -xdiff; i++ )
|
||||
{
|
||||
detectRect = QRect( 0, mWindowData[ w ].area.y(), area.width(), mWindowData[ w ].area.height() );
|
||||
next = NULL;
|
||||
foreach( EffectWindow* e, mWindowsToPresent )
|
||||
{
|
||||
if( mWindowData[ e ].area.intersects( detectRect ) &&
|
||||
mWindowData[ e ].area.x() + mWindowData[ e ].area.width() < mWindowData[ w ].area.x() + mWindowData[ w ].area.width() )
|
||||
{
|
||||
if( next == NULL )
|
||||
next = e;
|
||||
else if( mWindowData[ e ].area.x() + mWindowData[ e ].area.width() > mWindowData[ next ].area.x() + mWindowData[ next ].area.width() )
|
||||
next = e;
|
||||
}
|
||||
}
|
||||
if( next == NULL )
|
||||
{
|
||||
if( wrap ) // We are at the left-most window, now get the right-most one to wrap
|
||||
return relativeWindow( w, 1000, 0, false );
|
||||
break; // No more windows to the left
|
||||
}
|
||||
w = next;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect across the height of the desktop
|
||||
if( ydiff != 0 )
|
||||
{
|
||||
if( ydiff > 0 )
|
||||
{ // Detect down
|
||||
for( int i = 0; i < ydiff; i++ )
|
||||
{
|
||||
detectRect = QRect( mWindowData[ w ].area.x(), 0, mWindowData[ w ].area.width(), area.height() );
|
||||
next = NULL;
|
||||
foreach( EffectWindow* e, mWindowsToPresent )
|
||||
{
|
||||
if( mWindowData[ e ].area.intersects( detectRect ) &&
|
||||
mWindowData[ e ].area.y() > mWindowData[ w ].area.y() )
|
||||
{
|
||||
if( next == NULL )
|
||||
next = e;
|
||||
else if( mWindowData[ e ].area.y() < mWindowData[ next ].area.y() )
|
||||
next = e;
|
||||
}
|
||||
}
|
||||
if( next == NULL )
|
||||
{
|
||||
if( wrap ) // We are at the bottom-most window, now get the top-most one to wrap
|
||||
return relativeWindow( w, 0, -1000, false );
|
||||
break; // No more windows to the bottom
|
||||
}
|
||||
w = next;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
else
|
||||
{ // Detect up
|
||||
for( int i = 0; i < -ydiff; i++ )
|
||||
{
|
||||
detectRect = QRect( mWindowData[ w ].area.x(), 0, mWindowData[ w ].area.width(), area.height() );
|
||||
next = NULL;
|
||||
foreach( EffectWindow* e, mWindowsToPresent )
|
||||
{
|
||||
if( mWindowData[ e ].area.intersects( detectRect ) &&
|
||||
mWindowData[ e ].area.y() + mWindowData[ e ].area.height() < mWindowData[ w ].area.y() + mWindowData[ w ].area.height() )
|
||||
{
|
||||
if( next == NULL )
|
||||
next = e;
|
||||
else if( mWindowData[ e ].area.y() + mWindowData[ e ].area.height() > mWindowData[ next ].area.y() + mWindowData[ next ].area.height() )
|
||||
next = e;
|
||||
}
|
||||
}
|
||||
if( next == NULL )
|
||||
{
|
||||
if( wrap ) // We are at the top-most window, now get the bottom-most one to wrap
|
||||
return relativeWindow( w, 0, 1000, false );
|
||||
break; // No more windows to the top
|
||||
}
|
||||
w = next;
|
||||
}
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
assert( false ); // Should never get here
|
||||
}
|
||||
|
||||
EffectWindow* PresentWindowsEffect::relativeWindowGrid( EffectWindow* w, int xdiff, int ydiff, bool wrap ) const
|
||||
{
|
||||
if( mWindowData.count() == 0 )
|
||||
return NULL;
|
||||
|
@ -1043,11 +1413,26 @@ EffectWindow* PresentWindowsEffect::relativeWindow( EffectWindow* w, int xdiff,
|
|||
// returns the window that is the most to the topleft, if any
|
||||
EffectWindow* PresentWindowsEffect::findFirstWindow() const
|
||||
{
|
||||
if( layoutMode == LayoutNatural || effects->numScreens() > 1 )
|
||||
{
|
||||
EffectWindow* topLeft = NULL;
|
||||
foreach( EffectWindow* w, mWindowsToPresent )
|
||||
{
|
||||
if( topLeft == NULL )
|
||||
topLeft = w;
|
||||
else if( w->x() < topLeft->x() || w->y() < topLeft->y() )
|
||||
topLeft = w;
|
||||
}
|
||||
return topLeft;
|
||||
}
|
||||
|
||||
// The following only works on grid layouts on a single screen
|
||||
|
||||
int minslot = INT_MAX;
|
||||
EffectWindow* ret = NULL;
|
||||
for( DataHash::ConstIterator it = mWindowData.begin();
|
||||
it != mWindowData.end();
|
||||
++it )
|
||||
it != mWindowData.end();
|
||||
++it )
|
||||
{
|
||||
if( (*it).slot < minslot )
|
||||
{
|
||||
|
|
|
@ -120,10 +120,10 @@ Comment[zh_TW]=讓所有視窗排排站
|
|||
|
||||
Type=Service
|
||||
X-KDE-ServiceTypes=KWin/Effect
|
||||
X-KDE-PluginInfo-Author=Rivo Laks
|
||||
X-KDE-PluginInfo-Email=rivolaks@hot.ee
|
||||
X-KDE-PluginInfo-Author=Rivo Laks & Lucas Murray
|
||||
X-KDE-PluginInfo-Email=rivolaks@hot.ee & lmurray@undefinedfire.com
|
||||
X-KDE-PluginInfo-Name=kwin4_effect_presentwindows
|
||||
X-KDE-PluginInfo-Version=0.1.0
|
||||
X-KDE-PluginInfo-Version=0.2.0
|
||||
X-KDE-PluginInfo-Category=Appearance
|
||||
X-KDE-PluginInfo-Depends=
|
||||
X-KDE-PluginInfo-License=GPL
|
||||
|
|
|
@ -58,6 +58,8 @@ class PresentWindowsEffect
|
|||
virtual void tabBoxClosed();
|
||||
virtual void tabBoxUpdated();
|
||||
|
||||
enum { LayoutNatural, LayoutRegularGrid, LayoutFlexibleGrid }; // Layout modes
|
||||
|
||||
public slots:
|
||||
void setActive(bool active);
|
||||
void toggleActive() { mShowWindowsFromAllDesktops = false; setActive(!mActivated); }
|
||||
|
@ -67,9 +69,9 @@ class PresentWindowsEffect
|
|||
// Updates window tranformations, i.e. destination pos and scale of the window
|
||||
void rearrangeWindows();
|
||||
void prepareToRearrange();
|
||||
void calculateWindowTransformationsDumb(EffectWindowList windowlist);
|
||||
void calculateWindowTransformationsKompose(EffectWindowList windowlist);
|
||||
void calculateWindowTransformationsKompose(EffectWindowList windowlist, int screen);
|
||||
void calculateWindowTransformationsClosest(EffectWindowList windowlist, int screen);
|
||||
void calculateWindowTransformationsNatural(EffectWindowList windowlist, int screen);
|
||||
|
||||
// Helper methods for layout calculation
|
||||
double windowAspectRatio(EffectWindow* c);
|
||||
|
@ -79,6 +81,8 @@ class PresentWindowsEffect
|
|||
void assignSlots( EffectWindowList windowlist, const QRect& area, int columns, int rows );
|
||||
void getBestAssignments( EffectWindowList windowlist );
|
||||
|
||||
bool isOverlappingAny( EffectWindow* w, const EffectWindowList& windowlist, const QRegion& border );
|
||||
|
||||
void updateFilterTexture();
|
||||
void discardFilterTexture();
|
||||
|
||||
|
@ -86,6 +90,7 @@ class PresentWindowsEffect
|
|||
|
||||
void setHighlightedWindow( EffectWindow* w );
|
||||
EffectWindow* relativeWindow( EffectWindow* w, int xdiff, int ydiff, bool wrap ) const;
|
||||
EffectWindow* relativeWindowGrid( EffectWindow* w, int xdiff, int ydiff, bool wrap ) const;
|
||||
EffectWindow* findFirstWindow() const;
|
||||
|
||||
// Called once the effect is activated (and wasn't activated before)
|
||||
|
@ -146,9 +151,13 @@ class PresentWindowsEffect
|
|||
|
||||
ElectricBorder borderActivate;
|
||||
ElectricBorder borderActivateAll;
|
||||
int layoutMode;
|
||||
bool drawWindowCaptions;
|
||||
bool drawWindowIcons;
|
||||
bool mTabBoxMode;
|
||||
bool tabBox;
|
||||
int accuracy;
|
||||
bool fillGaps;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -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,170 +20,183 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
*********************************************************************/
|
||||
|
||||
#include "presentwindows_config.h"
|
||||
|
||||
#include <kwineffects.h>
|
||||
|
||||
#include <klocale.h>
|
||||
#include <kdebug.h>
|
||||
#include <kconfiggroup.h>
|
||||
#include <KActionCollection>
|
||||
#include <kaction.h>
|
||||
#include <KShortcutsEditor>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QColor>
|
||||
#ifndef KDE_USE_FINAL
|
||||
KWIN_EFFECT_CONFIG_FACTORY
|
||||
#endif
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
PresentWindowsEffectConfig::PresentWindowsEffectConfig(QWidget* parent, const QVariantList& args) :
|
||||
KCModule(EffectFactory::componentData(), parent, args)
|
||||
PresentWindowsEffectConfigForm::PresentWindowsEffectConfigForm(QWidget* parent) : QWidget(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
}
|
||||
|
||||
PresentWindowsEffectConfig::PresentWindowsEffectConfig(QWidget* parent, const QVariantList& args)
|
||||
: KCModule( EffectFactory::componentData(), parent, args )
|
||||
{
|
||||
kDebug();
|
||||
m_ui = new PresentWindowsEffectConfigForm( this );
|
||||
|
||||
QGridLayout* layout = new QGridLayout(this);
|
||||
QVBoxLayout* layout = new QVBoxLayout( this );
|
||||
|
||||
mDrawWindowText = new QCheckBox(i18n("Draw window caption on top of window"), this);
|
||||
connect(mDrawWindowText, SIGNAL(stateChanged(int)), this, SLOT(changed()));
|
||||
layout->addWidget(mDrawWindowText, 0, 0);
|
||||
layout->addWidget( m_ui );
|
||||
|
||||
mTabBoxCheck = new QCheckBox(i18n("Use for window switching"), this);
|
||||
connect(mTabBoxCheck, SIGNAL(stateChanged(int)), this, SLOT(changed()));
|
||||
layout->addWidget(mTabBoxCheck, 1, 0 );
|
||||
m_actionCollection = new KActionCollection( this, componentData() );
|
||||
m_actionCollection->setConfigGroup( "PresentWindows" );
|
||||
m_actionCollection->setConfigGlobal( true );
|
||||
|
||||
layout->addWidget(new QLabel(i18n("Activate when cursor is at a specific edge "
|
||||
"or corner of the screen:"), this), 2, 0, 1, 3);
|
||||
layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Fixed), 2, 0, 2, 1);
|
||||
KAction* a = (KAction*) m_actionCollection->addAction( "ExposeAll" );
|
||||
a->setText( i18n( "Toggle Present Windows (All desktops)" ));
|
||||
a->setProperty( "isConfigurationAction", true );
|
||||
a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F10 ));
|
||||
|
||||
layout->addWidget(new QLabel(i18n("for windows on current desktop: "), this), 3, 1);
|
||||
mActivateCombo = new QComboBox;
|
||||
addItems(mActivateCombo);
|
||||
connect(mActivateCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed()));
|
||||
layout->addWidget(mActivateCombo, 3, 2);
|
||||
KAction* b = (KAction*) m_actionCollection->addAction( "Expose" );
|
||||
b->setText( i18n( "Toggle Present Windows (Current desktop)" ));
|
||||
b->setProperty( "isConfigurationAction", true );
|
||||
b->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F9 ));
|
||||
|
||||
layout->addWidget(new QLabel(i18n("for windows on all desktops: "), this), 4, 1);
|
||||
mActivateAllCombo = new QComboBox;
|
||||
addItems(mActivateAllCombo);
|
||||
connect(mActivateAllCombo, SIGNAL(currentIndexChanged(int)), this, SLOT(changed()));
|
||||
layout->addWidget(mActivateAllCombo, 4, 2);
|
||||
m_ui->shortcutEditor->addCollection( m_actionCollection );
|
||||
|
||||
layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding), 5, 0, 1, 3);
|
||||
m_ui->screenEdgeAllCombo->addItem( i18n( "Top" ));
|
||||
m_ui->screenEdgeAllCombo->addItem( i18n( "Top-right" ));
|
||||
m_ui->screenEdgeAllCombo->addItem( i18n( "Right" ));
|
||||
m_ui->screenEdgeAllCombo->addItem( i18n( "Bottom-right" ));
|
||||
m_ui->screenEdgeAllCombo->addItem( i18n( "Bottom" ));
|
||||
m_ui->screenEdgeAllCombo->addItem( i18n( "Bottom-left" ));
|
||||
m_ui->screenEdgeAllCombo->addItem( i18n( "Left" ));
|
||||
m_ui->screenEdgeAllCombo->addItem( i18n( "Top-left" ));
|
||||
m_ui->screenEdgeAllCombo->addItem( i18n( "None" ));
|
||||
|
||||
// Shortcut config
|
||||
KActionCollection* actionCollection = new KActionCollection( this, componentData() );
|
||||
KAction* a = (KAction*)actionCollection->addAction( "Expose" );
|
||||
a->setText( i18n("Toggle Expose Effect" ));
|
||||
a->setProperty("isConfigurationAction", true);
|
||||
a->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F9));
|
||||
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" ));
|
||||
|
||||
KAction* b = (KAction*)actionCollection->addAction( "ExposeAll" );
|
||||
b->setText( i18n("Toggle Expose Effect (incl. other desktops)" ));
|
||||
b->setProperty("isConfigurationAction", true);
|
||||
b->setGlobalShortcut(KShortcut(Qt::CTRL + Qt::Key_F10));
|
||||
|
||||
mShortcutEditor = new KShortcutsEditor(actionCollection, this,
|
||||
KShortcutsEditor::GlobalAction, KShortcutsEditor::LetterShortcutsDisallowed);
|
||||
connect(mShortcutEditor, SIGNAL(keyChange()), this, SLOT(changed()));
|
||||
layout->addWidget(mShortcutEditor, 6, 0, 1, 3);
|
||||
|
||||
layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding), 7, 0, 1, 3);
|
||||
connect( m_ui->layoutCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() ));
|
||||
connect( m_ui->rearrangeDurationSpin, SIGNAL( valueChanged( int )), this, SLOT( changed() ));
|
||||
connect( m_ui->displayTitleBox, SIGNAL( stateChanged( int )), this, SLOT( changed() ));
|
||||
connect( m_ui->displayIconBox, SIGNAL( stateChanged( int )), this, SLOT( changed() ));
|
||||
connect( m_ui->switchingBox, SIGNAL( stateChanged( int )), this, SLOT( changed() ));
|
||||
connect( m_ui->accuracySlider, SIGNAL( valueChanged( int )), this, SLOT( changed() ));
|
||||
connect( m_ui->fillGapsBox, SIGNAL( stateChanged( int )), this, SLOT( changed() ));
|
||||
connect( m_ui->screenEdgeAllCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() ));
|
||||
connect( m_ui->screenEdgeCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() ));
|
||||
connect( m_ui->shortcutEditor, SIGNAL( keyChange() ), this, SLOT( changed() ));
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
PresentWindowsEffectConfig::~PresentWindowsEffectConfig()
|
||||
{
|
||||
kDebug();
|
||||
// Undo (only) unsaved changes to global key shortcuts
|
||||
mShortcutEditor->undoChanges();
|
||||
}
|
||||
|
||||
void PresentWindowsEffectConfig::addItems(QComboBox* combo)
|
||||
{
|
||||
combo->addItem(i18n("Top"));
|
||||
combo->addItem(i18n("Top-right"));
|
||||
combo->addItem(i18n("Right"));
|
||||
combo->addItem(i18n("Bottom-right"));
|
||||
combo->addItem(i18n("Bottom"));
|
||||
combo->addItem(i18n("Bottom-left"));
|
||||
combo->addItem(i18n("Left"));
|
||||
combo->addItem(i18n("Top-left"));
|
||||
combo->addItem(i18n("None"));
|
||||
// If save() is called undoChanges() has no effect
|
||||
m_ui->shortcutEditor->undoChanges();
|
||||
}
|
||||
|
||||
void PresentWindowsEffectConfig::load()
|
||||
{
|
||||
kDebug() ;
|
||||
KCModule::load();
|
||||
|
||||
KConfigGroup conf = EffectsHandler::effectConfig("PresentWindows");
|
||||
int activateBorder = conf.readEntry("BorderActivate", (int)ElectricNone);
|
||||
if(activateBorder == (int)ElectricNone)
|
||||
activateBorder--;
|
||||
mActivateCombo->setCurrentIndex(activateBorder);
|
||||
KConfigGroup conf = EffectsHandler::effectConfig( "PresentWindows" );
|
||||
|
||||
int layoutMode = conf.readEntry( "LayoutMode", int( PresentWindowsEffect::LayoutNatural ));
|
||||
m_ui->layoutCombo->setCurrentIndex( layoutMode );
|
||||
|
||||
int activateAllBorder = conf.readEntry("BorderActivateAll", (int)ElectricTopLeft);
|
||||
if(activateAllBorder == (int)ElectricNone)
|
||||
m_ui->rearrangeDurationSpin->setValue( conf.readEntry( "RearrangeDuration", 250 ));
|
||||
|
||||
bool displayTitle = conf.readEntry( "DrawWindowCaptions", true );
|
||||
m_ui->displayTitleBox->setChecked( displayTitle );
|
||||
|
||||
bool displayIcon = conf.readEntry( "DrawWindowIcons", true );
|
||||
m_ui->displayIconBox->setChecked( displayIcon );
|
||||
|
||||
bool switching = conf.readEntry( "TabBox", false );
|
||||
m_ui->switchingBox->setChecked( switching );
|
||||
|
||||
int accuracy = conf.readEntry( "Accuracy", 1 );
|
||||
m_ui->accuracySlider->setSliderPosition( accuracy );
|
||||
|
||||
bool fillGaps = conf.readEntry( "FillGaps", true );
|
||||
m_ui->fillGapsBox->setChecked( fillGaps );
|
||||
|
||||
int activateAllBorder = conf.readEntry( "BorderActivateAll", int( ElectricTopLeft ));
|
||||
if( activateAllBorder == int( ElectricNone ))
|
||||
activateAllBorder--;
|
||||
mActivateAllCombo->setCurrentIndex(activateAllBorder);
|
||||
m_ui->screenEdgeAllCombo->setCurrentIndex( activateAllBorder );
|
||||
|
||||
bool drawWindowCaptions = conf.readEntry("DrawWindowCaptions", true);
|
||||
mDrawWindowText->setChecked(drawWindowCaptions);
|
||||
|
||||
bool tabBox = conf.readEntry("TabBox", false);
|
||||
mTabBoxCheck->setChecked(tabBox);
|
||||
int activateBorder = conf.readEntry( "BorderActivate", int( ElectricNone ));
|
||||
if( activateBorder == int( ElectricNone ))
|
||||
activateBorder--;
|
||||
m_ui->screenEdgeCombo->setCurrentIndex( activateBorder );
|
||||
|
||||
emit changed(false);
|
||||
}
|
||||
|
||||
void PresentWindowsEffectConfig::save()
|
||||
{
|
||||
kDebug() ;
|
||||
KCModule::save();
|
||||
|
||||
KConfigGroup conf = EffectsHandler::effectConfig("PresentWindows");
|
||||
KConfigGroup conf = EffectsHandler::effectConfig( "PresentWindows" );
|
||||
|
||||
int activateBorder = mActivateCombo->currentIndex();
|
||||
if(activateBorder == (int)ELECTRIC_COUNT)
|
||||
activateBorder = (int)ElectricNone;
|
||||
conf.writeEntry("BorderActivate", activateBorder);
|
||||
int layoutMode = m_ui->layoutCombo->currentIndex();
|
||||
conf.writeEntry( "LayoutMode", layoutMode );
|
||||
|
||||
int activateAllBorder = mActivateAllCombo->currentIndex();
|
||||
if(activateAllBorder == (int)ELECTRIC_COUNT)
|
||||
activateAllBorder = (int)ElectricNone;
|
||||
conf.writeEntry("BorderActivateAll", activateAllBorder);
|
||||
conf.writeEntry( "RearrangeDuration", m_ui->rearrangeDurationSpin->value() );
|
||||
|
||||
bool drawWindowCaptions = mDrawWindowText->isChecked();
|
||||
conf.writeEntry("DrawWindowCaptions", drawWindowCaptions);
|
||||
conf.writeEntry( "DrawWindowCaptions", m_ui->displayTitleBox->isChecked() );
|
||||
conf.writeEntry( "DrawWindowIcons", m_ui->displayIconBox->isChecked() );
|
||||
conf.writeEntry( "TabBox", m_ui->switchingBox->isChecked() );
|
||||
|
||||
bool tabBox = mTabBoxCheck->isChecked();
|
||||
conf.writeEntry("TabBox", tabBox);
|
||||
int accuracy = m_ui->accuracySlider->value();
|
||||
conf.writeEntry( "Accuracy", accuracy );
|
||||
|
||||
conf.writeEntry( "FillGaps", m_ui->fillGapsBox->isChecked() );
|
||||
|
||||
int activateAllBorder = m_ui->screenEdgeAllCombo->currentIndex();
|
||||
if( activateAllBorder == int( ELECTRIC_COUNT ))
|
||||
activateAllBorder = int( ElectricNone );
|
||||
conf.writeEntry( "BorderActivateAll", activateAllBorder );
|
||||
|
||||
int activateBorder = m_ui->screenEdgeCombo->currentIndex();
|
||||
if( activateBorder == int( ELECTRIC_COUNT ))
|
||||
activateBorder = int( ElectricNone );
|
||||
conf.writeEntry( "BorderActivate", activateBorder );
|
||||
|
||||
m_ui->shortcutEditor->save();
|
||||
|
||||
conf.sync();
|
||||
|
||||
mShortcutEditor->save(); // undo() will restore to this state from now on
|
||||
|
||||
emit changed(false);
|
||||
EffectsHandler::sendReloadMessage( "presentwindows" );
|
||||
}
|
||||
|
||||
void PresentWindowsEffectConfig::defaults()
|
||||
{
|
||||
kDebug() ;
|
||||
mActivateCombo->setCurrentIndex( (int)ElectricNone - 1 );
|
||||
mActivateAllCombo->setCurrentIndex( (int)ElectricTopLeft );
|
||||
mDrawWindowText->setChecked(true);
|
||||
mTabBoxCheck->setChecked(false);
|
||||
mShortcutEditor->allDefault();
|
||||
m_ui->layoutCombo->setCurrentIndex( int( PresentWindowsEffect::LayoutNatural ));
|
||||
m_ui->rearrangeDurationSpin->setValue( 250 );
|
||||
m_ui->displayTitleBox->setChecked( true );
|
||||
m_ui->displayIconBox->setChecked( true );
|
||||
m_ui->switchingBox->setChecked( false );
|
||||
m_ui->accuracySlider->setSliderPosition( 1 );
|
||||
m_ui->fillGapsBox->setChecked( true );
|
||||
m_ui->screenEdgeAllCombo->setCurrentIndex( int( ElectricTopLeft ));
|
||||
m_ui->screenEdgeCombo->setCurrentIndex( int( ElectricNone - 1 ));
|
||||
m_ui->shortcutEditor->allDefault();
|
||||
emit changed(true);
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#include "presentwindows_config.moc"
|
||||
|
|
|
@ -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,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
|
||||
#include <kcmodule.h>
|
||||
|
||||
class QCheckBox;
|
||||
class QComboBox;
|
||||
class KShortcutsEditor;
|
||||
#include "ui_presentwindows_config.h"
|
||||
#include "presentwindows.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class PresentWindowsEffectConfigForm : public QWidget, public Ui::PresentWindowsEffectConfigForm
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PresentWindowsEffectConfigForm(QWidget* parent);
|
||||
};
|
||||
|
||||
class PresentWindowsEffectConfig : public KCModule
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -37,19 +44,14 @@ class PresentWindowsEffectConfig : public KCModule
|
|||
explicit PresentWindowsEffectConfig(QWidget* parent = 0, const QVariantList& args = QVariantList());
|
||||
~PresentWindowsEffectConfig();
|
||||
|
||||
public slots:
|
||||
virtual void save();
|
||||
virtual void load();
|
||||
virtual void defaults();
|
||||
|
||||
protected:
|
||||
void addItems(QComboBox* combo);
|
||||
|
||||
private:
|
||||
QCheckBox* mDrawWindowText;
|
||||
QCheckBox* mTabBoxCheck;
|
||||
QComboBox* mActivateCombo;
|
||||
QComboBox* mActivateAllCombo;
|
||||
KShortcutsEditor* mShortcutEditor;
|
||||
PresentWindowsEffectConfigForm* m_ui;
|
||||
KActionCollection* m_actionCollection;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
243
effects/presentwindows_config.ui
Normal file
243
effects/presentwindows_config.ui
Normal file
|
@ -0,0 +1,243 @@
|
|||
<ui version="4.0" >
|
||||
<class>KWin::PresentWindowsEffectConfigForm</class>
|
||||
<widget class="QWidget" name="KWin::PresentWindowsEffectConfigForm" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>430</width>
|
||||
<height>306</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout" >
|
||||
<item row="0" column="0" >
|
||||
<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>Rearrange &duration:</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>rearrangeDurationSpin</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QSpinBox" name="rearrangeDurationSpin" >
|
||||
<property name="suffix" >
|
||||
<string> msec</string>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>5000</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>250</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2" >
|
||||
<widget class="QCheckBox" name="displayTitleBox" >
|
||||
<property name="text" >
|
||||
<string>Display window &titles</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2" >
|
||||
<widget class="QCheckBox" name="displayIconBox" >
|
||||
<property name="text" >
|
||||
<string>Display window &icons</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2" >
|
||||
<widget class="QCheckBox" name="switchingBox" >
|
||||
<property name="text" >
|
||||
<string>Use for window &switching</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" >
|
||||
<widget class="QLabel" name="label_3" >
|
||||
<property name="text" >
|
||||
<string>Layout mode:</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>layoutCombo</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" >
|
||||
<widget class="QComboBox" name="layoutCombo" >
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Natural</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Regular grid</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text" >
|
||||
<string>Flexible grid</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2" >
|
||||
<widget class="QGroupBox" name="groupBox_2" >
|
||||
<property name="title" >
|
||||
<string>Activation</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2" >
|
||||
<item row="5" 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>
|
||||
<item row="2" column="0" >
|
||||
<widget class="QLabel" name="label_2" >
|
||||
<property name="text" >
|
||||
<string>Active screen &edge (Current desktop):</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>screenEdgeCombo</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" >
|
||||
<widget class="QComboBox" name="screenEdgeCombo" />
|
||||
</item>
|
||||
<item row="0" column="0" >
|
||||
<widget class="QLabel" name="label_4" >
|
||||
<property name="text" >
|
||||
<string>Active screen &edge (All desktops):</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring>screenEdgeAllCombo</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QComboBox" name="screenEdgeAllCombo" />
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" >
|
||||
<widget class="QGroupBox" name="groupBox_3" >
|
||||
<property name="title" >
|
||||
<string>Natural Layout Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4" >
|
||||
<item row="5" column="0" >
|
||||
<widget class="QCheckBox" name="fillGapsBox" >
|
||||
<property name="text" >
|
||||
<string>Fill &gaps</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" >
|
||||
<spacer name="verticalSpacer" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0" >
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="0" >
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" >
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6" >
|
||||
<property name="text" >
|
||||
<string>Faster</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring></cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="accuracySlider" >
|
||||
<property name="minimum" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum" >
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="singleStep" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="pageStep" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value" >
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="tracking" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="invertedAppearance" >
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="invertedControls" >
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="tickPosition" >
|
||||
<enum>QSlider::TicksBelow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5" >
|
||||
<property name="text" >
|
||||
<string>Nicer</string>
|
||||
</property>
|
||||
<property name="buddy" >
|
||||
<cstring></cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</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>rearrangeDurationSpin</tabstop>
|
||||
<tabstop>displayTitleBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Loading…
Reference in a new issue