diff --git a/geometry.cpp b/geometry.cpp index 1b1f7ed761..0690e5ffa1 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -76,6 +76,7 @@ void Workspace::desktopResized() rootInfo->setDesktopGeometry(-1, desktop_geometry); updateClientArea(); + saveOldScreenSizes(); // after updateClientArea(), so that one still uses the previous one #ifdef KWIN_BUILD_SCREENEDGES m_screenEdge.update(true); #endif @@ -83,6 +84,15 @@ void Workspace::desktopResized() compositeResetTimer.start(0); } +void Workspace::saveOldScreenSizes() +{ + oldscreensizes.clear(); + for( int i = 0; + i < numScreens(); + ++i ) + oldscreensizes.append( screenGeometry( i )); +} + /*! Updates the current client areas according to the current clients. @@ -216,7 +226,7 @@ void Workspace::updateClientArea(bool force) ++it) (*it)->checkWorkspacePosition(); - oldrestrictedmovearea.clear(); // reset, for hasPreviousRestrictedMoveAreas() + oldrestrictedmovearea.clear(); // reset, no longer valid or needed } kDebug(1212) << "Done."; @@ -341,6 +351,11 @@ QRegion Workspace::restrictedMoveArea(int desktop, StrutAreas areas) const return region; } +bool Workspace::inUpdateClientArea() const +{ + return !oldrestrictedmovearea.isEmpty(); +} + QRegion Workspace::previousRestrictedMoveArea(int desktop, StrutAreas areas) const { if (desktop == NETWinInfo::OnAllDesktops || desktop == 0) @@ -352,10 +367,9 @@ QRegion Workspace::previousRestrictedMoveArea(int desktop, StrutAreas areas) con return region; } -// This in practice returns true when we are inside Workspace::updateClientArea() -bool Workspace::hasPreviousRestrictedMoveAreas() const +QVector< QRect > Workspace::previousScreenSizes() const { - return !oldrestrictedmovearea.isEmpty(); + return oldscreensizes; } /*! @@ -1070,7 +1084,20 @@ void Client::checkWorkspacePosition(QRect oldGeometry, int oldDesktop) // If the window was touching an edge before but not now move it so it is again. // Old and new maximums have different starting values so windows on the screen // edge will move when a new strut is placed on the edge. - const QRect oldScreenArea = workspace()->clientArea(ScreenArea, oldGeometry.center(), oldDesktop); + QRect oldScreenArea; + if( workspace()->inUpdateClientArea()) { + // we need to find the screen area as it was before the change + oldScreenArea = QRect( 0, 0, displayWidth(), displayHeight()); + int distance = INT_MAX; + foreach( QRect r, workspace()->previousScreenSizes()) { + int d = r.contains( oldGeometry.center()) ? 0 : ( r.center() - oldGeometry.center()).manhattanLength(); + if( d < distance ) { + distance = d; + oldScreenArea = r; + } + } + } else + oldScreenArea = workspace()->clientArea(ScreenArea, oldGeometry.center(), oldDesktop); int oldTopMax = oldScreenArea.y(); int oldRightMax = oldScreenArea.x() + oldScreenArea.width(); int oldBottomMax = oldScreenArea.y() + oldScreenArea.height(); @@ -1084,7 +1111,7 @@ void Client::checkWorkspacePosition(QRect oldGeometry, int oldDesktop) const QRect newGeomWide = QRect(0, newGeom.y(), displayWidth(), newGeom.height()); // Full screen width // Get the max strut point for each side where the window is (E.g. Highest point for // the bottom struts bounded by the window's left and right sides). - if( workspace()->hasPreviousRestrictedMoveAreas()) { + if( workspace()->inUpdateClientArea()) { // These 4 compute old bounds when the restricted areas themselves changed (Workspace::updateClientArea()) foreach (const QRect & r, workspace()->previousRestrictedMoveArea(oldDesktop, StrutAreaTop).rects()) { QRect rect = r & oldGeomTall; diff --git a/workspace.cpp b/workspace.cpp index deeefad872..443bb6acc2 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -462,6 +462,7 @@ void Workspace::init() // Propagate clients, will really happen at the end of the updates blocker block updateStackingOrder(true); + saveOldScreenSizes(); updateClientArea(); // NETWM spec says we have to set it to (0,0) if we don't support it diff --git a/workspace.h b/workspace.h index 28bd9c286e..dc0a7478fd 100644 --- a/workspace.h +++ b/workspace.h @@ -120,8 +120,6 @@ public: QRect clientArea(clientAreaOption, int screen, int desktop) const; QRegion restrictedMoveArea(int desktop, StrutAreas areas = StrutAreaAll) const; - QRegion previousRestrictedMoveArea(int desktop, StrutAreas areas = StrutAreaAll) const; - bool hasPreviousRestrictedMoveAreas() const; /** * @internal @@ -339,6 +337,12 @@ public: return activityController_.listActivities(KActivityInfo::Running); } + // True when performing Workspace::updateClientArea(). + // The calls below are valid only in that case. + bool inUpdateClientArea() const; + QRegion previousRestrictedMoveArea(int desktop, StrutAreas areas = StrutAreaAll) const; + QVector< QRect > previousScreenSizes() const; + // Tab box #ifdef KWIN_BUILD_TABBOX TabBox::TabBox *tabBox() const; @@ -717,6 +721,7 @@ private: void blockStackingUpdates(bool block); void updateToolWindows(bool also_hide); void fixPositionAfterCrash(Window w, const XWindowAttributes& attr); + void saveOldScreenSizes(); /// This is the right way to create a new client Client* createClient(Window w, bool is_mapped); @@ -878,6 +883,7 @@ private: // Array of the previous restricted areas that window cannot be moved into QVector oldrestrictedmovearea; QVector< QVector > screenarea; // Array of workareas per xinerama screen for all virtual desktops + QVector< QRect > oldscreensizes; // array of previous sizes of xinerama screens int set_active_client_recursion; int block_stacking_updates; // When > 0, stacking updates are temporarily disabled