core/popupanchor: pick flip direction based on available width
This commit is contained in:
parent
6bf4826ae7
commit
38ba3fff24
|
@ -1,5 +1,6 @@
|
|||
#include "popupanchor.hpp"
|
||||
|
||||
#include <qcontainerfwd.h>
|
||||
#include <qlogging.h>
|
||||
#include <qobject.h>
|
||||
#include <qsize.h>
|
||||
|
@ -168,20 +169,56 @@ void PopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bool only
|
|||
: anchorEdges.testFlag(Edges::Bottom) ? anchorRectGeometry.bottom()
|
||||
: anchorRectGeometry.center().y();
|
||||
|
||||
auto calcEffectiveX = [&]() {
|
||||
return anchorGravity.testFlag(Edges::Left) ? anchorX - windowGeometry.width() + 1
|
||||
: anchorGravity.testFlag(Edges::Right) ? anchorX
|
||||
auto calcEffectiveX = [&](Edges::Flags anchorGravity, int anchorX) {
|
||||
auto ex = anchorGravity.testFlag(Edges::Left) ? anchorX - windowGeometry.width()
|
||||
: anchorGravity.testFlag(Edges::Right) ? anchorX - 1
|
||||
: anchorX - windowGeometry.width() / 2;
|
||||
|
||||
return ex + 1;
|
||||
};
|
||||
|
||||
auto calcEffectiveY = [&]() {
|
||||
return anchorGravity.testFlag(Edges::Top) ? anchorY - windowGeometry.height() + 1
|
||||
: anchorGravity.testFlag(Edges::Bottom) ? anchorY
|
||||
auto calcEffectiveY = [&](Edges::Flags anchorGravity, int anchorY) {
|
||||
auto ey = anchorGravity.testFlag(Edges::Top) ? anchorY - windowGeometry.height()
|
||||
: anchorGravity.testFlag(Edges::Bottom) ? anchorY - 1
|
||||
: anchorY - windowGeometry.height() / 2;
|
||||
|
||||
return ey + 1;
|
||||
};
|
||||
|
||||
auto effectiveX = calcEffectiveX();
|
||||
auto effectiveY = calcEffectiveY();
|
||||
auto calcRemainingWidth = [&](int effectiveX) {
|
||||
auto width = windowGeometry.width();
|
||||
if (effectiveX < screenGeometry.left()) {
|
||||
auto diff = screenGeometry.left() - effectiveX;
|
||||
effectiveX = screenGeometry.left();
|
||||
width -= diff;
|
||||
}
|
||||
|
||||
auto effectiveX2 = effectiveX + width;
|
||||
if (effectiveX2 > screenGeometry.right()) {
|
||||
width -= effectiveX2 - screenGeometry.right() - 1;
|
||||
}
|
||||
|
||||
return QPair<int, int>(effectiveX, width);
|
||||
};
|
||||
|
||||
auto calcRemainingHeight = [&](int effectiveY) {
|
||||
auto height = windowGeometry.height();
|
||||
if (effectiveY < screenGeometry.left()) {
|
||||
auto diff = screenGeometry.top() - effectiveY;
|
||||
effectiveY = screenGeometry.top();
|
||||
height -= diff;
|
||||
}
|
||||
|
||||
auto effectiveY2 = effectiveY + height;
|
||||
if (effectiveY2 > screenGeometry.bottom()) {
|
||||
height -= effectiveY2 - screenGeometry.bottom() - 1;
|
||||
}
|
||||
|
||||
return QPair<int, int>(effectiveY, height);
|
||||
};
|
||||
|
||||
auto effectiveX = calcEffectiveX(anchorGravity, anchorX);
|
||||
auto effectiveY = calcEffectiveY(anchorGravity, anchorY);
|
||||
|
||||
if (adjustment.testFlag(PopupAdjustment::FlipX)) {
|
||||
const bool flip = (anchorGravity.testFlag(Edges::Left) && effectiveX < screenGeometry.left())
|
||||
|
@ -189,13 +226,22 @@ void PopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bool only
|
|||
&& effectiveX + windowGeometry.width() > screenGeometry.right());
|
||||
|
||||
if (flip) {
|
||||
anchorGravity ^= Edges::Left | Edges::Right;
|
||||
auto newAnchorGravity = anchorGravity ^ (Edges::Left | Edges::Right);
|
||||
|
||||
anchorX = anchorEdges.testFlags(Edges::Left) ? anchorRectGeometry.right()
|
||||
auto newAnchorX = anchorEdges.testFlags(Edges::Left) ? anchorRectGeometry.right()
|
||||
: anchorEdges.testFlags(Edges::Right) ? anchorRectGeometry.left()
|
||||
: anchorX;
|
||||
|
||||
effectiveX = calcEffectiveX();
|
||||
auto newEffectiveX = calcEffectiveX(newAnchorGravity, newAnchorX);
|
||||
|
||||
// TODO IN HL: pick constraint monitor based on anchor rect position in window
|
||||
|
||||
// if the available width when flipped is more than the available width without flipping then flip
|
||||
if (calcRemainingWidth(newEffectiveX).second > calcRemainingWidth(effectiveX).second) {
|
||||
anchorGravity = newAnchorGravity;
|
||||
anchorX = newAnchorX;
|
||||
effectiveX = newEffectiveX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,13 +251,20 @@ void PopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bool only
|
|||
&& effectiveY + windowGeometry.height() > screenGeometry.bottom());
|
||||
|
||||
if (flip) {
|
||||
anchorGravity ^= Edges::Top | Edges::Bottom;
|
||||
auto newAnchorGravity = anchorGravity ^ (Edges::Top | Edges::Bottom);
|
||||
|
||||
anchorY = anchorEdges.testFlags(Edges::Top) ? anchorRectGeometry.bottom()
|
||||
auto newAnchorY = anchorEdges.testFlags(Edges::Top) ? anchorRectGeometry.bottom()
|
||||
: anchorEdges.testFlags(Edges::Bottom) ? anchorRectGeometry.top()
|
||||
: anchorY;
|
||||
|
||||
effectiveY = calcEffectiveY();
|
||||
auto newEffectiveY = calcEffectiveY(newAnchorGravity, newAnchorY);
|
||||
|
||||
// if the available width when flipped is more than the available width without flipping then flip
|
||||
if (calcRemainingHeight(newEffectiveY).second > calcRemainingHeight(effectiveY).second) {
|
||||
anchorGravity = newAnchorGravity;
|
||||
anchorY = newAnchorY;
|
||||
effectiveY = newEffectiveY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,29 +290,15 @@ void PopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bool only
|
|||
}
|
||||
|
||||
if (adjustment.testFlag(PopupAdjustment::ResizeX)) {
|
||||
if (effectiveX < screenGeometry.left()) {
|
||||
auto diff = screenGeometry.left() - effectiveX;
|
||||
effectiveX = screenGeometry.left();
|
||||
width -= diff;
|
||||
}
|
||||
|
||||
auto effectiveX2 = effectiveX + windowGeometry.width();
|
||||
if (effectiveX2 > screenGeometry.right()) {
|
||||
width -= effectiveX2 - screenGeometry.right() - 1;
|
||||
}
|
||||
auto [newX, newWidth] = calcRemainingWidth(effectiveX);
|
||||
effectiveX = newX;
|
||||
width = newWidth;
|
||||
}
|
||||
|
||||
if (adjustment.testFlag(PopupAdjustment::ResizeY)) {
|
||||
if (effectiveY < screenGeometry.top()) {
|
||||
auto diff = screenGeometry.top() - effectiveY;
|
||||
effectiveY = screenGeometry.top();
|
||||
height -= diff;
|
||||
}
|
||||
|
||||
auto effectiveY2 = effectiveY + windowGeometry.height();
|
||||
if (effectiveY2 > screenGeometry.bottom()) {
|
||||
height -= effectiveY2 - screenGeometry.bottom() - 1;
|
||||
}
|
||||
auto [newY, newHeight] = calcRemainingHeight(effectiveY);
|
||||
effectiveY = newY;
|
||||
height = newHeight;
|
||||
}
|
||||
|
||||
window->setGeometry({effectiveX, effectiveY, width, height});
|
||||
|
|
Loading…
Reference in a new issue