From 0581746327feee742150eff421264a912b61cb5f Mon Sep 17 00:00:00 2001 From: Lucas Murray Date: Fri, 25 Jul 2008 10:31:47 +0000 Subject: [PATCH] Allow moving of maximized windows across screens BUG: 131299 svn path=/trunk/KDE/kdebase/workspace/; revision=837644 --- client.h | 1 + effects.cpp | 7 +++++++ effects.h | 1 + geometry.cpp | 52 +++++++++++++++++++++++++++++++++-------------- lib/kwineffects.h | 3 ++- useractions.cpp | 6 +++--- 6 files changed, 51 insertions(+), 19 deletions(-) diff --git a/client.h b/client.h index 346fcef015..81131193a9 100644 --- a/client.h +++ b/client.h @@ -182,6 +182,7 @@ class Client bool isResizable() const; bool isMovable() const; + bool isMovableAcrossScreens() const; bool isCloseable() const; // may be closed by the user (may have a close button) void takeActivity( int flags, bool handled, allowed_t ); // takes ActivityFlags as arg (in utils.h) diff --git a/effects.cpp b/effects.cpp index 4db4c6f4cf..fb3970cb23 100644 --- a/effects.cpp +++ b/effects.cpp @@ -1144,6 +1144,13 @@ bool EffectWindowImpl::isMovable() const return false; } +bool EffectWindowImpl::isMovableAcrossScreens() const + { + if( Client* c = dynamic_cast< Client* >( toplevel )) + return c->isMovableAcrossScreens(); + return false; + } + bool EffectWindowImpl::isUserMove() const { if( Client* c = dynamic_cast< Client* >( toplevel )) diff --git a/effects.h b/effects.h index d14ee3ee6c..7a3c40937e 100644 --- a/effects.h +++ b/effects.h @@ -200,6 +200,7 @@ class EffectWindowImpl : public EffectWindow virtual QSize size() const; virtual QRect rect() const; virtual bool isMovable() const; + virtual bool isMovableAcrossScreens() const; virtual bool isUserMove() const; virtual bool isUserResize() const; virtual QRect iconGeometry() const; diff --git a/geometry.cpp b/geometry.cpp index 845d5841c6..a71fedc779 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -1720,6 +1720,20 @@ bool Client::isMovable() const return true; } +/*! + Returns whether the window is moveable across Xinerama screens + */ +bool Client::isMovableAcrossScreens() const + { + if( !motif_may_move ) + return false; + if( isSpecialWindow() && !isSplash() && !isToolbar()) // allow moving of splashscreens :) + return false; + if( rules()->checkPosition( invalidPoint ) != invalidPoint ) // forced position + return false; + return true; + } + /*! Returns whether the window is resizable or has a fixed size. */ @@ -2607,7 +2621,7 @@ void Client::delayedMoveResize() void Client::handleMoveResize( int x, int y, int x_root, int y_root ) { - if(( mode == PositionCenter && !isMovable()) + if(( mode == PositionCenter && !isMovableAcrossScreens() ) || ( mode != PositionCenter && ( isShade() || !isResizable()))) return; @@ -2760,20 +2774,28 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root ) else if( isMove()) { assert( mode == PositionCenter ); - // first move, then snap, then check bounds - moveResizeGeom.moveTopLeft( topleft ); - moveResizeGeom.moveTopLeft( workspace()->adjustClientPosition( this, moveResizeGeom.topLeft(), - unrestrictedMoveResize ) ); - // NOTE: This is duped in checkUnrestrictedMoveResize(). - if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 ) // titlebar mustn't go out - moveResizeGeom.moveBottom( desktopArea.top() + titlebar_marge - 1 ); - // no need to check top_marge, titlebar_marge already handles it - if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge ) - moveResizeGeom.moveTop( desktopArea.bottom() - bottom_marge ); - if( moveResizeGeom.right() < desktopArea.left() + left_marge ) - moveResizeGeom.moveRight( desktopArea.left() + left_marge ); - if( moveResizeGeom.left() > desktopArea.right() - right_marge ) - moveResizeGeom.moveLeft(desktopArea.right() - right_marge ); + if( !isMovable() ) // isMovableAcrossScreens() must have been true to get here + { // Special moving of maximized windows on Xinerama screens + int screen = workspace()->screenNumber( globalPos ); + moveResizeGeom = workspace()->clientArea( MaximizeArea, screen, 0 ); + } + else + { + // first move, then snap, then check bounds + moveResizeGeom.moveTopLeft( topleft ); + moveResizeGeom.moveTopLeft( workspace()->adjustClientPosition( this, moveResizeGeom.topLeft(), + unrestrictedMoveResize )); + // NOTE: This is duped in checkUnrestrictedMoveResize(). + if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 ) // titlebar mustn't go out + moveResizeGeom.moveBottom( desktopArea.top() + titlebar_marge - 1 ); + // no need to check top_marge, titlebar_marge already handles it + if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge ) + moveResizeGeom.moveTop( desktopArea.bottom() - bottom_marge ); + if( moveResizeGeom.right() < desktopArea.left() + left_marge ) + moveResizeGeom.moveRight( desktopArea.left() + left_marge ); + if( moveResizeGeom.left() > desktopArea.right() - right_marge ) + moveResizeGeom.moveLeft(desktopArea.right() - right_marge ); + } if( moveResizeGeom.topLeft() != previousMoveResizeGeom.topLeft()) update = true; } diff --git a/lib/kwineffects.h b/lib/kwineffects.h index 32397b7c23..9509cb422b 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -162,7 +162,7 @@ X-KDE-Library=kwin4_effect_cooleffect #define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor )) #define KWIN_EFFECT_API_VERSION_MAJOR 0 -#define KWIN_EFFECT_API_VERSION_MINOR 21 +#define KWIN_EFFECT_API_VERSION_MINOR 22 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) @@ -629,6 +629,7 @@ class KWIN_EXPORT EffectWindow virtual QSize size() const = 0; virtual QRect rect() const = 0; virtual bool isMovable() const = 0; + virtual bool isMovableAcrossScreens() const = 0; virtual bool isUserMove() const = 0; virtual bool isUserResize() const = 0; virtual QRect iconGeometry() const = 0; diff --git a/useractions.cpp b/useractions.cpp index 9a87e822c2..a1b58a8d43 100644 --- a/useractions.cpp +++ b/useractions.cpp @@ -220,7 +220,7 @@ void Workspace::clientPopupAboutToShow() } mResizeOpAction->setEnabled( active_popup_client->isResizable() ); - mMoveOpAction->setEnabled( active_popup_client->isMovable() ); + mMoveOpAction->setEnabled( active_popup_client->isMovableAcrossScreens() ); mMaximizeOpAction->setEnabled( active_popup_client->isMaximizable() ); mMaximizeOpAction->setChecked( active_popup_client->maximizeMode() == Client::MaximizeFull ); mShadeOpAction->setEnabled( active_popup_client->isShadeable() ); @@ -610,13 +610,13 @@ bool Client::performMouseCommand( Options::MouseCommand command, const QPoint &g workspace()->raiseClient( this ); workspace()->requestFocus( this ); workspace()->setActiveScreenMouse( globalPos ); - if( options->moveMode == Options::Transparent && isMovable()) + if( options->moveMode == Options::Transparent && isMovableAcrossScreens()) move_faked_activity = workspace()->fakeRequestedActivity( this ); // fallthrough case Options::MouseMove: case Options::MouseUnrestrictedMove: { - if (!isMovable()) + if (!isMovableAcrossScreens()) break; if( moveResizeMode ) finishMoveResize( false );