core/popupanchor: pick flip direction based on available width
This commit is contained in:
parent
6bf4826ae7
commit
38ba3fff24
1 changed files with 79 additions and 40 deletions
|
@ -1,5 +1,6 @@
|
||||||
#include "popupanchor.hpp"
|
#include "popupanchor.hpp"
|
||||||
|
|
||||||
|
#include <qcontainerfwd.h>
|
||||||
#include <qlogging.h>
|
#include <qlogging.h>
|
||||||
#include <qobject.h>
|
#include <qobject.h>
|
||||||
#include <qsize.h>
|
#include <qsize.h>
|
||||||
|
@ -168,20 +169,56 @@ void PopupPositioner::reposition(PopupAnchor* anchor, QWindow* window, bool only
|
||||||
: anchorEdges.testFlag(Edges::Bottom) ? anchorRectGeometry.bottom()
|
: anchorEdges.testFlag(Edges::Bottom) ? anchorRectGeometry.bottom()
|
||||||
: anchorRectGeometry.center().y();
|
: anchorRectGeometry.center().y();
|
||||||
|
|
||||||
auto calcEffectiveX = [&]() {
|
auto calcEffectiveX = [&](Edges::Flags anchorGravity, int anchorX) {
|
||||||
return anchorGravity.testFlag(Edges::Left) ? anchorX - windowGeometry.width() + 1
|
auto ex = anchorGravity.testFlag(Edges::Left) ? anchorX - windowGeometry.width()
|
||||||
: anchorGravity.testFlag(Edges::Right) ? anchorX
|
: anchorGravity.testFlag(Edges::Right) ? anchorX - 1
|
||||||
: anchorX - windowGeometry.width() / 2;
|
: anchorX - windowGeometry.width() / 2;
|
||||||
|
|
||||||
|
return ex + 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto calcEffectiveY = [&]() {
|
auto calcEffectiveY = [&](Edges::Flags anchorGravity, int anchorY) {
|
||||||
return anchorGravity.testFlag(Edges::Top) ? anchorY - windowGeometry.height() + 1
|
auto ey = anchorGravity.testFlag(Edges::Top) ? anchorY - windowGeometry.height()
|
||||||
: anchorGravity.testFlag(Edges::Bottom) ? anchorY
|
: anchorGravity.testFlag(Edges::Bottom) ? anchorY - 1
|
||||||
: anchorY - windowGeometry.height() / 2;
|
: anchorY - windowGeometry.height() / 2;
|
||||||
|
|
||||||
|
return ey + 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto effectiveX = calcEffectiveX();
|
auto calcRemainingWidth = [&](int effectiveX) {
|
||||||
auto effectiveY = calcEffectiveY();
|
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)) {
|
if (adjustment.testFlag(PopupAdjustment::FlipX)) {
|
||||||
const bool flip = (anchorGravity.testFlag(Edges::Left) && effectiveX < screenGeometry.left())
|
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());
|
&& effectiveX + windowGeometry.width() > screenGeometry.right());
|
||||||
|
|
||||||
if (flip) {
|
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()
|
: anchorEdges.testFlags(Edges::Right) ? anchorRectGeometry.left()
|
||||||
: anchorX;
|
: 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());
|
&& effectiveY + windowGeometry.height() > screenGeometry.bottom());
|
||||||
|
|
||||||
if (flip) {
|
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()
|
: anchorEdges.testFlags(Edges::Bottom) ? anchorRectGeometry.top()
|
||||||
: anchorY;
|
: 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 (adjustment.testFlag(PopupAdjustment::ResizeX)) {
|
||||||
if (effectiveX < screenGeometry.left()) {
|
auto [newX, newWidth] = calcRemainingWidth(effectiveX);
|
||||||
auto diff = screenGeometry.left() - effectiveX;
|
effectiveX = newX;
|
||||||
effectiveX = screenGeometry.left();
|
width = newWidth;
|
||||||
width -= diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto effectiveX2 = effectiveX + windowGeometry.width();
|
|
||||||
if (effectiveX2 > screenGeometry.right()) {
|
|
||||||
width -= effectiveX2 - screenGeometry.right() - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (adjustment.testFlag(PopupAdjustment::ResizeY)) {
|
if (adjustment.testFlag(PopupAdjustment::ResizeY)) {
|
||||||
if (effectiveY < screenGeometry.top()) {
|
auto [newY, newHeight] = calcRemainingHeight(effectiveY);
|
||||||
auto diff = screenGeometry.top() - effectiveY;
|
effectiveY = newY;
|
||||||
effectiveY = screenGeometry.top();
|
height = newHeight;
|
||||||
height -= diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto effectiveY2 = effectiveY + windowGeometry.height();
|
|
||||||
if (effectiveY2 > screenGeometry.bottom()) {
|
|
||||||
height -= effectiveY2 - screenGeometry.bottom() - 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
window->setGeometry({effectiveX, effectiveY, width, height});
|
window->setGeometry({effectiveX, effectiveY, width, height});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue