Tiling is here!

This commit merges the kwin-tiling branch. Ideally it shouldn't break anything and add a few features ;-)
It was applied as a patch. Do not attempt to merge the branch directly, it has a few issues.
This feature is currently experimental, although it hasn't crashed in quite a long time. It lacks some features and probably leaks some memory. Fixes will be on the way.

Season Of KDE 2009 project by Nikhil Marathe

svn path=/trunk/KDE/kdebase/workspace/; revision=1118677
This commit is contained in:
Nikhil Marathe 2010-04-25 16:43:14 +00:00
parent d6861e06e5
commit 5fc7e93d69
33 changed files with 2883 additions and 593 deletions

View file

@ -105,8 +105,25 @@ set(kwin_KDEINIT_SRCS
compositingprefs.cpp
desktoplayout.cpp
paintredirector.cpp
tile.cpp
tiling.cpp
tilinglayout.cpp
tilinglayoutfactory.cpp
# tiling layouts
# spiral
#tilinglayouts/spiral/spiralfactory.cpp
tilinglayouts/spiral/spiral.cpp
# columns
#tilinglayouts/columns/columnsfactory.cpp
tilinglayouts/columns/columns.cpp
# floating
tilinglayouts/floating/floating.cpp
)
add_subdirectory( tilinglayouts )
qt4_add_dbus_adaptor( kwin_KDEINIT_SRCS org.kde.KWin.xml workspace.h KWin::Workspace )

View file

@ -259,6 +259,9 @@ void Workspace::setActiveClient( Client* c, allowed_t )
updateColormap();
if( effects )
static_cast<EffectsHandlerImpl*>(effects)->windowActivated( active_client ? active_client->effectWindow() : NULL );
if( tilingMode() )
notifyWindowActivated( active_client );
--set_active_client_recursion;
}

View file

@ -895,6 +895,9 @@ void Client::minimize( bool avoid_animation )
if( effects && !avoid_animation ) // TODO: Shouldn't it tell effects at least about the change?
static_cast<EffectsHandlerImpl*>(effects)->windowMinimized( effectWindow());
// when tiling, request a rearrangement
workspace()->notifyWindowMinimizeToggled( this );
// Update states of all other windows in this group
if( clientGroup() )
clientGroup()->updateStates( this );
@ -911,9 +914,13 @@ void Client::unminimize( bool avoid_animation )
updateAllowedActions();
workspace()->updateMinimizedOfTransients( this );
updateWindowRules();
workspace()->updateAllTiles();
if( effects && !avoid_animation )
static_cast<EffectsHandlerImpl*>( effects )->windowUnminimized( effectWindow() );
// when tiling, request a rearrangement
workspace()->notifyWindowMinimizeToggled( this );
// Update states of all other windows in this group
if( clientGroup() )
clientGroup()->updateStates( this );

View file

@ -2155,6 +2155,7 @@ void Client::move( int x, int y, ForceGeometry_t force )
workspace()->checkActiveScreen( this );
workspace()->updateStackingOrder();
workspace()->checkUnredirect();
workspace()->notifyWindowMove( this, moveResizeGeom, initialMoveResizeGeom );
// client itself is not damaged
const QRect deco_rect = decorationRect().translated( geom.x(), geom.y() );
addWorkspaceRepaint( deco_rect_before_block );
@ -2807,15 +2808,56 @@ bool Client::startMoveResize()
void Client::finishMoveResize( bool cancel )
{
// store for notification
bool wasResize = isResize();
bool wasMove = isMove();
leaveMoveResize();
if( isElectricBorderMaximizing() )
if( workspace()->tilingMode() )
{
cancel = true;
if( wasResize )
workspace()->notifyWindowResizeDone( this, moveResizeGeom, initialMoveResizeGeom, cancel );
else if( wasMove )
workspace()->notifyWindowMoveDone( this, moveResizeGeom, initialMoveResizeGeom, cancel );
}
else
{
if( cancel )
setGeometry( initialMoveResizeGeom );
else
setGeometry( moveResizeGeom );
}
if( cancel )
setGeometry( initialMoveResizeGeom );
if( isElectricBorderMaximizing() )
{
cancel = true;
}
if( isElectricBorderMaximizing() )
{
switch( electricMode )
{
case ElectricMaximizeMode:
if( maximizeMode() == MaximizeFull )
setMaximize( false, false );
else
setMaximize( true, true );
workspace()->restoreElectricBorderSize( ElectricTop );
break;
case ElectricLeftMode:
setQuickTileMode( QuickTileLeft );
workspace()->restoreElectricBorderSize( ElectricLeft );
break;
case ElectricRightMode:
setQuickTileMode( QuickTileRight );
workspace()->restoreElectricBorderSize( ElectricRight );
break;
}
electricMaximizing = false;
workspace()->hideElectricBorderWindowOutline();
}
if( isElectricBorderMaximizing() )
{
switch( electricMode )
@ -2841,6 +2883,7 @@ void Client::finishMoveResize( bool cancel )
}
checkMaximizeGeometry();
// FRAME update();
Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd );
if( effects )
static_cast<EffectsHandlerImpl*>(effects)->windowUserMovedResized( effectWindow(), false, true );
@ -2999,6 +3042,11 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
bool update = false;
if( isResize())
{
// query layout for supported resize mode
if( workspace()->tilingMode() )
{
mode = workspace()->supportedTilingResizeMode( this, mode );
}
// first resize (without checking constrains), then snap, then check bounds, then check constrains
QRect orig = initialMoveResizeGeom;
Sizemode sizemode = SizemodeAny;
@ -3033,10 +3081,19 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
sizemode = SizemodeFixedW;
break;
case PositionCenter:
// exception for tiling
// Center means no resizing allowed
if( workspace()->tilingMode() )
{
finishMoveResize( false );
buttonDown = false;
return;
}
default:
abort();
break;
}
workspace()->notifyWindowResize( this, moveResizeGeom, initialMoveResizeGeom );
// adjust new size to snap to other windows/borders
moveResizeGeom = workspace()->adjustClientSize( this, moveResizeGeom, mode );
@ -3208,9 +3265,13 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
if( update )
performMoveResize();
if ( isMove() )
{
workspace()->notifyWindowMove( this, moveResizeGeom, initialMoveResizeGeom );
workspace()->checkElectricBorder(globalPos, xTime());
}
}
void Client::performMoveResize()
{
@ -3229,6 +3290,7 @@ void Client::performMoveResize()
if( rules()->checkMoveResizeMode
( isResize() ? options->resizeMode : options->moveMode ) == Options::Opaque )
{
if( !workspace()->tilingMode() )
setGeometry( moveResizeGeom );
positionGeometryTip();
}

View file

@ -66,6 +66,9 @@
#define KWIN_AUTOGROUP_FOREGROUND "AutogroupInForeground"
#define KWIN_SEPARATE_SCREEN_FOCUS "SeparateScreenFocus"
#define KWIN_ACTIVE_MOUSE_SCREEN "ActiveMouseScreen"
#define KWIN_TILINGON "TilingOn"
#define KWIN_TILING_DEFAULT_LAYOUT "TilingDefaultLayout"
#define KWIN_TILING_RAISE_POLICY "TilingRaisePolicy"
//CT 15mar 98 - magics
#define KWM_BRDR_SNAP_ZONE "BorderSnapZone"
@ -636,6 +639,54 @@ KAdvancedConfig::KAdvancedConfig (bool _standAlone, KConfig *_config, const KCom
connect(hideUtilityWindowsForInactive, SIGNAL(toggled(bool)), SLOT(changed()));
vLay->addWidget( hideUtilityWindowsForInactive, 1, 0, 1, 2 );
tilBox = new KButtonGroup(this);
tilBox->setTitle(i18n("Tiling"));
QGridLayout *tilBoxLay = new QGridLayout(tilBox);
tilingOn = new QCheckBox( i18n( "Enable Tiling" ), tilBox );
tilingOn->setWhatsThis(
i18n( "A tiling window manager lays out all the windows in a non-overlapping manner."
" This way all windows are always visible.") );
tilBoxLay->addWidget( tilingOn );
connect( tilingOn, SIGNAL( toggled(bool) ), SLOT( tilingOnChanged(bool) ) );
connect( tilingOn, SIGNAL( toggled(bool) ), SLOT( changed() ) );
tilingLayoutLabel = new QLabel( i18n("Default Tiling &Layout"), tilBox );
tilBoxLay->addWidget( tilingLayoutLabel, 1, 0 );
tilingLayoutCombo = new QComboBox( tilBox );
// NOTE: add your layout to the bottom of this list
tilingLayoutCombo->addItem( "Spiral" );
tilingLayoutCombo->addItem( "Columns" );
tilingLayoutCombo->addItem( "Floating" );
tilingLayoutLabel->setBuddy( tilingLayoutCombo );
connect( tilingLayoutCombo, SIGNAL( activated(int) ), SLOT( changed() ) );
tilBoxLay->addWidget( tilingLayoutCombo, 1, 1 );
tilingRaiseLabel = new QLabel( i18n("Floating &Windows Raising"), tilBox );
tilBoxLay->addWidget( tilingRaiseLabel, 2, 0 );
tilingRaiseCombo = new QComboBox( tilBox );
tilingRaiseCombo->addItem( i18nc( "Window Raising Policy", "Raise/Lower all floating windows" ) );
tilingRaiseCombo->addItem( i18nc( "Window Raising Policy", "Raise/Lower current window only") );
tilingRaiseCombo->addItem( i18nc( "Window Raising Policy", "Floating windows are always on top" ) );
wtstr = i18n("The window raising policy determines how floating windows are stacked"
" <ul>"
" <li><em>Raise/Lower all</em> will raise all floating windows when a"
" floating window is activated.</li>"
" <li><em>Raise/Lower current</em> will raise only the current window.</li>"
" <li><em>Floating windows on top</em> will always keep floating windows on top, even"
" when a tiled window is activated."
"</ul>") ;
tilingRaiseCombo->setWhatsThis( wtstr );
connect( tilingRaiseCombo, SIGNAL( activated(int) ), SLOT( changed() ) );
tilingRaiseLabel->setBuddy( tilingRaiseCombo );
tilBoxLay->addWidget( tilingRaiseCombo, 2, 1 );
lay->addWidget( tilBox );
lay->addStretch();
load();
@ -661,6 +712,24 @@ void KAdvancedConfig::shadeHoverChanged(bool a) {
shadeHover->setEnabled(a);
}
void KAdvancedConfig::setTilingOn( bool on ) {
tilingOn->setChecked( on );
}
void KAdvancedConfig::setTilingLayout( int l ) {
tilingLayoutCombo->setCurrentIndex( l );
}
void KAdvancedConfig::setTilingRaisePolicy( int l ) {
tilingRaiseCombo->setCurrentIndex( l );
}
void KAdvancedConfig::tilingOnChanged( bool a ) {
tilingLayoutLabel->setEnabled( a );
tilingLayoutCombo->setEnabled( a );
tilingRaiseLabel->setEnabled( a );
tilingRaiseCombo->setEnabled( a );
}
void KAdvancedConfig::showEvent( QShowEvent *ev )
{
@ -719,6 +788,10 @@ void KAdvancedConfig::load( void )
setAutogroupSimilarWindows( cg.readEntry( KWIN_AUTOGROUP_SIMILAR, false));
setAutogroupInForeground( cg.readEntry( KWIN_AUTOGROUP_FOREGROUND, true));
setTilingOn( cg.readEntry( KWIN_TILINGON, false ) );
setTilingLayout( cg.readEntry( KWIN_TILING_DEFAULT_LAYOUT, 0 ) );
setTilingRaisePolicy( cg.readEntry( KWIN_TILING_RAISE_POLICY, 0 ) );
emit KCModule::changed(false);
}
@ -769,6 +842,10 @@ void KAdvancedConfig::save( void )
QDBusConnection::sessionBus().send(message);
}
cg.writeEntry( KWIN_TILINGON, tilingOn->isChecked() );
cg.writeEntry( KWIN_TILING_DEFAULT_LAYOUT, tilingLayoutCombo->currentIndex() );
cg.writeEntry( KWIN_TILING_RAISE_POLICY, tilingRaiseCombo->currentIndex() );
emit KCModule::changed(false);
}
@ -778,6 +855,9 @@ void KAdvancedConfig::defaults()
setShadeHoverInterval(250);
setPlacement(SMART_PLACEMENT);
setHideUtilityWindowsForInactive( true );
setTilingOn( false );
setTilingLayout( 0 );
setTilingRaisePolicy( 0 );
setInactiveTabsSkipTaskbar( false );
setAutogroupSimilarWindows( false );
setAutogroupInForeground( true );

View file

@ -196,6 +196,7 @@ private slots:
void changed() { emit KCModule::changed(true); }
void tilingOnChanged( bool a );
private:
int getShadeHoverInterval (void );
@ -225,7 +226,21 @@ private:
int getPlacement( void ); //CT
void setPlacement(int); //CT
KComboBox *placementCombo;
// ------------------------------
// Tiling related widgets/methods
// ------------------------------
KButtonGroup *tilBox;
QCheckBox *tilingOn;
QLabel *tilingLayoutLabel;
QLabel *tilingRaiseLabel;
QComboBox *tilingLayoutCombo;
QComboBox *tilingRaiseCombo;
void setTilingOn( bool );
void setTilingLayout( int );
void setTilingRaisePolicy( int );
};
#endif // KKWMWINDOWS_H

View file

@ -103,6 +103,7 @@ RulesWidget::RulesWidget( QWidget* parent )
SETUP( autogroupid, force );
SETUP( opacityactive, force );
SETUP( opacityinactive, force );
SETUP( tilingoption, force );
SETUP( shortcut, force );
// workarounds tab
SETUP( fsplevel, force );
@ -153,6 +154,7 @@ UPDATE_ENABLE_SLOT( autogroupfg )
UPDATE_ENABLE_SLOT( autogroupid )
UPDATE_ENABLE_SLOT( opacityactive )
UPDATE_ENABLE_SLOT( opacityinactive )
UPDATE_ENABLE_SLOT( tilingoption )
void RulesWidget::updateEnableshortcut()
{
shortcut->setEnabled( enable_shortcut->isChecked() && rule_shortcut->currentIndex() != 0 );
@ -269,6 +271,16 @@ int RulesWidget::comboToDesktop( int val ) const
return val + 1;
}
int RulesWidget::tilingToCombo( int t ) const
{
return qBound(0, t, 1);
}
int RulesWidget::comboToTiling( int val ) const
{
return val; // 0 is tiling, 1 is floating
}
static int placementToCombo( Placement::Policy placement )
{
static const int conv[] =
@ -431,6 +443,7 @@ void RulesWidget::setRules( Rules* rules )
LINEEDIT_FORCE_RULE( autogroupid, );
LINEEDIT_FORCE_RULE( opacityactive, intToStr );
LINEEDIT_FORCE_RULE( opacityinactive, intToStr );
COMBOBOX_FORCE_RULE( tilingoption, tilingToCombo );
LINEEDIT_SET_RULE( shortcut, );
COMBOBOX_FORCE_RULE( fsplevel, );
COMBOBOX_FORCE_RULE( moveresizemode, moveresizeToCombo );
@ -524,6 +537,7 @@ Rules* RulesWidget::rules() const
LINEEDIT_FORCE_RULE( autogroupid, );
LINEEDIT_FORCE_RULE( opacityactive, strToInt );
LINEEDIT_FORCE_RULE( opacityinactive, strToInt );
COMBOBOX_FORCE_RULE( tilingoption, comboToTiling );
LINEEDIT_SET_RULE( shortcut, );
COMBOBOX_FORCE_RULE( fsplevel, );
COMBOBOX_FORCE_RULE( moveresizemode, comboToMoveResize );
@ -644,6 +658,7 @@ void RulesWidget::prefillUnusedValues( const KWindowInfo& info )
//LINEEDIT_PREFILL( autogroupid, );
LINEEDIT_PREFILL( opacityactive, intToStr, 100 /*get the actual opacity somehow*/);
LINEEDIT_PREFILL( opacityinactive, intToStr, 100 /*get the actual opacity somehow*/);
COMBOBOX_PREFILL( tilingoption, tilingToCombo, 0 );
//LINEEDIT_PREFILL( shortcut, );
//COMBOBOX_PREFILL( fsplevel, );
//COMBOBOX_PREFILL( moveresizemode, moveresizeToCombo );

View file

@ -77,6 +77,7 @@ class RulesWidget
void updateEnableautogroupid();
void updateEnableopacityactive();
void updateEnableopacityinactive();
void updateEnabletilingoption();
// workarounds tab
void updateEnablefsplevel();
void updateEnablemoveresizemode();
@ -92,6 +93,8 @@ class RulesWidget
private:
int desktopToCombo( int d ) const;
int comboToDesktop( int val ) const;
int tilingToCombo( int t ) const;
int comboToTiling( int val ) const;
void prefillUnusedValues( const KWindowInfo& info );
DetectDialog* detect_dlg;
bool detect_dlg_ok;

File diff suppressed because it is too large Load diff

View file

@ -6775,3 +6775,18 @@ Comment[x-test]=xxSome effects are not supported by backend or hardware.xx
Comment[zh_CN]=因为后端或硬件的关系,一些效果不受支持。
Comment[zh_TW]=有些效果未被後端介面或硬體支援。
Action=Popup
[Event/tilingenabled]
Name=Tiling Enabled
Comment=Tiling mode has been enabled
Action=Popup
[Event/tilingdisabled]
Name=Tiling Disabled
Comment=Tiling mode has been disabled
Action=Popup
[Event/tilinglayoutchanged]
Name=Tiling Layout Changed
Comment=Tiling Layout has been changed
Action=Popup

View file

@ -219,6 +219,28 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
DEF( I18N_NOOP("Block Global Shortcuts"), 0, slotDisableGlobalShortcuts());
DEF( I18N_NOOP("Suspend Compositing"), Qt::SHIFT+Qt::ALT+Qt::Key_F12, slotToggleCompositing());
a = actionCollection->addAction( "Group:Tiling" );
a->setText( i18n("Tiling") );
DEF( I18N_NOOP("Toggle Tiling"), Qt::SHIFT+Qt::ALT+Qt::Key_F11, slotToggleTiling() );
DEF( I18N_NOOP("Toggle Orientation"), Qt::META+Qt::Key_Space, slotToggleOrientation() );
DEF( I18N_NOOP("Increase Ratio"), Qt::META+Qt::Key_Right, slotTileIncreaseRatio() );
DEF( I18N_NOOP("Decrease Ratio"), Qt::META+Qt::Key_Left, slotTileDecreaseRatio() );
DEF( I18N_NOOP("Toggle Floating"), Qt::META+Qt::Key_F, slotToggleFloating() );
DEF( I18N_NOOP("Switch Focus Left") , Qt::META+Qt::Key_H, slotLeft() );
DEF( I18N_NOOP("Switch Focus Right") , Qt::META+Qt::Key_L, slotRight() );
DEF( I18N_NOOP("Switch Focus Up") , Qt::META+Qt::Key_K, slotTop() );
DEF( I18N_NOOP("Switch Focus Down") , Qt::META+Qt::Key_J, slotBottom() );
DEF( I18N_NOOP("Move Left") , Qt::SHIFT+Qt::META+Qt::Key_H, slotMoveLeft() );
DEF( I18N_NOOP("Move Right") , Qt::SHIFT+Qt::META+Qt::Key_L, slotMoveRight() );
DEF( I18N_NOOP("Move Up") , Qt::SHIFT+Qt::META+Qt::Key_K, slotMoveTop() );
DEF( I18N_NOOP("Move Down") , Qt::SHIFT+Qt::META+Qt::Key_J, slotMoveBottom() );
DEF( I18N_NOOP("Next Layout"), Qt::META+Qt::Key_PageDown, slotNextTileLayout() );
DEF( I18N_NOOP("Previous Layout"), Qt::META+Qt::Key_PageUp, slotPreviousTileLayout() );
// NOTE: temporary
DEF( I18N_NOOP("Test Dump tiles"), Qt::META+Qt::Key_D, dumpTiles() );
DEF( I18N_NOOP("Test Below Cursor"), Qt::META+Qt::Key_X, belowCursor() );
#undef DEF
#undef DEF2

View file

@ -124,6 +124,10 @@ unsigned long Options::updateSettings()
shadeHover = config.readEntry("ShadeHover", false);
shadeHoverInterval = config.readEntry("ShadeHoverInterval", 250 );
tilingOn = config.readEntry( "TilingOn", false );
tilingLayout = config.readEntry( "TilingDefaultLayout", 0 );
tilingRaisePolicy = config.readEntry( "TilingRaisePolicy", 0 );
// important: autoRaise implies ClickRaise
clickRaise = autoRaise || config.readEntry("ClickRaise", true);

View file

@ -116,6 +116,21 @@ class Options : public KDecorationOptions
*/
int shadeHoverInterval;
/**
* Whether tiling is enabled or not
*/
bool tilingOn;
/**
* Tiling Layout
*/
int tilingLayout;
/**
* Tiling window raise policy.
*/
int tilingRaisePolicy;
/**
Different Alt-Tab-Styles:
<ul>

View file

@ -69,5 +69,9 @@
<arg type="ai" direction="out"/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="QList&lt;int>"/>
</method>
<method name="toggleTiling"/>
<method name="nextTileLayout"/>
<method name="previousTileLayout"/>
<method name="dumpTiles"/>
</interface>
</node>

View file

@ -51,6 +51,7 @@ Rules::Rules()
, maxsizerule( UnusedForceRule )
, opacityactiverule( UnusedForceRule )
, opacityinactiverule( UnusedForceRule )
, tilingoptionrule( UnusedForceRule )
, ignorepositionrule( UnusedForceRule )
, desktoprule( UnusedSetRule )
, typerule( UnusedForceRule )
@ -153,6 +154,7 @@ void Rules::readFromCfg( const KConfigGroup& cfg )
READ_FORCE_RULE( opacityinactive,, 0);
if( opacityinactive < 0 || opacityinactive > 100 )
opacityinactive = 100;
READ_FORCE_RULE( tilingoption,, 0 );
READ_FORCE_RULE( ignoreposition,, false);
READ_SET_RULE( desktop,,0 );
type = readType( cfg, "type" );
@ -241,6 +243,7 @@ void Rules::write( KConfigGroup& cfg ) const
WRITE_FORCE_RULE( maxsize, );
WRITE_FORCE_RULE( opacityactive, );
WRITE_FORCE_RULE( opacityinactive, );
WRITE_FORCE_RULE( tilingoption, );
WRITE_FORCE_RULE( ignoreposition, );
WRITE_SET_RULE( desktop, );
WRITE_FORCE_RULE( type, int );
@ -280,6 +283,7 @@ bool Rules::isEmpty() const
&& maxsizerule == UnusedForceRule
&& opacityactiverule == UnusedForceRule
&& opacityinactiverule == UnusedForceRule
&& tilingoptionrule == UnusedForceRule
&& ignorepositionrule == UnusedForceRule
&& desktoprule == UnusedSetRule
&& typerule == UnusedForceRule
@ -576,6 +580,7 @@ APPLY_FORCE_RULE( maxsize, MaxSize, QSize )
APPLY_FORCE_RULE( opacityactive, OpacityActive, int )
APPLY_FORCE_RULE( opacityinactive, OpacityInactive, int )
APPLY_FORCE_RULE( ignoreposition, IgnorePosition, bool )
APPLY_FORCE_RULE( tilingoption, TilingOption, int )
// the cfg. entry needs to stay named the say for backwards compatibility
bool Rules::applyIgnoreGeometry( bool& ignore ) const
@ -672,6 +677,7 @@ void Rules::discardUsed( bool withdrawn )
DISCARD_USED_FORCE_RULE( maxsize );
DISCARD_USED_FORCE_RULE( opacityactive );
DISCARD_USED_FORCE_RULE( opacityinactive );
DISCARD_USED_FORCE_RULE( tilingoption );
DISCARD_USED_FORCE_RULE( ignoreposition );
DISCARD_USED_SET_RULE( desktop );
DISCARD_USED_FORCE_RULE( type );
@ -781,6 +787,7 @@ CHECK_FORCE_RULE( MinSize, QSize )
CHECK_FORCE_RULE( MaxSize, QSize )
CHECK_FORCE_RULE( OpacityActive, int )
CHECK_FORCE_RULE( OpacityInactive, int )
CHECK_FORCE_RULE( TilingOption, int )
CHECK_FORCE_RULE( IgnorePosition, bool )
bool WindowRules::checkIgnoreGeometry( bool ignore ) const

View file

@ -61,6 +61,7 @@ class WindowRules
QSize checkMaxSize( QSize s ) const;
int checkOpacityActive(int s) const;
int checkOpacityInactive(int s) const;
int checkTilingOption( int s ) const;
bool checkIgnoreGeometry( bool ignore ) const;
int checkDesktop( int desktop, bool init = false ) const;
NET::WindowType checkType( NET::WindowType type ) const;
@ -115,6 +116,7 @@ class Rules
bool applyMaxSize( QSize& s ) const;
bool applyOpacityActive(int& s) const;
bool applyOpacityInactive(int& s) const;
bool applyTilingOption( int& s ) const;
bool applyIgnoreGeometry( bool& ignore ) const;
bool applyDesktop( int& desktop, bool init ) const;
bool applyType( NET::WindowType& type ) const;
@ -214,6 +216,8 @@ class Rules
ForceRule opacityactiverule;
int opacityinactive;
ForceRule opacityinactiverule;
int tilingoption;
ForceRule tilingoptionrule;
bool ignoreposition;
ForceRule ignorepositionrule;
int desktop;

14
sm.cpp
View file

@ -82,6 +82,17 @@ void Workspace::storeSession( KConfig* config, SMSavePhase phase )
KConfigGroup cg(config, "Session");
int count = 0;
int active_client = -1;
if( phase == SMSavePhase2 || phase == SMSavePhase2Full )
{
cg.writeEntry( "tiling", tilingMode() );
if( tilingMode() )
{
kDebug(1212) << "Tiling was ON";
setTilingMode( false );
}
}
for (ClientList::Iterator it = clients.begin(); it != clients.end(); ++it)
{
Client* c = (*it);
@ -167,6 +178,9 @@ void Workspace::loadSessionInfo()
{
session.clear();
KConfigGroup cg(kapp->sessionConfig(), "Session");
setTilingMode( cg.readEntry( "tiling", false ) );
int count = cg.readEntry( "count",0 );
int active_client = cg.readEntry( "active",0 );
for ( int i = 1; i <= count; i++ )

152
tile.cpp Normal file
View file

@ -0,0 +1,152 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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 "tile.h"
#include <assert.h>
#include <QQueue>
#include "client.h"
#include "workspace.h"
namespace KWin
{
Tile::Tile( Client *c, const QRect& area)
: m_client(c),
m_floating(false)
{
setGeometry(area);
if( c )
{
m_prevGeom = c->geometry();
}
if( c && !c->isResizable() )
floatTile();
}
/*
* NOTE: Why isn't left/right/parent copied?
* Because they might be deleted at any point, so we can't keep pointers to them
* Also it doesn't make sense in the areas where copy is actually going to be used.
* Since we will be getting a new parent and children.
*/
Tile::Tile( const Tile& orig )
: m_client( orig.client() ),
m_floating( orig.floating() ),
m_prevGeom( orig.m_prevGeom )
{
setGeometry( orig.geometry() );
}
Tile::~Tile()
{
restorePreviousGeometry();
m_client = NULL;
}
void Tile::commit()
{
m_client->setGeometry(geometry(), ForceGeometrySet);
}
void Tile::setGeometry(int x, int y, int w, int h)
{
QRect old = m_geom;
m_geom.setTopLeft( QPoint(x, y) );
m_geom.setWidth( w );
m_geom.setHeight( h );
if( old == m_geom )
return;
if( floating() )
m_prevGeom = m_geom;
}
void Tile::floatTile()
{
if( floating() ) return;
// note, order of setting m_floating to true
// then calling restore is important
// childGeometryChanged will check for ignoreGeometry()
m_floating = true;
restorePreviousGeometry();
commit();
client()->workspace()->notifyWindowActivated( client() );
// TODO: notify layout manager
}
void Tile::unfloatTile()
{
if( !floating() ) return;
m_floating = false;
m_prevGeom = m_client->geometry();
setGeometry( m_client->workspace()->clientArea( PlacementArea, m_client ) );
commit();
// TODO: notify layout manager
}
void Tile::restorePreviousGeometry()
{
// why this check?
// sometimes we remove a Tile, but don't want to remove the children
// so the children are set to NULL. In this case leaf() will return
// true but m_client will still be null
if( !m_client ) return;
if( m_prevGeom.isNull() )
{
QRect area = m_client->workspace()->clientArea( PlacementArea, m_client );
m_client->workspace()->place( m_client, area );
}
else
{
m_client->setGeometry( m_prevGeom, ForceGeometrySet );
}
setGeometry( m_client->geometry() );
}
inline bool Tile::minimized() const
{
return m_client->isMinimized();
}
void Tile::focus()
{
m_client->workspace()->activateClient( m_client, true );
}
void Tile::dumpTile(const QString& indent ) const
{
kDebug(1212) << indent << m_client
<< ( floating() ? "floating" : "not floating" )
<< ( ignoreGeometry() ? "ignored" : "tiled" )
<< m_geom ;
}
}

125
tile.h Normal file
View file

@ -0,0 +1,125 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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_TILE_H
#define KWIN_TILE_H
#include <QRect>
#include <QString>
namespace KWin
{
class Client;
class Workspace;
class Tile
{
public:
enum Direction {
Top,
Right,
Bottom,
Left
};
enum LayoutMode {
UseRatio, // uses m_ratio
UseGeometry, // uses current geometry of children
Equal // distribute equally
};
Tile( Client *c, const QRect& area);
Tile(const Tile& orig);
virtual ~Tile();
void setGeometry(const QRect& area);
void setGeometry(int x, int y, int w, int h);
void resize( const QRect area );
void restorePreviousGeometry();
void commit();
void focus();
// :| the float datatype interferes with naming
void floatTile();
void unfloatTile();
bool minimized() const;
bool floating() const;
bool ignoreGeometry() const;
QRect geometry() const;
Client* client() const;
void dumpTile( const QString& indent = "" ) const;
private:
// -------------
// PROPERTIES
// -------------
// our client
Client *m_client;
// tiled geometry
QRect m_geom;
// before tiling was enabled, if any
QRect m_prevGeom;
bool m_floating;
};
inline QRect Tile::geometry() const
{
return m_geom;
}
inline Client* Tile::client() const
{
return m_client;
}
inline bool Tile::floating() const
{
return m_floating;
}
/*
* should be respected by all geometry modifying methods.
* It returns true if the Tile is 'out' of the layout,
* due to being minimized, floating or for some other reason.
*/
inline bool Tile::ignoreGeometry() const
{
return minimized() || floating();
}
inline void Tile::setGeometry(const QRect& area)
{
setGeometry(area.x(), area.y(), area.width(), area.height());
}
} // namespace
#endif

504
tiling.cpp Normal file
View file

@ -0,0 +1,504 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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/>.
*********************************************************************/
// all the tiling related code that is extensions to existing KWin classes
// Includes Workspace for now
#include "client.h"
#include "workspace.h"
#include "tile.h"
#include "tilinglayout.h"
#include "tilinglayoutfactory.h"
#include <knotification.h>
#include <klocale.h>
#include "lib/kdecoration.h"
namespace KWin
{
bool Workspace::tilingMode() const
{
return tilingMode_;
}
void Workspace::setTilingMode( bool tiling )
{
if( tilingMode() == tiling ) return;
tilingMode_ = tiling;
if( tilingMode_ )
{
tilingLayouts.resize( numberOfDesktops() + 1 );
foreach( Client *c, stackingOrder() )
{
createTile( c );
}
}
else
{
foreach( TilingLayout *t, tilingLayouts )
{
if( t )
delete t;
}
tilingLayouts.clear();
}
}
void Workspace::slotToggleTiling()
{
if ( tilingMode() )
{
setTilingMode( false );
QString message = i18n( "Tiling Disabled" );
KNotification::event( "tilingdisabled", message, QPixmap(), NULL, KNotification::CloseOnTimeout, KComponentData( "kwin" ) );
}
else
{
setTilingMode( true );
QString message = i18n( "Tiling Enabled" );
KNotification::event( "tilingenabled", message, QPixmap(), NULL, KNotification::CloseOnTimeout, KComponentData( "kwin" ) );
}
}
void Workspace::createTile( Client *c )
{
if( c == NULL ) return;
if( c->desktop() < 0 || c->desktop() >= tilingLayouts.size() ) return;
kDebug(1212) << "Now tiling " << c->caption();
if( !tilingMode() || !tileable(c) )
return;
Tile *t = new Tile( c, clientArea( PlacementArea, c ) );
if( !tileable( c ) )
{
kDebug(1212) << c->caption() << "is not tileable";
t->floatTile();
}
if( !tilingLayouts.value(c->desktop()) )
{
tilingLayouts[c->desktop()] = TilingLayoutFactory::createLayout( TilingLayoutFactory::DefaultL, this );
}
tilingLayouts[c->desktop()]->addTile( t );
tilingLayouts[c->desktop()]->commit();
}
void Workspace::removeTile( Client *c )
{
if( tilingLayouts[ c->desktop() ] )
tilingLayouts[ c->desktop() ]->removeTile( c );
}
bool Workspace::tileable( Client *c )
{
kDebug(1212) << c->caption();
// TODO: if application specific settings
// to ignore, put them here
// as suggested by Lucas Murray
// see Client::manage ( ~ line 270 of manage.cpp at time of writing )
// This is useful to ignore plasma widget placing.
// According to the ICCCM if an application
// or user requests a certain geometry
// respect it
long msize;
XSizeHints xSizeHint;
XGetWMNormalHints(display(), c->window(), &xSizeHint, &msize);
if( xSizeHint.flags & PPosition ||
xSizeHint.flags & USPosition ) {
kDebug(1212) << "Not tileable due to USPosition requirement";
return false;
}
kDebug(1212) << "c->isNormalWindow()" << c->isNormalWindow() ;
kDebug(1212) << "c->isUtility() " << c->isUtility() ;
kDebug(1212) << "c->isDialog() " << c->isDialog() ;
kDebug(1212) << "c->isSplash() " << c->isSplash() ;
kDebug(1212) << "c->isToolbar() " << c->isToolbar() ;
kDebug(1212) << "c->isPopupMenu() " << c->isPopupMenu() ;
kDebug(1212) << "c->isTransient() " << c->isTransient() ;
if( !c->isNormalWindow() ||
c->isUtility() ||
c->isDialog() ||
c->isSplash() ||
c->isToolbar() ||
c->isPopupMenu() ||
c->isTransient() )
{
return false;
}
return true;
}
void Workspace::belowCursor()
{
// TODO
}
Tile* Workspace::getNiceTile() const
{
if( !tilingMode() ) return NULL;
if( !tilingLayouts.value( activeClient()->desktop() ) ) return NULL;
return tilingLayouts[ activeClient()->desktop() ]->findTile( activeClient() );
// TODO
}
void Workspace::updateAllTiles()
{
foreach( TilingLayout *t, tilingLayouts )
{
if( !t ) continue;
t->commit();
}
}
/*
* Resize the neighbouring clients to close any gaps
*/
void Workspace::notifyWindowResize( Client *c, const QRect &moveResizeGeom, const QRect &orig )
{
if( tilingLayouts.value( c->desktop() ) == NULL )
return;
tilingLayouts[ c->desktop() ]->clientResized( c, moveResizeGeom, orig );
}
void Workspace::notifyWindowMove( Client *c, const QRect &moveResizeGeom, const QRect &orig )
{
if( tilingLayouts.value( c->desktop() ) == NULL )
{
c->setGeometry( moveResizeGeom );
return;
}
tilingLayouts[ c->desktop() ]->clientMoved( c, moveResizeGeom, orig );
updateAllTiles();
}
void Workspace::notifyWindowResizeDone( Client *c, const QRect &moveResizeGeom, const QRect &orig, bool canceled )
{
if( canceled )
notifyWindowResize( c, orig, moveResizeGeom );
else
notifyWindowResize( c, moveResizeGeom, orig );
}
void Workspace::notifyWindowMoveDone( Client *c, const QRect &moveResizeGeom, const QRect &orig, bool canceled )
{
if( canceled )
notifyWindowMove( c, orig, moveResizeGeom );
else
notifyWindowMove( c, moveResizeGeom, orig );
}
void Workspace::notifyWindowDesktopChanged( Client *c, int old_desktop )
{
if( c->desktop() < 1 || c->desktop() > numberOfDesktops() )
return;
if( tilingLayouts.value( old_desktop ) )
{
Tile *t = tilingLayouts[ old_desktop ]->findTile( c );
// TODO: copied from createTile(), move this into separate method?
if( !tilingLayouts.value( c->desktop() ) )
{
tilingLayouts[c->desktop()] = TilingLayoutFactory::createLayout( TilingLayoutFactory::DefaultL, this );
}
if( t )
tilingLayouts[ c->desktop() ]->addTile( t );
tilingLayouts[ old_desktop ]->removeTile( c );
tilingLayouts[ old_desktop ]->commit();
}
}
// TODO: make this configurable
/*
* If a floating window was activated, raise all floating windows.
* If a tiled window was activated, lower all floating windows.
*/
void Workspace::notifyWindowActivated( Client *c )
{
if( c == NULL )
return;
if( options->tilingRaisePolicy == 1 ) // individual raise/lowers
return;
if( tilingLayouts.value( c->desktop() ) )
{
QList<Tile *> tiles = tilingLayouts[ c->desktop() ]->tiles();
StackingUpdatesBlocker blocker( this );
Tile *tile_to_raise = tilingLayouts[ c->desktop() ]->findTile( c );
if( !tile_to_raise )
{
return;
}
kDebug(1212) << "FOUND TILE";
bool raise_floating = false;
if( options->tilingRaisePolicy == 2 ) // floating always on top
raise_floating = true;
else
raise_floating = tile_to_raise->floating();
foreach( Tile *t, tiles )
{
kDebug(1212) << t->client() << t->floating();
if( t->floating() == raise_floating && t != tile_to_raise )
raiseClient( t->client() );
}
// raise the current tile last so that it ends up on top
// but only if it supposed to be raised, required to support tilingRaisePolicy
kDebug(1212) << "Raise floating? " << raise_floating << "to raise is floating?" << tile_to_raise->floating();
if( tile_to_raise->floating() == raise_floating )
raiseClient( tile_to_raise->client() );
}
}
void Workspace::notifyWindowMinimizeToggled( Client *c )
{
if( tilingLayouts.value( c->desktop() ) )
{
tilingLayouts[ c->desktop() ]->clientMinimizeToggled( c );
}
}
void Workspace::notifyWindowMaximized( Client *c, Options::WindowOperation op )
{
if( tilingLayouts.value( c->desktop() ) )
{
Tile *t = tilingLayouts[ c->desktop() ]->findTile( c );
if( !t )
{
createTile( c );
t = tilingLayouts[ c->desktop() ]->findTile( c );
// if still no tile, it couldn't be tiled
// so ignore it
if( !t )
return;
}
// if window IS tiled and a maximize
// is attempted, make the window float.
// That is all we do since that can
// mess up the layout.
// In all other cases, don't do
// anything, let the user manage toggling
// using Meta+F
if ( !t->floating()
&& ( op == Options::MaximizeOp
|| op == Options::HMaximizeOp
|| op == Options::VMaximizeOp ) )
{
tilingLayouts[ c->desktop() ]->toggleFloatTile( c );
}
}
}
Tile* Workspace::findAdjacentTile( Tile *ref, int d )
{
QRect reference = ref->geometry();
QPoint origin = reference.center();
Tile *closest = NULL;
int minDist = -1;
QList<Tile *> tiles = tilingLayouts[ ref->client()->desktop() ]->tiles();
foreach( Tile *t, tiles )
{
if( t->client() == ref->client() || t->ignoreGeometry() )
continue;
bool consider = false;
QRect other = t->geometry();
QPoint otherCenter = other.center();
switch( d )
{
case Tile::Top:
consider = otherCenter.y() < origin.y()
&& other.bottom() < reference.top();
break;
case Tile::Right:
consider = otherCenter.x() > origin.x()
&& other.left() > reference.right();
break;
case Tile::Bottom:
consider = otherCenter.y() > origin.y()
&& other.top() > reference.bottom();
break;
case Tile::Left:
consider = otherCenter.x() < origin.x()
&& other.right() < reference.left();
break;
default:
abort();
}
if( consider )
{
int dist = ( otherCenter - origin ).manhattanLength();
if( minDist > dist || minDist < 0 )
{
minDist = dist;
closest = t;
}
}
}
return closest;
}
void Workspace::focusTile( int d )
{
Tile *t = getNiceTile();
if( t )
{
Tile *adj = findAdjacentTile(t, d);
if( adj )
activateClient( adj->client() );
}
}
void Workspace::moveTile( int d )
{
Tile *t = getNiceTile();
if( t )
{
Tile* adj = findAdjacentTile( t, d );
tilingLayouts[ t->client()->desktop() ]->swapTiles( t, adj );
}
}
void Workspace::slotLeft()
{
focusTile( Tile::Left );
}
void Workspace::slotRight()
{
focusTile( Tile::Right );
}
void Workspace::slotTop()
{
focusTile( Tile::Top );
}
void Workspace::slotBottom()
{
focusTile( Tile::Bottom );
}
void Workspace::slotMoveLeft()
{
moveTile( Tile::Left );
}
void Workspace::slotMoveRight()
{
moveTile( Tile::Right );
}
void Workspace::slotMoveTop()
{
moveTile( Tile::Top );
}
void Workspace::slotMoveBottom()
{
moveTile( Tile::Bottom );
}
void Workspace::slotToggleFloating()
{
Client *c = activeClient();
if( tilingLayouts.value( c->desktop() ) )
{
tilingLayouts[ c->desktop() ]->toggleFloatTile( c );
}
}
void Workspace::slotNextTileLayout()
{
if( tilingLayouts.value( currentDesktop() ) )
{
tilingLayouts.replace( currentDesktop(), TilingLayoutFactory::nextLayout( tilingLayouts[currentDesktop()] ) );
tilingLayouts[currentDesktop()]->commit();
}
}
void Workspace::slotPreviousTileLayout()
{
if( tilingLayouts.value( currentDesktop() ) )
{
tilingLayouts.replace( currentDesktop(), TilingLayoutFactory::previousLayout( tilingLayouts[currentDesktop()] ) );
tilingLayouts[currentDesktop()]->commit();
}
}
KDecorationDefines::Position Workspace::supportedTilingResizeMode( Client *c, KDecorationDefines::Position currentMode )
{
if( tilingLayouts.value( c->desktop() ) )
{
return tilingLayouts[c->desktop()]->resizeMode( c, currentMode );
}
return currentMode;
}
void Workspace::dumpTiles() const
{
foreach( TilingLayout *t, tilingLayouts )
{
if( !t ) {
kDebug(1212) << "EMPTY DESKTOP";
continue;
}
kDebug(1212) << "Desktop" << tilingLayouts.indexOf( t );
foreach( Tile *tile, t->tiles() )
{
tile->dumpTile( "--" );
}
}
}
} // namespace

218
tilinglayout.cpp Normal file
View file

@ -0,0 +1,218 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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 "tilinglayout.h"
#include <QCursor>
#include "client.h"
#include "tile.h"
#include "workspace.h"
namespace KWin
{
TilingLayout::TilingLayout( Workspace *w )
: m_workspace( w )
{
}
TilingLayout::~TilingLayout()
{
}
unsigned int TilingLayout::findTilePos( Client *c ) const
{
unsigned int i = 0;
foreach( Tile *t, m_tiles )
{
if( t->client() == c )
return i;
i++;
}
return -1;
}
Tile* TilingLayout::findTile( Client *c ) const
{
unsigned int i = findTilePos( c );
if( i != -1 )
return m_tiles[ i ];
return NULL;
}
void TilingLayout::clientMinimizeToggled( Client *c )
{
Tile *t = findTile( c );
if( t )
arrange( layoutArea( t ) );
}
void TilingLayout::clientResized( Client *c, const QRect &moveResizeGeom, const QRect &orig )
{
if( moveResizeGeom == orig )
return;
Tile *t = findTile( c );
if( !t || t->ignoreGeometry() )
{
c->setGeometry( moveResizeGeom );
return;
}
t->setGeometry( moveResizeGeom );
commit();
}
void TilingLayout::clientMoved( Client *c, const QRect &moveResizeGeom, const QRect &orig )
{
if( moveResizeGeom == orig )
return;
Tile *t = findTile( c );
if( !t )
{
c->setGeometry( moveResizeGeom );
return;
}
if( t->floating() )
{
t->setGeometry( moveResizeGeom );
t->commit();
return;
}
Tile *r = findTileBelowPoint( QCursor::pos() );
// TODO: if the client moved in from another desktop, don't swap, add
if( r && t )
{
swapTiles( r, t );
}
}
void TilingLayout::swapTiles( Tile *a, Tile *b )
{
if( a && b )
{
// t is the tile the user requested a move of
// r is the tile below it
int a_index = tiles().indexOf( a );
int b_index = tiles().indexOf( b );
// use m_tiles since tiles() is const
// not sure how good an idea this is
m_tiles.replace( a_index, b );
m_tiles.replace( b_index, a );
arrange( layoutArea( a ) );
}
}
void TilingLayout::addTileNoArrange( Tile * t )
{
m_tiles.append( t );
postAddTile( t );
}
void TilingLayout::addTile( Tile *t )
{
addTileNoArrange( t );
arrange( layoutArea( t ) );
}
void TilingLayout::addTile( Client *c )
{
}
void TilingLayout::removeTileNoArrange( Tile * t )
{
if( t == NULL )
return;
preRemoveTile( t );
m_tiles.removeOne( t );
}
const QRect TilingLayout::layoutArea( Tile *t ) const
{
return m_workspace->clientArea( PlacementArea, t->client() );
}
void TilingLayout::removeTile( Tile *t )
{
if( t == NULL )
return;
removeTileNoArrange( t );
arrange( layoutArea( t ) );
}
void TilingLayout::removeTile( Client *c )
{
removeTile( findTile( c ) );
}
void TilingLayout::toggleFloatTile( Client *c )
{
Tile *t = findTile( c );
if( t && t->floating() )
t->unfloatTile();
else if( t )
t->floatTile();
if( t )
arrange( layoutArea( t ) );
}
Tile* TilingLayout::findTileBelowPoint( const QPoint &p ) const
{
foreach( Tile *t, tiles() )
{
if( t->floating() )
continue;
if( t->geometry().contains( p ) )
return t;
}
return NULL;
}
void TilingLayout::commit()
{
foreach( Tile *t, m_tiles )
t->commit();
}
/*
* Default is to allow no resizing
*/
KDecorationDefines::Position TilingLayout::resizeMode( Client *c, KDecorationDefines::Position currentMode ) const
{
Tile *t = findTile( c );
// if not tiled, allow resize
if( !t )
return currentMode;
if( t && t->floating() )
return currentMode;
// We return PositionCenter since it makes
// no sense in resizing.
return KDecorationDefines::PositionCenter;
}
} // end namespace

118
tilinglayout.h Normal file
View file

@ -0,0 +1,118 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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_TILINGLAYOUT_H
#define KWIN_TILINGLAYOUT_H
#include <QRect>
#include <QList>
#include "lib/kdecoration.h"
namespace KWin
{
class Workspace;
class Client;
class Tile;
class TilingLayout
{
public:
TilingLayout( Workspace *w );
virtual ~TilingLayout();
virtual void clientResized( Client *c, const QRect &moveResizeGeom, const QRect &orig );
void clientMoved( Client *c, const QRect &moveResizeGeom, const QRect &orig );
void clientMinimizeToggled( Client *c );
void commit();
void setLayoutType( int t );
int layoutType() const;
void addTile( Tile *t );
void addTile( Client *c );
void removeTile( Tile *t );
void removeTile( Client *c );
void toggleFloatTile( Client *c );
void swapTiles( Tile *a, Tile *b );
virtual KDecorationDefines::Position resizeMode( Client *c, KDecorationDefines::Position currentMode ) const;
const QList<Tile *>& tiles() const;
Tile* findTile( Client *c ) const;
protected:
Workspace * workspace() const;
const QRect layoutArea( Tile *t ) const;
// currently only required by floating layout
virtual void postAddTile( Tile *t );
virtual void preRemoveTile( Tile *t );
private:
unsigned int findTilePos( Client *c ) const;
virtual void arrange( QRect wgeom ) = 0;
void addTileNoArrange( Tile *t );
void removeTileNoArrange( Tile *t );
Tile* findTileBelowPoint( const QPoint &p ) const;
QList<Tile *> m_tiles;
int m_layoutType;
Workspace *m_workspace;
friend class TilingLayoutFactory;
};
inline void TilingLayout::setLayoutType( int t )
{
m_layoutType = t;
}
inline int TilingLayout::layoutType() const
{
return m_layoutType;
}
inline const QList<Tile *>& TilingLayout::tiles() const
{
return m_tiles;
}
inline Workspace* TilingLayout::workspace() const
{
return m_workspace;
}
inline void TilingLayout::postAddTile( Tile *t )
{
}
inline void TilingLayout::preRemoveTile( Tile *t )
{
}
} // end namespace
#endif

126
tilinglayoutfactory.cpp Normal file
View file

@ -0,0 +1,126 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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 "tilinglayoutfactory.h"
#include <QtGlobal>
#include <QList>
#include <knotification.h>
#include <klocale.h>
#include <kdebug.h>
#include "tile.h"
#include "client.h"
#include "tilinglayouts/spiral/spiral.h"
#include "tilinglayouts/columns/columns.h"
#include "tilinglayouts/floating/floating.h"
// w is the workspace pointer
#define ADD_LAYOUT( lay ) \
case lay##L:\
kDebug(1212) << #lay;\
layout = new lay( w );\
layout->setLayoutType( lay##L );\
KNotification::event( "tilinglayoutchanged", \
i18n( "Layout changed to %1" ).arg( #lay ),\
QPixmap(), NULL, KNotification::CloseOnTimeout, KComponentData( "kwin" ) );\
break
namespace KWin
{
TilingLayout* TilingLayoutFactory::createLayout( int type, Workspace *w )
{
Q_ASSERT( type != First && type != Last );
TilingLayout *layout;
/* For new layouts, make a case entry here */
switch( type )
{
case DefaultL: // NOTE: fall through makes first layout default
layout = createLayout( indexToLayoutIndex( options->tilingLayout ), w );
break;
ADD_LAYOUT( Spiral );
ADD_LAYOUT( Columns );
ADD_LAYOUT( Floating );
default:
kDebug(1212) << "INVALID LAYOUT!";
return NULL;
}
return layout;
}
// if next, goes next, otherwise previous
TilingLayout* TilingLayoutFactory::cycleLayout( TilingLayout *curr, bool next )
{
int type = curr->layoutType();
if( next )
{
type++;
if( type >= Last )
type = First + 1;
}
else
{
type--;
if( type <= First )
type = Last - 1;
}
QList<Tile *> tiles = curr->tiles(); //root->flatten();
TilingLayout *l = createLayout( type, curr->workspace() );
foreach( Tile *t, tiles )
{
curr->removeTileNoArrange( t );
}
Tile *last = tiles.takeLast();
foreach( Tile *t, tiles )
{
l->addTileNoArrange( t );
}
l->addTile( last );
return l;
}
/**
* Returns the appropriate layout enum item
* Meant to be used with a combo box.
* This function handles the issues of DefaultL and First and Last layouts
*/
int TilingLayoutFactory::indexToLayoutIndex( int index )
{
int layout = DefaultL + index + 1;
if( layout >= Last )
layout = DefaultL + 1;
if( layout <= First )
layout = Last - 1;
return layout;
}
} // end namespace

71
tilinglayoutfactory.h Normal file
View file

@ -0,0 +1,71 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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_TILINGLAYOUTFACTORY_H
#define KWIN_TILINGLAYOUTFACTORY_H
namespace KWin
{
class Workspace;
class TilingLayout;
class Tile;
class TilingLayoutFactory
{
public:
/** When adding your own layout, edit this
* Remember to suffix an L for now
*/
enum Layouts {
First, // special, do not modify/move
DefaultL,
/* Actual layouts */
SpiralL,
ColumnsL,
FloatingL,
/* Put your layout above this line ^^^ */
Last // special, do not modify/move
};
static TilingLayout* createLayout( int type, Workspace * );
static TilingLayout* nextLayout( TilingLayout *curr );
static TilingLayout* previousLayout( TilingLayout *curr );
static int indexToLayoutIndex( int index );
private:
static TilingLayout* cycleLayout( TilingLayout *curr, bool next );
};
inline TilingLayout* TilingLayoutFactory::nextLayout( TilingLayout *curr )
{
return cycleLayout( curr, true );
}
inline TilingLayout* TilingLayoutFactory::previousLayout( TilingLayout *curr )
{
return cycleLayout( curr, false );
}
} // end namespace
#endif

View file

@ -0,0 +1,162 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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 "columns.h"
#include "client.h"
#include "tile.h"
#include "lib/kdecoration.h"
namespace KWin
{
// TODO: caching of actually tiled windows
// Columns is doing a lot of looping
// checking which tiles are actually *tiled*
// ( ie. not floating or minimized )
// This can probably be moved to TilingLayout
// and cached. But remember to preserve order!
Columns::Columns( Workspace *w )
: TilingLayout( w )
, m_leftWidth( 0 )
{
}
KDecorationDefines::Position Columns::resizeMode( Client *c, KDecorationDefines::Position currentMode ) const
{
Tile *t = findTile( c );
if( !t )
return currentMode;
if( t && t->floating() )
return currentMode;
QList<Tile *> tiled( tiles() );
QMutableListIterator<Tile *> i(tiled);
while( i.hasNext() )
{
Tile *tile = i.next();
if( tile->ignoreGeometry() )
i.remove();
}
if( tiled.first() == t
&& ( currentMode == KDecorationDefines::PositionRight
|| currentMode == KDecorationDefines::PositionTopRight
|| currentMode == KDecorationDefines::PositionBottomRight ) )
{
return KDecorationDefines::PositionRight;
}
// in right column so only left resize allowed
if( tiled.contains( t )
&& ( tiled.first() != t )
&& ( currentMode == KDecorationDefines::PositionLeft
|| currentMode == KDecorationDefines::PositionTopLeft
|| currentMode == KDecorationDefines::PositionBottomLeft ) )
{
return KDecorationDefines::PositionLeft;
}
return KDecorationDefines::PositionCenter;
}
void Columns::clientResized( Client *c, const QRect &moveResizeGeom, const QRect &orig )
{
TilingLayout::clientResized( c, moveResizeGeom, orig );
Tile *t = findTile( c );
QList<Tile *> tiled( tiles() );
QMutableListIterator<Tile *> i(tiled);
while( i.hasNext() )
{
Tile *tile = i.next();
if( tile->ignoreGeometry() )
i.remove();
}
if( tiled.first() == t )
{
m_leftWidth = moveResizeGeom.width();
}
else
{
m_leftWidth = layoutArea( t ).width() - moveResizeGeom.width();
}
arrange( layoutArea( t ) );
}
void Columns::arrange( QRect wgeom )
{
QList<Tile *> tiled( tiles() );
QMutableListIterator<Tile *> i(tiled);
while( i.hasNext() )
{
Tile *t = i.next();
if( t->ignoreGeometry() )
i.remove();
}
int n = tiled.length();
if( n < 1 )
return;
if( n == 1 )
{
tiled.first()->setGeometry( wgeom );
tiled.first()->commit();
return;
}
// save the original before we mangle it
int totalWidth = wgeom.width();
if( m_leftWidth == 0 )
m_leftWidth = wgeom.width() / 2;
if( n > 1 )
wgeom.setWidth( m_leftWidth );
tiled.first()->setGeometry( wgeom );
tiled.first()->commit();
wgeom.moveLeft( wgeom.x() + m_leftWidth );
wgeom.setWidth( totalWidth - m_leftWidth );
int ht = wgeom.height()/(n-1);
wgeom.setHeight( ht );
int mult = 0;
int originalTop = wgeom.y();
for( QList<Tile *>::const_iterator it = ++tiled.begin() ; it != tiled.end() ; it++ )
{
if( (*it)->floating() )
continue;
(*it)->setGeometry( wgeom );
(*it)->commit();
mult++;
wgeom.moveTop( originalTop + mult*ht );
}
}
}

View file

@ -0,0 +1,49 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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 COLUMNS_H
#define COLUMNS_H
#include <Qt>
#include "tilinglayout.h"
namespace KWin
{
class Workspace;
class Tile;
class Client;
// simulates a 2 column right layout for now, make it arbitrary
// in columns and direction
class Columns : public TilingLayout
{
public:
Columns( Workspace * );
KDecorationDefines::Position resizeMode( Client *c, KDecorationDefines::Position currentMode ) const;
void clientResized( Client *c, const QRect &moveResizeGeom, const QRect &orig );
private:
void arrange( QRect wgeom );
int m_leftWidth; // width of left column
};
} // end namespace
#endif

View file

@ -0,0 +1,61 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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 "floating.h"
#include "tile.h"
#include "client.h"
namespace KWin
{
Floating::Floating( Workspace *w )
: TilingLayout( w )
{
}
void Floating::postAddTile( Tile *t )
{
if( t->floating() )
was_floating.insert( t );
}
void Floating::arrange( QRect wgeom )
{
foreach( Tile *t, tiles() )
{
if( !t->floating() )
t->floatTile();
workspace()->place( t->client(), wgeom );
t->setGeometry( t->client()->geometry() );
}
}
void Floating::preRemoveTile( Tile *t )
{
if( ! was_floating.contains( t ) )
t->unfloatTile();
}
Floating::~Floating()
{
}
}

View file

@ -0,0 +1,59 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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 FLOATING_H
#define FLOATING_H
#include <Qt>
#include <QSet>
#include "tilinglayout.h"
#include "tile.h"
namespace KWin
{
class Workspace;
class Floating : public TilingLayout
{
public:
Floating( Workspace * );
~Floating();
private:
void arrange( QRect wgeom );
void postAddTile( Tile *t );
void preRemoveTile( Tile *t );
Tile::Direction m_dir;
Tile *m_split;
/*
* Tiles are added to was_floating if they
* were floating before being added to this layout
*
* When the layout is changed, was_floating is
* referred to, to restore the final state of the
* Tile
*/
QSet<Tile *> was_floating;
};
} // end namespace
#endif

View file

@ -0,0 +1,82 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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 "spiral.h"
#include "client.h"
#include "tile.h"
namespace KWin
{
Spiral::Spiral( Workspace *w )
: TilingLayout( w )
{
}
Spiral::~Spiral()
{
}
void Spiral::arrange( QRect wgeom )
{
QList<Tile *> tiled( tiles() );
QMutableListIterator<Tile *> it(tiled);
while( it.hasNext() )
{
Tile *t = it.next();
if( t->ignoreGeometry() )
it.remove();
}
int n = tiled.length();
int i = 1;
foreach( Tile *t, tiled )
{
if( t->floating() )
continue;
if( i < n )
{
if( i % 2 == 0 )
wgeom.setHeight( wgeom.height() / 2 );
else
wgeom.setWidth( wgeom.width() / 2 );
}
if( i % 4 == 0 )
wgeom.moveLeft( wgeom.x() - wgeom.width() );
else if( i % 2 == 0 || ( i % 4 == 3 && i < n ) )
wgeom.moveLeft( wgeom.x() + wgeom.width() );
if( i % 4 == 1 && i != 1 )
wgeom.moveTop( wgeom.y() - wgeom.height() );
else if( i % 2 == 1 && i != 1
|| ( i % 4 == 0 && i < n ) )
wgeom.moveTop( wgeom.y() + wgeom.height() );
t->setGeometry( wgeom );
t->commit();
i++;
}
}
}

View file

@ -0,0 +1,49 @@
/********************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2009 Nikhil Marathe <nsm.nikhil@gmail.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 SPIRAL_H
#define SPIRAL_H
#include <Qt>
#include "tilinglayout.h"
namespace KWin
{
class Workspace;
class Tile;
class Client;
class Spiral : public TilingLayout
{
public:
Spiral( Workspace * );
~Spiral();
void addTile( Tile *t );
void removeTile( Tile *t );
private:
void arrange( QRect wgeom );
};
} // end namespace
#endif

View file

@ -668,6 +668,15 @@ void Workspace::performWindowOperation( Client* c, Options::WindowOperation op )
if ( !c )
return;
if( tilingMode()
&& ( op == Options::MaximizeOp
|| op == Options::HMaximizeOp
|| op == Options::VMaximizeOp
|| op == Options::RestoreOp ) )
{
notifyWindowMaximized( c, op );
}
if (op == Options::MoveOp || op == Options::UnrestrictedMoveOp )
QCursor::setPos( c->geometry().center() );
if (op == Options::ResizeOp || op == Options::UnrestrictedResizeOp )

View file

@ -44,6 +44,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <QtDBus/QtDBus>
#include "client.h"
#include "tile.h"
#include "tabbox.h"
#include "desktopchangeosd.h"
#include "atoms.h"
@ -56,6 +57,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "scene.h"
#include "deleted.h"
#include "effects.h"
#include "tilinglayout.h"
#include <X11/extensions/shape.h>
#include <X11/keysym.h>
@ -151,6 +153,7 @@ Workspace::Workspace( bool restore )
, transSlider( NULL )
, transButton( NULL )
, forceUnredirectCheck( true )
, tilingMode_( false )
{
(void) new KWinAdaptor( this );
@ -469,6 +472,9 @@ void Workspace::init()
outline_bottom = XCreateWindow( QX11Info::display(), QX11Info::appRootWindow(), 0, 0, 1, 1, 0,
CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attr );
// Enable/disable tiling
setTilingMode( options->tilingOn );
// SELI TODO: This won't work with unreasonable focus policies,
// and maybe in rare cases also if the selected client doesn't
// want focus
@ -550,6 +556,11 @@ Client* Workspace::createClient( Window w, bool is_mapped )
return NULL;
}
addClient( c, Allowed );
tilingLayouts.resize( numberOfDesktops() + 1 );
createTile( c );
if( scene )
scene->windowAdded( c );
if( effects )
@ -649,6 +660,11 @@ void Workspace::removeClient( Client* c, allowed_t )
tab_box->nextPrev( true );
Q_ASSERT( clients.contains( c ) || desktops.contains( c ));
if( tilingMode() && tilingLayouts.value(c->desktop()) )
{
removeTile( c );
}
// TODO: if marked client is removed, notify the marked list
clients.removeAll( c );
desktops.removeAll( c );
unconstrained_stacking_order.removeAll( c );
@ -1134,6 +1150,10 @@ void Workspace::slotReconfigure()
(*it)->applyWindowRules();
discardUsedWindowRules( *it, false );
}
setTilingMode( options->tilingOn );
// just so that we reset windows in the right manner, 'activate' the current active window
notifyWindowActivated( activeClient() );
rootInfo->setSupported( NET::WM2FrameOverlap, mgr->factory()->supports( AbilityExtendIntoClientArea ) );
}
@ -1398,7 +1418,14 @@ bool Workspace::setCurrentDesktop( int new_desktop )
rootInfo->setCurrentDesktop( currentDesktop() );
if( movingClient && !movingClient->isOnDesktop( new_desktop ))
{
int old_desktop = movingClient->desktop();
movingClient->setDesktop( new_desktop );
if( tilingMode() )
{
notifyWindowDesktopChanged( movingClient, old_desktop );
}
}
for( int i = stacking_order.size() - 1; i >= 0 ; --i )
if( stacking_order.at( i )->isOnDesktop( new_desktop ))
@ -1532,6 +1559,7 @@ void Workspace::setNumberOfDesktops( int n )
++it)
if( !(*it)->isOnAllDesktops() && (*it)->desktop() > numberOfDesktops() )
sendClientToDesktop( *it, numberOfDesktops(), true );
// TODO: Tile should have a method allClients, push them into other tiles
}
if( old_number_of_desktops > numberOfDesktops() )
{
@ -1550,6 +1578,8 @@ void Workspace::setNumberOfDesktops( int n )
for( int i = 0; i < int( desktop_focus_chain.size() ); i++ )
desktop_focus_chain[i] = i+1;
tilingLayouts.resize( numberOfDesktops() + 1 );
// reset the desktop change osd
desktop_change_osd->numberDesktopsChanged();
// inform effects
@ -1564,6 +1594,7 @@ void Workspace::setNumberOfDesktops( int n )
*/
void Workspace::sendClientToDesktop( Client* c, int desk, bool dont_activate )
{
int old_desktop = c->desktop();
bool was_on_desktop = c->isOnDesktop( desk ) || c->isOnAllDesktops();
c->setDesktop( desk );
if( c->desktop() != desk ) // No change or desktop forced
@ -1582,6 +1613,8 @@ void Workspace::sendClientToDesktop( Client* c, int desk, bool dont_activate )
else
raiseClient( c );
notifyWindowDesktopChanged( c, old_desktop );
ClientList transients_stacking_order = ensureStackingOrder( c->transients() );
for( ClientList::ConstIterator it = transients_stacking_order.constBegin();
it != transients_stacking_order.constEnd();

View file

@ -61,6 +61,8 @@ class TabBox;
}
class Client;
class Tile;
class TilingLayout;
class ClientGroup;
class DesktopChangeOSD;
class RootInfo;
@ -169,6 +171,23 @@ class Workspace : public QObject, public KDecorationDefines
void reserveElectricBorderActions( bool reserve );
void reserveElectricBorderSwitching( bool reserve );
//-------------------------------------------------
// Tiling
public:
bool tilingMode() const;
void setTilingMode( bool tiling );
void updateAllTiles();
void notifyWindowResize( Client *c, const QRect &moveResizeGeom, const QRect &orig );
void notifyWindowMove( Client *c, const QRect &moveResizeGeom, const QRect &orig );
void notifyWindowResizeDone( Client *c, const QRect &moveResizeGeom, const QRect &orig, bool canceled );
void notifyWindowMoveDone( Client *c, const QRect &moveResizeGeom, const QRect &orig, bool canceled );
void notifyWindowDesktopChanged( Client *c, int old_desktop );
void notifyWindowActivated( Client *c );
void notifyWindowMinimizeToggled( Client *c );
void notifyWindowMaximized( Client *c, WindowOperation op );
Position supportedTilingResizeMode( Client *c, Position currentMode );
//-------------------------------------------------
// Desktop layout
@ -286,6 +305,9 @@ class Workspace : public QObject, public KDecorationDefines
int currentDesktop_;
bool desktopLayoutDynamicity_;
bool tilingMode_;
QVector<TilingLayout *> tilingLayouts;
//-------------------------------------------------
// Unsorted
@ -396,6 +418,9 @@ class Workspace : public QObject, public KDecorationDefines
void circulateDesktopApplications();
bool compositingActive();
bool waitForCompositingSetup();
void toggleTiling();
void nextTileLayout();
void previousTileLayout();
void setCurrentScreen( int new_screen );
@ -652,6 +677,24 @@ class Workspace : public QObject, public KDecorationDefines
void suspendCompositing();
void suspendCompositing( bool suspend );
void slotToggleTiling();
void slotToggleFloating();
void slotNextTileLayout();
void slotPreviousTileLayout();
void slotLeft();
void slotRight();
void slotTop();
void slotBottom();
void slotMoveLeft();
void slotMoveRight();
void slotMoveTop();
void slotMoveBottom();
void belowCursor();
// NOTE: debug method
void dumpTiles() const;
void slotSwitchToTabLeft(); // Slot to move left the active Client.
void slotSwitchToTabRight(); // Slot to move right the active Client.
void slotRemoveFromGroup(); // Slot to remove the active client from its group.
@ -799,6 +842,16 @@ class Workspace : public QObject, public KDecorationDefines
static NET::WindowType txtToWindowType( const char* txt );
static bool sessionInfoWindowTypeMatch( Client* c, SessionInfo* info );
Tile* getNiceTile() const;
void createTile( Client *c );
void removeTile( Client *c );
bool tileable( Client *c );
// int, and not Tile::Direction because
// we are using a forward declaration for Tile
Tile* findAdjacentTile( Tile *ref, int d );
void focusTile( int d );
void moveTile( int d );
Client* active_client;
Client* last_active_client;
Client* most_recently_raised; // Used ONLY by raiseOrLowerClient()
@ -1276,6 +1329,30 @@ inline void Workspace::removeClientGroup( ClientGroup* group )
clientGroups.removeAll( group );
}
/*
* Called from D-BUS
*/
inline void Workspace::toggleTiling()
{
slotToggleTiling();
}
/*
* Called from D-BUS
*/
inline void Workspace::nextTileLayout()
{
slotNextTileLayout();
}
/*
* Called from D-BUS
*/
inline void Workspace::previousTileLayout()
{
slotPreviousTileLayout();
}
} // namespace
#endif