make checkWorkspacePosition() work also on desktop/screen change

It previously worked only when struts changed, this makes it work
e.g. when moving a window between desktops that have different
struts, or when sending a windows between differently sized screens.
icc-effect-5.14.5
Luboš Luňák 2011-09-29 17:52:19 +02:00
parent 8edf542bb7
commit 07e3dff871
4 changed files with 79 additions and 38 deletions

View File

@ -321,7 +321,7 @@ public:
void gotPing(Time timestamp);
void checkWorkspacePosition(const QRect &geo = QRect());
void checkWorkspacePosition(QRect oldGeometry = QRect(), int oldDesktop = -2);
void updateUserTime(Time time = CurrentTime);
Time userTime() const;
bool hasUserTimeSupport() const;

View File

@ -215,6 +215,8 @@ void Workspace::updateClientArea(bool force)
it != desktops.constEnd();
++it)
(*it)->checkWorkspacePosition();
oldrestrictedmovearea.clear(); // reset, for hasPreviousRestricedMoveAreas()
}
kDebug(1212) << "Done.";
@ -350,6 +352,12 @@ QRegion Workspace::previousRestrictedMoveArea(int desktop, StrutAreas areas) con
return region;
}
// This in practice returns true when we are inside Workspace::updateClientArea()
bool Workspace::hasPreviousRestricedMoveAreas() const
{
return !oldrestrictedmovearea.isEmpty();
}
/*!
Client \a c is moved around to position \a pos. This gives the
workspace the opportunity to interveniate and to implement
@ -1018,8 +1026,12 @@ bool Client::hasOffscreenXineramaStrut() const
return !region.isEmpty();
}
void Client::checkWorkspacePosition(const QRect &geo)
void Client::checkWorkspacePosition(QRect oldGeometry, int oldDesktop)
{
if( !oldGeometry.isValid())
oldGeometry = geometry();
if( oldDesktop == -2 )
oldDesktop = desktop();
if (isDesktop())
return;
if (isFullScreen()) {
@ -1058,38 +1070,66 @@ void Client::checkWorkspacePosition(const QRect &geo)
// 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);
int oldTopMax = oldScreenArea.y();
int oldRightMax = oldScreenArea.x() + oldScreenArea.width();
int oldBottomMax = oldScreenArea.y() + oldScreenArea.height();
int oldLeftMax = oldScreenArea.x();
const QRect screenArea = workspace()->clientArea(ScreenArea, this);
int oldTopMax = screenArea.y();
int oldRightMax = screenArea.x() + screenArea.width();
int oldBottomMax = screenArea.y() + screenArea.height();
int oldLeftMax = screenArea.x();
int topMax = INT_MIN, rightMax = INT_MAX, bottomMax = INT_MAX, leftMax = INT_MIN;
QRect newGeom = geo.isValid() ? geo : geometry();
QRect newGeom = geometry();
const QRect oldGeomTall = QRect(oldGeometry.x(), 0, oldGeometry.width(), displayHeight()); // Full screen height
const QRect oldGeomWide = QRect(0, oldGeometry.y(), displayWidth(), oldGeometry.height()); // Full screen width
const QRect newGeomTall = QRect(newGeom.x(), 0, newGeom.width(), displayHeight()); // Full screen height
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).
foreach (const QRect & r, workspace()->previousRestrictedMoveArea(desktop(), StrutAreaTop).rects()) {
QRect rect = r & newGeomTall;
if (!rect.isEmpty())
oldTopMax = qMax(oldTopMax, rect.y() + rect.height());
}
foreach (const QRect & r, workspace()->previousRestrictedMoveArea(desktop(), StrutAreaRight).rects()) {
QRect rect = r & newGeomWide;
if (!rect.isEmpty())
oldRightMax = qMin(oldRightMax, rect.x());
}
foreach (const QRect & r, workspace()->previousRestrictedMoveArea(desktop(), StrutAreaBottom).rects()) {
QRect rect = r & newGeomTall;
if (!rect.isEmpty())
oldBottomMax = qMin(oldBottomMax, rect.y());
}
foreach (const QRect & r, workspace()->previousRestrictedMoveArea(desktop(), StrutAreaLeft).rects()) {
QRect rect = r & newGeomWide;
if (!rect.isEmpty())
oldLeftMax = qMax(oldLeftMax, rect.x() + rect.width());
if( workspace()->hasPreviousRestricedMoveAreas()) {
// 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;
if (!rect.isEmpty())
oldTopMax = qMax(oldTopMax, rect.y() + rect.height());
}
foreach (const QRect & r, workspace()->previousRestrictedMoveArea(oldDesktop, StrutAreaRight).rects()) {
QRect rect = r & oldGeomWide;
if (!rect.isEmpty())
oldRightMax = qMin(oldRightMax, rect.x());
}
foreach (const QRect & r, workspace()->previousRestrictedMoveArea(oldDesktop, StrutAreaBottom).rects()) {
QRect rect = r & oldGeomTall;
if (!rect.isEmpty())
oldBottomMax = qMin(oldBottomMax, rect.y());
}
foreach (const QRect & r, workspace()->previousRestrictedMoveArea(oldDesktop, StrutAreaLeft).rects()) {
QRect rect = r & oldGeomWide;
if (!rect.isEmpty())
oldLeftMax = qMax(oldLeftMax, rect.x() + rect.width());
}
} else {
// These 4 compute old bounds when e.g. active desktop or screen changes
foreach (const QRect & r, workspace()->restrictedMoveArea(oldDesktop, StrutAreaTop).rects()) {
QRect rect = r & oldGeomTall;
if (!rect.isEmpty())
oldTopMax = qMax(oldTopMax, rect.y() + rect.height());
}
foreach (const QRect & r, workspace()->restrictedMoveArea(oldDesktop, StrutAreaRight).rects()) {
QRect rect = r & oldGeomWide;
if (!rect.isEmpty())
oldRightMax = qMin(oldRightMax, rect.x());
}
foreach (const QRect & r, workspace()->restrictedMoveArea(oldDesktop, StrutAreaBottom).rects()) {
QRect rect = r & oldGeomTall;
if (!rect.isEmpty())
oldBottomMax = qMin(oldBottomMax, rect.y());
}
foreach (const QRect & r, workspace()->restrictedMoveArea(oldDesktop, StrutAreaLeft).rects()) {
QRect rect = r & oldGeomWide;
if (!rect.isEmpty())
oldLeftMax = qMax(oldLeftMax, rect.x() + rect.width());
}
}
// These 4 compute new bounds
foreach (const QRect & r, workspace()->restrictedMoveArea(desktop(), StrutAreaTop).rects()) {
QRect rect = r & newGeomTall;
if (!rect.isEmpty())
@ -1112,11 +1152,11 @@ void Client::checkWorkspacePosition(const QRect &geo)
}
// Check if the sides were touching before but are no longer
if (newGeom.y() == oldTopMax &&
if (oldGeometry.y() == oldTopMax &&
newGeom.y() != topMax) {
// Top was touching before but isn't anymore
// If the other side was touching make sure it still is afterwards
if (newGeom.y() + newGeom.height() == oldBottomMax)
if (oldGeometry.y() + oldGeometry.height() == oldBottomMax)
newGeom.setTop(qMax(topMax, screenArea.y()));
else
newGeom.moveTop(qMax(topMax, screenArea.y()));
@ -1124,11 +1164,11 @@ void Client::checkWorkspacePosition(const QRect &geo)
newGeom.setBottom(qMin(qMin(bottomMax - 1, screenArea.bottom()),
newGeom.y() + newGeom.height() - 1));
}
if (newGeom.x() + newGeom.width() == oldRightMax &&
if (oldGeometry.x() + oldGeometry.width() == oldRightMax &&
newGeom.x() + newGeom.width() != rightMax) {
// Right was touching before but isn't anymore
// If the other side was touching make sure it still is afterwards
if (newGeom.x() == oldLeftMax)
if (oldGeometry.x() == oldLeftMax)
newGeom.setRight(qMin(rightMax - 1, screenArea.right()));
else
newGeom.moveRight(qMin(rightMax - 1, screenArea.right()));
@ -1136,11 +1176,11 @@ void Client::checkWorkspacePosition(const QRect &geo)
newGeom.setLeft(qMax(qMax(leftMax, screenArea.x()),
newGeom.x()));
}
if (newGeom.y() + newGeom.height() == oldBottomMax &&
if (oldGeometry.y() + oldGeometry.height() == oldBottomMax &&
newGeom.y() + newGeom.height() != bottomMax) {
// Bottom was touching before but isn't anymore
// If the other side was touching make sure it still is afterwards
if (newGeom.y() == oldTopMax)
if (oldGeometry.y() == oldTopMax)
newGeom.setBottom(qMin(bottomMax - 1, screenArea.bottom()));
else
newGeom.moveBottom(qMin(bottomMax - 1, screenArea.bottom()));
@ -1148,11 +1188,11 @@ void Client::checkWorkspacePosition(const QRect &geo)
newGeom.setTop(qMax(qMax(topMax, screenArea.y()),
newGeom.y()));
}
if (newGeom.x() == oldLeftMax &&
if (oldGeometry.x() == oldLeftMax &&
newGeom.x() != leftMax) {
// Left was touching before but isn't anymore
// If the other side was touching make sure it still is afterwards
if (newGeom.x() + newGeom.width() == oldRightMax)
if (oldGeometry.x() + oldGeometry.width() == oldRightMax)
newGeom.setLeft(qMax(leftMax, screenArea.x()));
else
newGeom.moveLeft(qMax(leftMax, screenArea.x()));

View File

@ -1584,8 +1584,6 @@ void Workspace::setNumberOfDesktops(int n)
workarea.resize(n + 1);
restrictedmovearea.clear();
restrictedmovearea.resize(n + 1);
oldrestrictedmovearea.clear();
oldrestrictedmovearea.resize(n + 1);
screenarea.clear();
updateClientArea(true);
@ -1630,6 +1628,7 @@ void Workspace::sendClientToDesktop(Client* c, int desk, bool dont_activate)
#ifdef KWIN_BUILD_TILING
m_tiling->notifyTilingWindowDesktopChanged(c, old_desktop);
#endif
c->checkWorkspacePosition( QRect(), old_desktop );
ClientList transients_stacking_order = ensureStackingOrder(c->transients());
for (ClientList::ConstIterator it = transients_stacking_order.constBegin();
@ -1742,9 +1741,10 @@ void Workspace::sendClientToScreen(Client* c, int screen)
GeometryUpdatesBlocker blocker(c);
QRect old_sarea = clientArea(MaximizeArea, c);
QRect sarea = clientArea(MaximizeArea, screen, c->desktop());
QRect oldgeom = c->geometry();
c->setGeometry(sarea.x() - old_sarea.x() + c->x(), sarea.y() - old_sarea.y() + c->y(),
c->size().width(), c->size().height());
c->checkWorkspacePosition();
c->checkWorkspacePosition( oldgeom );
ClientList transients_stacking_order = ensureStackingOrder(c->transients());
for (ClientList::ConstIterator it = transients_stacking_order.constBegin();
it != transients_stacking_order.constEnd();

View File

@ -121,6 +121,7 @@ public:
QRegion restrictedMoveArea(int desktop, StrutAreas areas = StrutAreaAll) const;
QRegion previousRestrictedMoveArea(int desktop, StrutAreas areas = StrutAreaAll) const;
bool hasPreviousRestricedMoveAreas() const;
/**
* @internal