summaryrefslogtreecommitdiffstats
path: root/opensuse/core/tdebase/xinerama.patch
diff options
context:
space:
mode:
Diffstat (limited to 'opensuse/core/tdebase/xinerama.patch')
-rw-r--r--opensuse/core/tdebase/xinerama.patch951
1 files changed, 951 insertions, 0 deletions
diff --git a/opensuse/core/tdebase/xinerama.patch b/opensuse/core/tdebase/xinerama.patch
new file mode 100644
index 000000000..41aedbcba
--- /dev/null
+++ b/opensuse/core/tdebase/xinerama.patch
@@ -0,0 +1,951 @@
+Index: kdesktop/minicli.cpp
+===================================================================
+--- kdesktop/minicli.cpp.orig
++++ kdesktop/minicli.cpp
+@@ -379,6 +379,17 @@ int Minicli::runCommand()
+ cmd = uri.path();
+ else
+ cmd = uri.url();
++
++ QCString asn;
++ if( qApp->desktop()->isVirtualDesktop())
++ {
++ asn = KStartupInfo::createNewStartupId();
++ KStartupInfoId id;
++ id.initId( asn );
++ KStartupInfoData data;
++ data.setXinerama( qApp->desktop()->screenNumber( this ));
++ KStartupInfo::sendChange( id, data );
++ }
+
+ // Determine whether the application should be run through
+ // the command line (terminal) interface...
+@@ -514,7 +525,7 @@ int Minicli::runCommand()
+ case KURIFilterData::HELP:
+ {
+ // No need for kfmclient, KRun does it all (David)
+- (void) new KRun( m_filterData->uri(), parentWidget());
++ (void) new KRun( m_filterData->uri(), parentWidget(), asn );
+ return 0;
+ }
+ case KURIFilterData::EXECUTABLE:
+@@ -526,7 +537,7 @@ int Minicli::runCommand()
+ if (service && service->isValid() && service->type() == "Application")
+ {
+ notifyServiceStarted(service);
+- KRun::run(*service, KURL::List());
++ KRun::run(*service, KURL::List(), parentWidget(), asn );
+ return 0;
+ }
+ }
+@@ -561,7 +572,7 @@ int Minicli::runCommand()
+ if (service && service->isValid() && service->type() == "Application")
+ {
+ notifyServiceStarted(service);
+- KRun::run(*service, KURL::List(), this);
++ KRun::run(*service, KURL::List(), parentWidget(), asn );
+ return 0;
+ }
+
+@@ -569,7 +580,7 @@ int Minicli::runCommand()
+ if (service && service->isValid() && service->type() == "Application")
+ {
+ notifyServiceStarted(service);
+- KRun::run(*service, KURL::List(), this);
++ KRun::run(*service, KURL::List(), parentWidget(), asn );
+ return 0;
+ }
+
+@@ -581,7 +592,7 @@ int Minicli::runCommand()
+ }
+ }
+
+- if ( KRun::runCommand( cmd, exec, m_iconName ) )
++ if ( KRun::runCommand( cmd, exec, m_iconName, parentWidget(), asn ) )
+ return 0;
+ else
+ {
+Index: kdesktop/desktop.cc
+===================================================================
+--- kdesktop/desktop.cc.orig
++++ kdesktop/desktop.cc
+@@ -520,9 +520,12 @@ void KDesktop::popupExecuteCommand(const
+ if ( m_miniCli->isVisible() ) {
+ KWin::forceActiveWindow( m_miniCli->winId() );
+ } else {
+- QRect rect = KGlobalSettings::desktopGeometry(QCursor::pos());
+- m_miniCli->move(rect.x() + (rect.width() - m_miniCli->width())/2,
+- rect.y() + (rect.height() - m_miniCli->height())/2);
++ NETRootInfo i( qt_xdisplay(), NET::Supported );
++ if( !i.isSupported( NET::WM2FullPlacement )) {
++ QRect rect = KGlobalSettings::desktopGeometry(QCursor::pos());
++ m_miniCli->move(rect.x() + (rect.width() - m_miniCli->width())/2,
++ rect.y() + (rect.height() - m_miniCli->height())/2);
++ }
+ m_miniCli->show(); // non-modal
+ }
+ }
+Index: kwin/useractions.cpp
+===================================================================
+--- kwin/useractions.cpp.orig
++++ kwin/useractions.cpp
+@@ -482,27 +482,33 @@ bool Client::performMouseCommand( Option
+ case Options::MouseActivateAndRaise:
+ replay = isActive(); // for clickraise mode
+ workspace()->takeActivity( this, ActivityFocus | ActivityRaise, handled && replay );
++ workspace()->setActiveScreenMouse( globalPos );
+ break;
+ case Options::MouseActivateAndLower:
+ workspace()->requestFocus( this );
+ workspace()->lowerClient( this );
++ workspace()->setActiveScreenMouse( globalPos );
+ break;
+ case Options::MouseActivate:
+ replay = isActive(); // for clickraise mode
+ workspace()->takeActivity( this, ActivityFocus, handled && replay );
++ workspace()->setActiveScreenMouse( globalPos );
+ break;
+ case Options::MouseActivateRaiseAndPassClick:
+ workspace()->takeActivity( this, ActivityFocus | ActivityRaise, handled );
++ workspace()->setActiveScreenMouse( globalPos );
+ replay = TRUE;
+ break;
+ case Options::MouseActivateAndPassClick:
+ workspace()->takeActivity( this, ActivityFocus, handled );
++ workspace()->setActiveScreenMouse( globalPos );
+ replay = TRUE;
+ break;
+ case Options::MouseActivateRaiseAndMove:
+ case Options::MouseActivateRaiseAndUnrestrictedMove:
+ workspace()->raiseClient( this );
+ workspace()->requestFocus( this );
++ workspace()->setActiveScreenMouse( globalPos );
+ if( options->moveMode == Options::Transparent && isMovable())
+ move_faked_activity = workspace()->fakeRequestedActivity( this );
+ // fallthrough
+@@ -709,6 +715,40 @@ void Workspace::slotWindowToDesktop( int
+ sendClientToDesktop( c, i, true );
+ }
+
++void Workspace::slotSwitchToScreen( int i )
++ {
++ setCurrentScreen( i );
++ }
++
++void Workspace::slotSwitchToNextScreen()
++ {
++ slotSwitchToScreen(( activeScreen() + 1 ) % numScreens());
++ }
++
++void Workspace::slotWindowToScreen( int i )
++ {
++ Client* c = active_popup_client ? active_popup_client : active_client;
++ if( i >= 0 && i <= numScreens() && c
++ && !c->isDesktop()
++ && !c->isDock()
++ && !c->isTopMenu())
++ {
++ sendClientToScreen( c, i );
++ }
++ }
++
++void Workspace::slotWindowToNextScreen()
++ {
++ Client* c = active_popup_client ? active_popup_client : active_client;
++ if( c
++ && !c->isDesktop()
++ && !c->isDock()
++ && !c->isTopMenu())
++ {
++ sendClientToScreen( c, ( c->screen() + 1 ) % numScreens());
++ }
++ }
++
+ /*!
+ Maximizes the popup client
+ */
+Index: kwin/options.h
+===================================================================
+--- kwin/options.h.orig
++++ kwin/options.h
+@@ -124,6 +124,11 @@ class Options : public KDecorationOption
+ */
+ enum AltTabStyle { KDE, CDE };
+ AltTabStyle altTabStyle;
++
++ // whether to see Xinerama screens separately for focus (in Alt+Tab, when activating next client)
++ bool separateScreenFocus;
++ // whether active Xinerama screen is the one with mouse (or with the active window)
++ bool activeMouseScreen;
+
+ /**
+ * Xinerama options
+@@ -133,6 +138,9 @@ class Options : public KDecorationOption
+ bool xineramaMovementEnabled;
+ bool xineramaMaximizeEnabled;
+ bool xineramaFullscreenEnabled;
++
++ // number, or -1 = active screen (Workspace::activeScreen())
++ int xineramaPlacementScreen;
+
+ /**
+ MoveResizeMode, either Tranparent or Opaque.
+Index: kwin/workspace.h
+===================================================================
+--- kwin/workspace.h.orig
++++ kwin/workspace.h
+@@ -91,6 +91,7 @@ class Workspace : public QObject, public
+
+ QRect clientArea( clientAreaOption, const QPoint& p, int desktop ) const;
+ QRect clientArea( clientAreaOption, const Client* c ) const;
++ QRect clientArea( clientAreaOption, int screen, int desktop ) const;
+
+ /**
+ * @internal
+@@ -161,6 +162,13 @@ class Workspace : public QObject, public
+ */
+ int numberOfDesktops() const;
+ void setNumberOfDesktops( int n );
++
++ int activeScreen() const;
++ int numScreens() const;
++ void checkActiveScreen( const Client* c );
++ void setActiveScreenMouse( QPoint mousepos );
++ QRect screenGeometry( int screen ) const;
++ int screenNumber( QPoint pos ) const;
+
+ QWidget* desktopWidget();
+
+@@ -186,6 +194,7 @@ class Workspace : public QObject, public
+ void sendClientToDesktop( Client* c, int desktop, bool dont_activate );
+ void windowToPreviousDesktop( Client* c );
+ void windowToNextDesktop( Client* c );
++ void sendClientToScreen( Client* c, int screen );
+
+ // KDE4 remove me - and it's also in the DCOP interface :(
+ void showWindowMenuAt( unsigned long id, int x, int y );
+@@ -224,6 +233,7 @@ class Workspace : public QObject, public
+ void nextDesktop();
+ void previousDesktop();
+ void circulateDesktopApplications();
++ void setCurrentScreen( int new_screen );
+
+ QString desktopName( int desk ) const;
+ virtual void setDesktopLayout(int , int , int );
+@@ -301,6 +311,10 @@ class Workspace : public QObject, public
+ //void slotSwitchToWindow( int );
+ void slotWindowToDesktop( int );
+ //void slotWindowToListPosition( int );
++ void slotSwitchToScreen( int );
++ void slotWindowToScreen( int );
++ void slotSwitchToNextScreen();
++ void slotWindowToNextScreen();
+
+ void slotWindowMaximize();
+ void slotWindowMaximizeVertical();
+@@ -481,6 +495,7 @@ class Workspace : public QObject, public
+ int current_desktop;
+ int number_of_desktops;
+ QMemArray<int> desktop_focus_chain;
++ int active_screen;
+
+ QWidget* active_popup;
+ Client* active_popup_client;
+Index: kwin/tabbox.cpp
+===================================================================
+--- kwin/tabbox.cpp.orig
++++ kwin/tabbox.cpp
+@@ -23,7 +23,6 @@ License. See the file "COPYING" for the
+ #include <klocale.h>
+ #include <qapplication.h>
+ #include <qdesktopwidget.h>
+-#include <qcursor.h>
+ #include <kstringhandler.h>
+ #include <stdarg.h>
+ #include <kdebug.h>
+@@ -110,26 +109,36 @@ void TabBox::createClientList(ClientList
+
+ while ( c )
+ {
++ Client* add = NULL;
+ if ( ((desktop == -1) || c->isOnDesktop(desktop))
+ && c->wantsTabFocus() )
++ { // don't add windows that have modal dialogs
++ Client* modal = c->findModal();
++ if( modal == NULL || modal == c )
++ add = c;
++ else if( !list.contains( modal ))
++ add = modal;
++ else
++ {
++ // nothing
++ }
++ }
++
++ if( options->separateScreenFocus && options->xineramaEnabled )
+ {
+- if ( start == c )
++ if( c->screen() != workspace()->activeScreen())
++ add = NULL;
++ }
++
++ if( add != NULL )
++ {
++ if ( start == add )
+ {
+- list.remove( c );
+- list.prepend( c );
++ list.remove( add );
++ list.prepend( add );
+ }
+ else
+- { // don't add windows that have modal dialogs
+- Client* modal = c->findModal();
+- if( modal == NULL || modal == c )
+- list += c;
+- else if( !list.contains( modal ))
+- list += modal;
+- else
+- {
+- // nothing
+- }
+- }
++ list += add;
+ }
+
+ if ( chain )
+@@ -156,7 +165,7 @@ void TabBox::reset()
+ {
+ int w, h, cw = 0, wmax = 0;
+
+- QRect r = KGlobalSettings::desktopGeometry(QCursor::pos());
++ QRect r = workspace()->screenGeometry( workspace()->activeScreen());
+
+ // calculate height of 1 line
+ // fontheight + 1 pixel above + 1 pixel below, or 32x32 icon + 2 pixel above + below
+Index: kwin/kcmkwin/kwinoptions/windows.h
+===================================================================
+--- kwin/kcmkwin/kwinoptions/windows.h.orig
++++ kwin/kcmkwin/kwinoptions/windows.h
+@@ -86,6 +86,7 @@ private slots:
+ void delayFocusOnTog(bool);
+ void clickRaiseOnTog(bool);
+ void updateAltTabMode();
++ void updateActiveMouseScreen();
+ void changed() { emit KCModule::changed(true); }
+
+
+@@ -101,6 +102,8 @@ private:
+ void setDelayFocusInterval(int);
+ void setDelayFocus(bool);
+ void setClickRaise(bool);
++ void setSeparateScreenFocus(bool);
++ void setActiveMouseScreen(bool);
+ void setAltTabMode(bool);
+ void setTraverseAll(bool);
+ void setRollOverDesktops(bool);
+@@ -113,6 +116,8 @@ private:
+ QCheckBox *clickRaiseOn;
+ KIntNumInput *autoRaise;
+ KIntNumInput *delayFocus;
++ QCheckBox *separateScreenFocus;
++ QCheckBox *activeMouseScreen;
+
+ QButtonGroup *kbdBox;
+ QCheckBox *altTabPopup;
+Index: kwin/kcmkwin/kwinoptions/windows.cpp
+===================================================================
+--- kwin/kcmkwin/kwinoptions/windows.cpp.orig
++++ kwin/kcmkwin/kwinoptions/windows.cpp
+@@ -76,6 +76,8 @@
+ #define KWIN_SHADEHOVER_INTERVAL "ShadeHoverInterval"
+ #define KWIN_FOCUS_STEALING "FocusStealingPreventionLevel"
+ #define KWIN_HIDE_UTILITY "HideUtilityWindowsForInactive"
++#define KWIN_SEPARATE_SCREEN_FOCUS "SeparateScreenFocus"
++#define KWIN_ACTIVE_MOUSE_SCREEN "ActiveMouseScreen"
+
+ // kwm config keywords
+ #define KWM_ELECTRIC_BORDER "ElectricBorders"
+@@ -209,6 +211,27 @@ KFocusConfig::KFocusConfig (bool _standA
+ QWhatsThis::add( delayFocus, i18n("This is the delay after which the window the mouse pointer is over"
+ " will automatically receive focus.") );
+
++ separateScreenFocus = new QCheckBox( i18n( "S&eparate screen focus" ), fcsBox );
++ fLay->addWidget( separateScreenFocus );
++ wtstr = i18n( "When this option is enabled, focus operations are limited only to the active Xinerama screen" );
++ QWhatsThis::add( separateScreenFocus, wtstr );
++
++ activeMouseScreen = new QCheckBox( i18n( "Active &mouse screen" ), fcsBox );
++ fLay->addWidget( activeMouseScreen );
++ wtstr = i18n( "When this option is enabled, active Xinerama screen (where for example new windows appear)"
++ " is the screen with the mouse pointer. When disabled, the active Xinerama screen is the screen"
++ " with the focused window. This option is by default disabled for Click to focus and"
++ " enabled for other focus policies." );
++ QWhatsThis::add( activeMouseScreen, wtstr );
++ connect(focusCombo, SIGNAL(activated(int)), this, SLOT(updateActiveMouseScreen()));
++
++ if (!QApplication::desktop()->isVirtualDesktop() ||
++ QApplication::desktop()->numScreens() == 1) // No Ximerama
++ {
++ separateScreenFocus->hide();
++ activeMouseScreen->hide();
++ }
++
+ lay->addWidget(fcsBox);
+
+ kbdBox = new QButtonGroup(i18n("Navigation"), this);
+@@ -260,6 +283,8 @@ KFocusConfig::KFocusConfig (bool _standA
+ connect(fcsBox, SIGNAL(clicked(int)), SLOT(changed()));
+ connect(autoRaise, SIGNAL(valueChanged(int)), SLOT(changed()));
+ connect(delayFocus, SIGNAL(valueChanged(int)), SLOT(changed()));
++ connect(separateScreenFocus, SIGNAL(clicked()), SLOT(changed()));
++ connect(activeMouseScreen, SIGNAL(clicked()), SLOT(changed()));
+ connect(altTabPopup, SIGNAL(clicked()), SLOT(changed()));
+ connect(traverseAll, SIGNAL(clicked()), SLOT(changed()));
+ connect(rollOverDesktops, SIGNAL(clicked()), SLOT(changed()));
+@@ -366,6 +391,22 @@ void KFocusConfig::delayFocusOnTog(bool
+ void KFocusConfig::clickRaiseOnTog(bool ) {
+ }
+
++void KFocusConfig::setSeparateScreenFocus(bool s) {
++ separateScreenFocus->setChecked(s);
++}
++
++void KFocusConfig::setActiveMouseScreen(bool a) {
++ activeMouseScreen->setChecked(a);
++}
++
++void KFocusConfig::updateActiveMouseScreen()
++{
++ // on by default for non click to focus policies
++ KConfigGroup cfg( config, "Windows" );
++ if( !cfg.hasKey( KWIN_ACTIVE_MOUSE_SCREEN ))
++ setActiveMouseScreen( focusCombo->currentItem() != 0 );
++}
++
+ void KFocusConfig::setAltTabMode(bool a) {
+ altTabPopup->setChecked(a);
+ }
+@@ -412,6 +453,10 @@ void KFocusConfig::load( void )
+ setClickRaise(key != "off");
+ setAutoRaiseEnabled(); // this will disable/hide the auto raise delay widget if focus==click
+ setDelayFocusEnabled();
++
++ setSeparateScreenFocus( config->readBoolEntry(KWIN_SEPARATE_SCREEN_FOCUS, false));
++ // on by default for non click to focus policies
++ setActiveMouseScreen( config->readBoolEntry(KWIN_ACTIVE_MOUSE_SCREEN, focusCombo->currentItem() != 0 ));
+
+ key = config->readEntry(KWIN_ALTTABMODE, "KDE");
+ setAltTabMode(key == "KDE");
+@@ -467,6 +512,9 @@ void KFocusConfig::save( void )
+ else
+ config->writeEntry(KWIN_CLICKRAISE, "off");
+
++ config->writeEntry(KWIN_SEPARATE_SCREEN_FOCUS, separateScreenFocus->isChecked());
++ config->writeEntry(KWIN_ACTIVE_MOUSE_SCREEN, activeMouseScreen->isChecked());
++
+ if (altTabPopup->isChecked())
+ config->writeEntry(KWIN_ALTTABMODE, "KDE");
+ else
+@@ -500,6 +548,9 @@ void KFocusConfig::defaults()
+ setAutoRaise(false);
+ setDelayFocus(false);
+ setClickRaise(true);
++ setSeparateScreenFocus( false );
++ // on by default for non click to focus policies
++ setActiveMouseScreen( focusCombo->currentItem() != 0 );
+ setAltTabMode(true);
+ setTraverseAll( false );
+ setRollOverDesktops(true);
+Index: kwin/popupinfo.h
+===================================================================
+--- kwin/popupinfo.h.orig
++++ kwin/popupinfo.h
+@@ -24,7 +24,7 @@ class PopupInfo : public QWidget
+ {
+ Q_OBJECT
+ public:
+- PopupInfo( const char *name=0 );
++ PopupInfo( Workspace* ws, const char *name=0 );
+ ~PopupInfo();
+
+ void reset();
+@@ -43,6 +43,7 @@ class PopupInfo : public QWidget
+ bool m_show;
+ bool m_shown;
+ QString m_infoString;
++ Workspace* workspace;
+ };
+
+ } // namespace
+Index: kwin/options.cpp
+===================================================================
+--- kwin/options.cpp.orig
++++ kwin/options.cpp
+@@ -71,6 +71,9 @@ unsigned long Options::updateSettings()
+ altTabStyle = KDE; // what a default :-)
+ if ( val == "CDE" )
+ altTabStyle = CDE;
++
++ separateScreenFocus = config->readBoolEntry( "SeparateScreenFocus", false );
++ activeMouseScreen = config->readBoolEntry( "ActiveMouseScreen", focusPolicy != ClickToFocus );
+
+ rollOverDesktops = config->readBoolEntry("RollOverDesktops", TRUE);
+
+@@ -91,9 +94,10 @@ unsigned long Options::updateSettings()
+ delete gc;
+
+ placement = Placement::policyFromString( config->readEntry("Placement"), true );
++ xineramaPlacementScreen = KCLAMP( config->readNumEntry( "XineramaPlacementScreen", -1 ),
++ -1, qApp->desktop()->numScreens() - 1 );
+
+ animateShade = config->readBoolEntry("AnimateShade", TRUE );
+-
+ animateMinimize = config->readBoolEntry("AnimateMinimize", TRUE );
+ animateMinimizeSpeed = config->readNumEntry("AnimateMinimizeSpeed", 5 );
+
+Index: kwin/placement.cpp
+===================================================================
+--- kwin/placement.cpp.orig
++++ kwin/placement.cpp
+@@ -473,7 +473,7 @@ void Placement::placeOnMainWindow(Client
+ it != mainwindows.end();
+ ++it )
+ {
+- if( (*it)->isSpecialWindow())
++ if( mainwindows.count() > 1 && (*it)->isSpecialWindow())
+ continue; // don't consider toolbars etc when placing
+ ++mains_count;
+ place_on2 = *it;
+@@ -502,6 +502,11 @@ void Placement::placeOnMainWindow(Client
+ }
+ place_on = place_on2; // use the only window filtered together with 'mains_count'
+ }
++ if( place_on->isDesktop())
++ {
++ place( c, area, Centered );
++ return;
++ }
+ QRect geom = c->geometry();
+ geom.moveCenter( place_on->geometry().center());
+ c->move( geom.topLeft());
+Index: kwin/client.cpp
+===================================================================
+--- kwin/client.cpp.orig
++++ kwin/client.cpp
+@@ -1255,6 +1255,20 @@ bool Client::isOnCurrentDesktop() const
+ return isOnDesktop( workspace()->currentDesktop());
+ }
+
++int Client::screen() const
++ {
++ if( !options->xineramaEnabled )
++ return 0;
++ return workspace()->screenNumber( geometry().center());
++ }
++
++bool Client::isOnScreen( int screen ) const
++ {
++ if( !options->xineramaEnabled )
++ return screen == 0;
++ return workspace()->screenGeometry( screen ).intersects( geometry());
++ }
++
+ // performs activation and/or raising of the window
+ void Client::takeActivity( int flags, bool handled, allowed_t )
+ {
+Index: kwin/popupinfo.cpp
+===================================================================
+--- kwin/popupinfo.cpp.orig
++++ kwin/popupinfo.cpp
+@@ -25,7 +25,6 @@ License. See the file "COPYING" for the
+ #include <klocale.h>
+ #include <qapplication.h>
+ #include <qdesktopwidget.h>
+-#include <qcursor.h>
+ #include <kstringhandler.h>
+ #include <kglobalsettings.h>
+
+@@ -34,8 +33,8 @@ License. See the file "COPYING" for the
+ namespace KWinInternal
+ {
+
+-PopupInfo::PopupInfo( const char *name )
+- : QWidget( 0, name )
++PopupInfo::PopupInfo( Workspace* ws, const char *name )
++ : QWidget( 0, name ), workspace( ws )
+ {
+ m_infoString = "";
+ m_shown = false;
+@@ -60,7 +59,7 @@ PopupInfo::~PopupInfo()
+ */
+ void PopupInfo::reset()
+ {
+- QRect r = KGlobalSettings::desktopGeometry(QCursor::pos());
++ QRect r = workspace->screenGeometry( workspace->activeScreen());
+
+ int w = fontMetrics().width( m_infoString ) + 30;
+
+Index: kwin/geometry.cpp
+===================================================================
+--- kwin/geometry.cpp.orig
++++ kwin/geometry.cpp
+@@ -211,14 +211,11 @@ void Workspace::updateClientArea()
+
+ \sa geometry()
+ */
+-QRect Workspace::clientArea( clientAreaOption opt, const QPoint& p, int desktop ) const
++QRect Workspace::clientArea( clientAreaOption opt, int screen, int desktop ) const
+ {
+ if( desktop == NETWinInfo::OnAllDesktops || desktop == 0 )
+ desktop = currentDesktop();
+ QDesktopWidget *desktopwidget = KApplication::desktop();
+- int screen = desktopwidget->isVirtualDesktop() ? desktopwidget->screenNumber( p ) : desktopwidget->primaryScreen();
+- if( screen < 0 )
+- screen = desktopwidget->primaryScreen();
+ QRect sarea = screenarea // may be NULL during KWin initialization
+ ? screenarea[ desktop ][ screen ]
+ : desktopwidget->screenGeometry( screen );
+@@ -263,11 +260,21 @@ QRect Workspace::clientArea( clientAreaO
+ return QRect();
+ }
+
++QRect Workspace::clientArea( clientAreaOption opt, const QPoint& p, int desktop ) const
++ {
++ QDesktopWidget *desktopwidget = KApplication::desktop();
++ int screen = desktopwidget->screenNumber( p );
++ if( screen < 0 )
++ screen = desktopwidget->primaryScreen();
++ return clientArea( opt, screen, desktop );
++ }
++
+ QRect Workspace::clientArea( clientAreaOption opt, const Client* c ) const
+ {
+ return clientArea( opt, c->geometry().center(), c->desktop());
+ }
+
++
+ /*!
+ Client \a c is moved around to position \a pos. This gives the
+ workspace the opportunity to interveniate and to implement
+@@ -896,10 +903,6 @@ void Client::checkWorkspacePosition()
+ setGeometry( area );
+ return;
+ }
+- if( maximizeMode() != MaximizeRestore )
+- // TODO update geom_restore?
+- changeMaximize( false, false, true ); // adjust size
+-
+ if( isFullScreen())
+ {
+ QRect area = workspace()->clientArea( FullScreenArea, this );
+@@ -926,6 +929,10 @@ void Client::checkWorkspacePosition()
+ return;
+ }
+
++ if( maximizeMode() != MaximizeRestore )
++ // TODO update geom_restore?
++ changeMaximize( false, false, true ); // adjust size
++
+ if( !isShade()) // TODO
+ {
+ int old_diff_x = workarea_diff_x;
+@@ -1722,6 +1729,7 @@ void Client::setGeometry( int x, int y,
+ sendSyntheticConfigureNotify();
+ updateWindowRules();
+ checkMaximizeGeometry();
++ workspace()->checkActiveScreen( this );
+ }
+
+ void Client::plainResize( int w, int h, ForceGeometry_t force )
+@@ -1775,6 +1783,7 @@ void Client::plainResize( int w, int h,
+ sendSyntheticConfigureNotify();
+ updateWindowRules();
+ checkMaximizeGeometry();
++ workspace()->checkActiveScreen( this );
+ }
+
+ /*!
+@@ -1795,6 +1804,7 @@ void Client::move( int x, int y, ForceGe
+ sendSyntheticConfigureNotify();
+ updateWindowRules();
+ checkMaximizeGeometry();
++ workspace()->checkActiveScreen( this );
+ }
+
+
+Index: kwin/kwin.kcfg
+===================================================================
+--- kwin/kwin.kcfg.orig
++++ kwin/kwin.kcfg
+@@ -60,6 +60,9 @@
+ <entry key="IgnorePositionClasses" type="StringList" />
+ <entry key="KillPingTimeout" type="Int" />
+ <entry key="ShowDesktopIsMinimizeAll" type="Bool" />
++ <entry key="SeparateScreenFocus" type="Bool" />
++ <entry key="ActiveMouseScreen" type="Bool" />
++ <entry key="XineramaPlacementScreen" type="Int" />
+ </group>
+
+ <group name="WM" >
+Index: kwin/client.h
+===================================================================
+--- kwin/client.h.orig
++++ kwin/client.h
+@@ -118,6 +118,9 @@ class Client : public QObject, public KD
+ bool isOnCurrentDesktop() const;
+ bool isOnAllDesktops() const;
+ void setOnAllDesktops( bool set );
++
++ bool isOnScreen( int screen ) const; // true if it's at least partially there
++ int screen() const; // the screen where the center is
+
+ // !isMinimized() && not hidden, i.e. normally visible on some virtual desktop
+ bool isShown( bool shaded_is_shown ) const;
+Index: kwin/manage.cpp
+===================================================================
+--- kwin/manage.cpp.orig
++++ kwin/manage.cpp
+@@ -166,7 +166,7 @@ bool Client::manage( Window w, bool isMa
+ it != mainclients.end();
+ ++it )
+ {
+- if( (*it)->isSpecialWindow())
++ if( mainclients.count() > 1 && (*it)->isSpecialWindow())
+ continue; // don't consider toolbars etc when placing
+ maincl = *it;
+ if( (*it)->isOnCurrentDesktop())
+@@ -202,9 +202,14 @@ bool Client::manage( Window w, bool isMa
+ if( isMapped || session )
+ area = workspace()->clientArea( FullArea, geom.center(), desktop());
+ else if( options->xineramaPlacementEnabled )
+- area = workspace()->clientArea( PlacementArea, QCursor::pos(), desktop());
++ {
++ int screen = options->xineramaPlacementScreen;
++ if( screen == -1 ) // active screen
++ screen = asn_data.xinerama() == -1 ? workspace()->activeScreen() : asn_data.xinerama();
++ area = workspace()->clientArea( PlacementArea, workspace()->screenGeometry( screen ).center(), desktop());
++ }
+ else
+- area = workspace()->clientArea( PlacementArea, geom.center(), desktop());
++ area = workspace()->clientArea( PlacementArea, QCursor::pos(), desktop());
+
+ if( int type = checkFullScreenHack( geom ))
+ {
+Index: kwin/workspace.cpp
+===================================================================
+--- kwin/workspace.cpp.orig
++++ kwin/workspace.cpp
+@@ -82,6 +82,7 @@ Workspace::Workspace( bool restore )
+ QObject (0, "workspace"),
+ current_desktop (0),
+ number_of_desktops(0),
++ active_screen (0),
+ active_popup( NULL ),
+ active_popup_client( NULL ),
+ desktop_widget (0),
+@@ -202,7 +203,7 @@ Workspace::Workspace( bool restore )
+ client_keys = new KGlobalAccel( this );
+ initShortcuts();
+ tab_box = new TabBox( this );
+- popupinfo = new PopupInfo( );
++ popupinfo = new PopupInfo( this );
+
+ init();
+
+@@ -304,6 +305,7 @@ void Workspace::init()
+ NET::WM2ExtendedStrut |
+ NET::WM2KDETemporaryRules |
+ NET::WM2ShowingDesktop |
++ NET::WM2FullPlacement |
+ NET::WM2DesktopLayout |
+ 0
+ ,
+@@ -1541,6 +1543,83 @@ void Workspace::setDesktopLayout( int, i
+ { // DCOP-only, unused
+ }
+
++int Workspace::numScreens() const
++ {
++ if( !options->xineramaEnabled )
++ return 0;
++ return qApp->desktop()->numScreens();
++ }
++
++int Workspace::activeScreen() const
++ {
++ if( !options->xineramaEnabled )
++ return 0;
++ if( !options->activeMouseScreen )
++ {
++ if( activeClient() != NULL && !activeClient()->isOnScreen( active_screen ))
++ return qApp->desktop()->screenNumber( activeClient()->geometry().center());
++ return active_screen;
++ }
++ return qApp->desktop()->screenNumber( QCursor::pos());
++ }
++
++// check whether a client moved completely out of what's considered the active screen,
++// if yes, set a new active screen
++void Workspace::checkActiveScreen( const Client* c )
++ {
++ if( !options->xineramaEnabled )
++ return;
++ if( !c->isActive())
++ return;
++ if( !c->isOnScreen( active_screen ))
++ active_screen = c->screen();
++ }
++
++// called e.g. when a user clicks on a window, set active screen to be the screen
++// where the click occured
++void Workspace::setActiveScreenMouse( QPoint mousepos )
++ {
++ if( !options->xineramaEnabled )
++ return;
++ active_screen = qApp->desktop()->screenNumber( mousepos );
++ }
++
++QRect Workspace::screenGeometry( int screen ) const
++ {
++ if( !options->xineramaEnabled )
++ return qApp->desktop()->geometry();
++ return qApp->desktop()->screenGeometry( screen );
++ }
++
++int Workspace::screenNumber( QPoint pos ) const
++ {
++ if( !options->xineramaEnabled )
++ return 0;
++ return qApp->desktop()->screenNumber( pos );
++ }
++
++
++void Workspace::sendClientToScreen( Client* c, int screen )
++ {
++ if( c->screen() == screen ) // don't use isOnScreen(), that's true even when only parti
++ // ally
++ return;
++ GeometryUpdatesPostponer blocker( c );
++ QRect old_sarea = clientArea( MaximizeArea, c );
++ QRect sarea = clientArea( MaximizeArea, screen, c->desktop());
++ c->setGeometry( sarea.x() - old_sarea.x() + c->x(), sarea.y() - old_sarea.y() + c->y(),
++ c->size().width(), c->size().height());
++ c->checkWorkspacePosition();
++ ClientList transients_stacking_order = ensureStackingOrder( c->transients());
++ for( ClientList::ConstIterator it = transients_stacking_order.begin();
++ it != transients_stacking_order.end();
++ ++it )
++ sendClientToScreen( *it, screen );
++ if( c->isActive())
++ active_screen = screen;
++ }
++
++
+ void Workspace::updateDesktopLayout()
+ {
+ // rootInfo->desktopLayoutCorner(); // I don't find this worth bothering, feel free to
+Index: kwin/activation.cpp
+===================================================================
+--- kwin/activation.cpp.orig
++++ kwin/activation.cpp
+@@ -360,6 +360,8 @@ void Workspace::takeActivity( Client* c,
+ return;
+ }
+ c->takeActivity( flags, handled, Allowed );
++ if( !c->isOnScreen( active_screen ))
++ active_screen = c->screen();
+ }
+
+ void Workspace::handleTakeActivity( Client* c, Time /*timestamp*/, int flags )
+@@ -413,6 +415,13 @@ bool Workspace::activateNextClient( Clie
+ {
+ if( !(*it)->isShown( false ) || !(*it)->isOnCurrentDesktop())
+ continue;
++ if( options->separateScreenFocus )
++ {
++ if( c != NULL && !(*it)->isOnScreen( c->screen()))
++ continue;
++ if( c == NULL && !(*it)->isOnScreen( activeScreen()))
++ continue;
++ }
+ if( mainwindows.contains( *it ))
+ {
+ get_focus = *it;
+@@ -438,6 +447,31 @@ bool Workspace::activateNextClient( Clie
+ return true;
+ }
+
++void Workspace::setCurrentScreen( int new_screen )
++ {
++ if (new_screen < 0 || new_screen > numScreens())
++ return;
++ if ( !options->focusPolicyIsReasonable())
++ return;
++ closeActivePopup();
++ Client* get_focus = NULL;
++ for( ClientList::ConstIterator it = focus_chain[currentDesktop()].fromLast();
++ it != focus_chain[currentDesktop()].end();
++ --it )
++ {
++ if( !(*it)->isShown( false ) || !(*it)->isOnCurrentDesktop())
++ continue;
++ if( !(*it)->screen() == new_screen )
++ continue;
++ get_focus = *it;
++ break;
++ }
++ if( get_focus == NULL )
++ get_focus = findDesktop( true, currentDesktop());
++ if( get_focus != NULL && get_focus != mostRecentlyActivatedClient())
++ requestFocus( get_focus );
++ active_screen = new_screen;
++ }
+
+ void Workspace::gotFocusIn( const Client* c )
+ {
+@@ -860,6 +894,8 @@ void Client::startupIdChanged()
+ desktop = asn_data.desktop();
+ if( !isOnAllDesktops())
+ workspace()->sendClientToDesktop( this, desktop, true );
++ if( asn_data.xinerama() != -1 )
++ workspace()->sendClientToScreen( this, asn_data.xinerama());
+ Time timestamp = asn_id.timestamp();
+ if( timestamp == 0 && asn_data.timestamp() != -1U )
+ timestamp = asn_data.timestamp();
+Index: kwin/kwinbindings.cpp
+===================================================================
+--- kwin/kwinbindings.cpp.orig
++++ kwin/kwinbindings.cpp
+@@ -104,6 +104,15 @@
+ DEF( I18N_NOOP("Window One Desktop to the Left"), 0, 0, slotWindowToDesktopLeft() );
+ DEF( I18N_NOOP("Window One Desktop Up"), 0, 0, slotWindowToDesktopUp() );
+ DEF( I18N_NOOP("Window One Desktop Down"), 0, 0, slotWindowToDesktopDown() );
++ DEF( I18N_NOOP("Window to Screen 0"), 0, 0, slotWindowToScreen(int) );
++ DEF( I18N_NOOP("Window to Screen 1"), 0, 0, slotWindowToScreen(int) );
++ DEF( I18N_NOOP("Window to Screen 2"), 0, 0, slotWindowToScreen(int) );
++ DEF( I18N_NOOP("Window to Screen 3"), 0, 0, slotWindowToScreen(int) );
++ DEF( I18N_NOOP("Window to Screen 4"), 0, 0, slotWindowToScreen(int) );
++ DEF( I18N_NOOP("Window to Screen 5"), 0, 0, slotWindowToScreen(int) );
++ DEF( I18N_NOOP("Window to Screen 6"), 0, 0, slotWindowToScreen(int) );
++ DEF( I18N_NOOP("Window to Screen 7"), 0, 0, slotWindowToScreen(int) );
++ DEF( I18N_NOOP("Window to Next Screen"), 0, 0, slotWindowToNextScreen() );
+
+ keys->insert( "Group:Desktop Switching", i18n("Desktop Switching") );
+ DEF( I18N_NOOP("Switch to Desktop 1"), CTRL+Qt::Key_F1, WIN+Qt::Key_F1, slotSwitchToDesktop(int) );
+@@ -132,6 +141,15 @@
+ DEF( I18N_NOOP("Switch One Desktop to the Left"), 0, 0, slotSwitchDesktopLeft() );
+ DEF( I18N_NOOP("Switch One Desktop Up"), 0, 0, slotSwitchDesktopUp() );
+ DEF( I18N_NOOP("Switch One Desktop Down"), 0, 0, slotSwitchDesktopDown() );
++ DEF( I18N_NOOP("Switch to Screen 0"), 0, 0, slotSwitchToScreen(int) );
++ DEF( I18N_NOOP("Switch to Screen 1"), 0, 0, slotSwitchToScreen(int) );
++ DEF( I18N_NOOP("Switch to Screen 2"), 0, 0, slotSwitchToScreen(int) );
++ DEF( I18N_NOOP("Switch to Screen 3"), 0, 0, slotSwitchToScreen(int) );
++ DEF( I18N_NOOP("Switch to Screen 4"), 0, 0, slotSwitchToScreen(int) );
++ DEF( I18N_NOOP("Switch to Screen 5"), 0, 0, slotSwitchToScreen(int) );
++ DEF( I18N_NOOP("Switch to Screen 6"), 0, 0, slotSwitchToScreen(int) );
++ DEF( I18N_NOOP("Switch to Screen 7"), 0, 0, slotSwitchToScreen(int) );
++ DEF( I18N_NOOP("Switch to Next Screen"), 0, 0, slotSwitchToNextScreen() );
+
+ keys->insert( "Group:Miscellaneous", i18n("Miscellaneous") );
+ DEF( I18N_NOOP("Mouse Emulation"), ALT+Qt::Key_F12, 0, slotMouseEmulation() );