Window: Extract next interactive move geometry code to the separate function
This will allow code reuse.
This commit is contained in:
parent
4449315e39
commit
9cf424993f
4 changed files with 97 additions and 82 deletions
174
src/window.cpp
174
src/window.cpp
|
@ -1624,6 +1624,99 @@ QRectF Window::nextInteractiveResizeGeometry(const QPointF &global) const
|
|||
return nextMoveResizeGeom;
|
||||
}
|
||||
|
||||
QRectF Window::nextInteractiveMoveGeometry(const QPointF &global) const
|
||||
{
|
||||
const QRectF currentMoveResizeGeom = moveResizeGeometry();
|
||||
QRectF nextMoveResizeGeom = moveResizeGeometry();
|
||||
|
||||
if (!isMovable()) {
|
||||
return nextMoveResizeGeom;
|
||||
}
|
||||
|
||||
QPointF topleft = global - interactiveMoveOffset();
|
||||
// first move, then snap, then check bounds
|
||||
QRectF geometry = nextMoveResizeGeom;
|
||||
geometry.moveTopLeft(topleft);
|
||||
geometry.moveTopLeft(workspace()->adjustWindowPosition(this, geometry.topLeft(),
|
||||
isUnrestrictedInteractiveMoveResize()));
|
||||
nextMoveResizeGeom = geometry;
|
||||
|
||||
if (!isUnrestrictedInteractiveMoveResize()) {
|
||||
const StrutRects strut = workspace()->restrictedMoveArea(VirtualDesktopManager::self()->currentDesktop());
|
||||
QRegion availableArea(workspace()->clientArea(FullArea, this, workspace()->activeOutput()).toRect());
|
||||
for (const QRect &rect : strut) {
|
||||
availableArea -= rect; // Strut areas
|
||||
}
|
||||
bool transposed = false;
|
||||
int requiredPixels;
|
||||
QRectF bTitleRect = titleBarRect(nextMoveResizeGeom, transposed, requiredPixels);
|
||||
for (;;) {
|
||||
QRectF currentTry = nextMoveResizeGeom;
|
||||
const QRectF titleRect(bTitleRect.translated(currentTry.topLeft()));
|
||||
int visiblePixels = 0;
|
||||
for (const QRect &rect : availableArea) {
|
||||
const QRect r = rect & titleRect.toRect();
|
||||
if ((transposed && r.width() == titleRect.width()) || // Only the full size regions...
|
||||
(!transposed && r.height() == titleRect.height())) { // ...prevents long slim areas
|
||||
visiblePixels += r.width() * r.height();
|
||||
}
|
||||
}
|
||||
if (visiblePixels >= requiredPixels) {
|
||||
break; // We have reached a valid position
|
||||
}
|
||||
|
||||
// (esp.) if there're more screens with different struts (panels) it the titlebar
|
||||
// will be movable outside the movearea (covering one of the panels) until it
|
||||
// crosses the panel "too much" (not enough visiblePixels) and then stucks because
|
||||
// it's usually only pushed by 1px to either direction
|
||||
// so we first check whether we intersect suc strut and move the window below it
|
||||
// immediately (it's still possible to hit the visiblePixels >= titlebarArea break
|
||||
// by moving the window slightly downwards, but it won't stuck)
|
||||
// see bug #274466
|
||||
// and bug #301805 for why we can't just match the titlearea against the screen
|
||||
if (workspace()->outputs().count() > 1) { // optimization
|
||||
// TODO: could be useful on partial screen struts (half-width panels etc.)
|
||||
int newTitleTop = -1;
|
||||
for (const QRect ®ion : strut) {
|
||||
QRectF r = region;
|
||||
if (r.top() == 0 && r.width() > r.height() && // "top panel"
|
||||
r.intersects(currentTry) && currentTry.top() < r.bottom()) {
|
||||
newTitleTop = r.bottom();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newTitleTop > -1) {
|
||||
currentTry.moveTop(newTitleTop); // invalid position, possibly on screen change
|
||||
nextMoveResizeGeom = currentTry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int dx = sign(currentMoveResizeGeom.x() - currentTry.x()),
|
||||
dy = sign(currentMoveResizeGeom.y() - currentTry.y());
|
||||
if (visiblePixels && dx) { // means there's no full width cap -> favor horizontally
|
||||
dy = 0;
|
||||
} else if (dy) {
|
||||
dx = 0;
|
||||
}
|
||||
|
||||
// Move it back
|
||||
currentTry.translate(dx, dy);
|
||||
nextMoveResizeGeom = currentTry;
|
||||
|
||||
// sinces nextMoveResizeGeom is fractional, at best it is within 1 unit of currentMoveResizeGeom
|
||||
if (std::abs(currentMoveResizeGeom.left() - nextMoveResizeGeom.left()) <= 1.0
|
||||
&& std::abs(currentMoveResizeGeom.right() - nextMoveResizeGeom.right()) <= 1.0
|
||||
&& std::abs(currentMoveResizeGeom.top() - nextMoveResizeGeom.top()) <= 1.0
|
||||
&& std::abs(currentMoveResizeGeom.bottom() - nextMoveResizeGeom.bottom()) <= 1.0) {
|
||||
break; // Prevent lockup
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nextMoveResizeGeom;
|
||||
}
|
||||
|
||||
void Window::handleInteractiveMoveResize(qreal x, qreal y, qreal x_root, qreal y_root)
|
||||
{
|
||||
if (isWaitingForInteractiveMoveResizeSync()) {
|
||||
|
@ -1658,7 +1751,6 @@ void Window::handleInteractiveMoveResize(qreal x, qreal y, qreal x_root, qreal y
|
|||
QPointF globalPos(x_root, y_root);
|
||||
// these two points limit the geometry rectangle, i.e. if bottomleft resizing is done,
|
||||
// the bottomleft corner should be at is at (topleft.x(), bottomright().y())
|
||||
QPointF topleft = globalPos - interactiveMoveOffset();
|
||||
const QRectF currentMoveResizeGeom = moveResizeGeometry();
|
||||
QRectF nextMoveResizeGeom = moveResizeGeometry();
|
||||
|
||||
|
@ -1688,85 +1780,7 @@ void Window::handleInteractiveMoveResize(qreal x, qreal y, qreal x_root, qreal y
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// first move, then snap, then check bounds
|
||||
QRectF geometry = nextMoveResizeGeom;
|
||||
geometry.moveTopLeft(topleft);
|
||||
geometry.moveTopLeft(workspace()->adjustWindowPosition(this, geometry.topLeft(),
|
||||
isUnrestrictedInteractiveMoveResize()));
|
||||
nextMoveResizeGeom = geometry;
|
||||
|
||||
if (!isUnrestrictedInteractiveMoveResize()) {
|
||||
const StrutRects strut = workspace()->restrictedMoveArea(VirtualDesktopManager::self()->currentDesktop());
|
||||
QRegion availableArea(workspace()->clientArea(FullArea, this, workspace()->activeOutput()).toRect());
|
||||
for (const QRect &rect : strut) {
|
||||
availableArea -= rect; // Strut areas
|
||||
}
|
||||
bool transposed = false;
|
||||
int requiredPixels;
|
||||
QRectF bTitleRect = titleBarRect(nextMoveResizeGeom, transposed, requiredPixels);
|
||||
for (;;) {
|
||||
QRectF currentTry = nextMoveResizeGeom;
|
||||
const QRect titleRect = bTitleRect.translated(currentTry.topLeft()).toRect();
|
||||
int visiblePixels = 0;
|
||||
for (const QRect &rect : availableArea) {
|
||||
const QRect r = rect & titleRect;
|
||||
if ((transposed && r.width() == titleRect.width()) || // Only the full size regions...
|
||||
(!transposed && r.height() == titleRect.height())) { // ...prevents long slim areas
|
||||
visiblePixels += r.width() * r.height();
|
||||
}
|
||||
}
|
||||
if (visiblePixels >= requiredPixels) {
|
||||
break; // We have reached a valid position
|
||||
}
|
||||
|
||||
// (esp.) if there're more screens with different struts (panels) it the titlebar
|
||||
// will be movable outside the movearea (covering one of the panels) until it
|
||||
// crosses the panel "too much" (not enough visiblePixels) and then stucks because
|
||||
// it's usually only pushed by 1px to either direction
|
||||
// so we first check whether we intersect suc strut and move the window below it
|
||||
// immediately (it's still possible to hit the visiblePixels >= titlebarArea break
|
||||
// by moving the window slightly downwards, but it won't stuck)
|
||||
// see bug #274466
|
||||
// and bug #301805 for why we can't just match the titlearea against the screen
|
||||
if (workspace()->outputs().count() > 1) { // optimization
|
||||
// TODO: could be useful on partial screen struts (half-width panels etc.)
|
||||
int newTitleTop = -1;
|
||||
for (const QRect ®ion : strut) {
|
||||
QRectF r = region;
|
||||
if (r.top() == 0 && r.width() > r.height() && // "top panel"
|
||||
r.intersects(currentTry) && currentTry.top() < r.bottom()) {
|
||||
newTitleTop = r.bottom();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (newTitleTop > -1) {
|
||||
currentTry.moveTop(newTitleTop); // invalid position, possibly on screen change
|
||||
nextMoveResizeGeom = currentTry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int dx = sign(currentMoveResizeGeom.x() - currentTry.x()),
|
||||
dy = sign(currentMoveResizeGeom.y() - currentTry.y());
|
||||
if (visiblePixels && dx) { // means there's no full width cap -> favor horizontally
|
||||
dy = 0;
|
||||
} else if (dy) {
|
||||
dx = 0;
|
||||
}
|
||||
|
||||
// Move it back
|
||||
currentTry.translate(dx, dy);
|
||||
nextMoveResizeGeom = currentTry;
|
||||
|
||||
// sinces nextMoveResizeGeom is fractional, at best it is within 1 unit of currentMoveResizeGeom
|
||||
if (std::abs(currentMoveResizeGeom.left() - nextMoveResizeGeom.left()) <= 1.0
|
||||
&& std::abs(currentMoveResizeGeom.right() - nextMoveResizeGeom.right()) <= 1.0
|
||||
&& std::abs(currentMoveResizeGeom.top() - nextMoveResizeGeom.top()) <= 1.0
|
||||
&& std::abs(currentMoveResizeGeom.bottom() - nextMoveResizeGeom.bottom()) <= 1.0) {
|
||||
break; // Prevent lockup
|
||||
}
|
||||
}
|
||||
}
|
||||
nextMoveResizeGeom = nextInteractiveMoveGeometry(globalPos);
|
||||
}
|
||||
} else {
|
||||
Q_UNREACHABLE();
|
||||
|
|
|
@ -1681,6 +1681,7 @@ protected:
|
|||
void handleInteractiveMoveResize(qreal x, qreal y, qreal x_root, qreal y_root);
|
||||
void handleInteractiveMoveResize(const QPointF &local, const QPointF &global);
|
||||
QRectF titleBarRect(const QRectF &rect, bool &transposed, int &requiredPixels) const;
|
||||
QRectF nextInteractiveMoveGeometry(const QPointF &global) const;
|
||||
QRectF nextInteractiveResizeGeometry(const QPointF &global) const;
|
||||
void dontInteractiveMoveResize();
|
||||
|
||||
|
|
|
@ -2596,7 +2596,7 @@ void Workspace::setActiveCursorOutput(const QPointF &pos)
|
|||
* effective snap zones. When 1.0, it means that the snap zones will be
|
||||
* used without change.
|
||||
*/
|
||||
QPointF Workspace::adjustWindowPosition(Window *window, QPointF pos, bool unrestricted, double snapAdjust)
|
||||
QPointF Workspace::adjustWindowPosition(const Window *window, QPointF pos, bool unrestricted, double snapAdjust) const
|
||||
{
|
||||
QSizeF borderSnapZone(options->borderSnapZone(), options->borderSnapZone());
|
||||
QRectF maxRect;
|
||||
|
|
|
@ -223,7 +223,7 @@ public:
|
|||
void setMoveResizeWindow(Window *window);
|
||||
|
||||
QRectF adjustClientArea(Window *window, const QRectF &area) const;
|
||||
QPointF adjustWindowPosition(Window *window, QPointF pos, bool unrestricted, double snapAdjust = 1.0);
|
||||
QPointF adjustWindowPosition(const Window *window, QPointF pos, bool unrestricted, double snapAdjust = 1.0) const;
|
||||
QRectF adjustWindowSize(const Window *window, QRectF moveResizeGeom, Gravity gravity) const;
|
||||
void raiseWindow(Window *window, bool nogroup = false);
|
||||
void lowerWindow(Window *window, bool nogroup = false);
|
||||
|
|
Loading…
Reference in a new issue