mirror of https://github.com/procxx/kepka.git
Implement complex PiP movement.
This commit is contained in:
parent
a73520c9d8
commit
7a6052db81
|
@ -61,48 +61,62 @@ constexpr auto kPipLoaderPriority = 2;
|
||||||
return inner.topLeft() + QPoint(shiftx, shifty);
|
return inner.topLeft() + QPoint(shiftx, shifty);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] QRect Transformed(QRect original, QPoint delta, RectPart by) {
|
[[nodiscard]] QRect Transformed(
|
||||||
const auto min = st::pipMinimalSize;
|
QRect original,
|
||||||
|
QSize minimalSize,
|
||||||
|
QSize maximalSize,
|
||||||
|
QPoint delta,
|
||||||
|
RectPart by) {
|
||||||
const auto width = original.width();
|
const auto width = original.width();
|
||||||
const auto height = original.height();
|
const auto height = original.height();
|
||||||
const auto maxx = width - min;
|
const auto x1 = width - minimalSize.width();
|
||||||
const auto maxy = height - min;
|
const auto x2 = maximalSize.width() - width;
|
||||||
|
const auto y1 = height - minimalSize.height();
|
||||||
|
const auto y2 = maximalSize.height() - height;
|
||||||
switch (by) {
|
switch (by) {
|
||||||
case RectPart::Center: return original.translated(delta);
|
case RectPart::Center: return original.translated(delta);
|
||||||
case RectPart::TopLeft:
|
case RectPart::TopLeft:
|
||||||
original.setTop(original.y() + std::min(delta.y(), maxy));
|
original.setTop(original.y() + std::clamp(delta.y(), -y2, y1));
|
||||||
original.setLeft(original.x() + std::min(delta.x(), maxx));
|
original.setLeft(original.x() + std::clamp(delta.x(), -x2, x1));
|
||||||
return original;
|
return original;
|
||||||
case RectPart::TopRight:
|
case RectPart::TopRight:
|
||||||
original.setTop(original.y() + std::min(delta.y(), maxy));
|
original.setTop(original.y() + std::clamp(delta.y(), -y2, y1));
|
||||||
original.setWidth(original.width() + std::max(delta.x(), -maxx));
|
original.setWidth(original.width() + std::clamp(delta.x(), -x1, x2));
|
||||||
return original;
|
return original;
|
||||||
case RectPart::BottomRight:
|
case RectPart::BottomRight:
|
||||||
original.setHeight(original.height() + std::max(delta.y(), -maxy));
|
original.setHeight(
|
||||||
original.setWidth(original.width() + std::max(delta.x(), -maxx));
|
original.height() + std::clamp(delta.y(), -y1, y2));
|
||||||
|
original.setWidth(original.width() + std::clamp(delta.x(), -x1, x2));
|
||||||
return original;
|
return original;
|
||||||
case RectPart::BottomLeft:
|
case RectPart::BottomLeft:
|
||||||
original.setHeight(original.height() + std::max(delta.y(), -maxy));
|
original.setHeight(
|
||||||
original.setLeft(original.x() + std::min(delta.x(), maxx));
|
original.height() + std::clamp(delta.y(), -y1, y2));
|
||||||
|
original.setLeft(original.x() + std::clamp(delta.x(), -x2, x1));
|
||||||
return original;
|
return original;
|
||||||
case RectPart::Left:
|
case RectPart::Left:
|
||||||
original.setLeft(original.x() + std::min(delta.x(), maxx));
|
original.setLeft(original.x() + std::clamp(delta.x(), -x2, x1));
|
||||||
return original;
|
return original;
|
||||||
case RectPart::Top:
|
case RectPart::Top:
|
||||||
original.setTop(original.y() + std::min(delta.y(), maxy));
|
original.setTop(original.y() + std::clamp(delta.y(), -y2, y1));
|
||||||
return original;
|
return original;
|
||||||
case RectPart::Right:
|
case RectPart::Right:
|
||||||
original.setWidth(original.width() + std::max(delta.x(), -maxx));
|
original.setWidth(original.width() + std::clamp(delta.x(), -x1, x2));
|
||||||
return original;
|
return original;
|
||||||
case RectPart::Bottom:
|
case RectPart::Bottom:
|
||||||
original.setHeight(original.height() + std::max(delta.y(), -maxy));
|
original.setHeight(
|
||||||
|
original.height() + std::clamp(delta.y(), -y1, y2));
|
||||||
return original;
|
return original;
|
||||||
}
|
}
|
||||||
return original;
|
return original;
|
||||||
Unexpected("RectPart in PiP Transformed.");
|
Unexpected("RectPart in PiP Transformed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] QRect Constrained(QRect original, QSize ratio, RectPart by) {
|
[[nodiscard]] QRect Constrained(
|
||||||
|
QRect original,
|
||||||
|
QSize minimalSize,
|
||||||
|
QSize maximalSize,
|
||||||
|
QSize ratio,
|
||||||
|
RectPart by) {
|
||||||
if (by == RectPart::Center) {
|
if (by == RectPart::Center) {
|
||||||
return original;
|
return original;
|
||||||
} else if (!original.width() && !original.height()) {
|
} else if (!original.width() && !original.height()) {
|
||||||
|
@ -110,7 +124,7 @@ constexpr auto kPipLoaderPriority = 2;
|
||||||
}
|
}
|
||||||
const auto widthLarger = (original.width() * ratio.height())
|
const auto widthLarger = (original.width() * ratio.height())
|
||||||
> (original.height() * ratio.width());
|
> (original.height() * ratio.width());
|
||||||
const auto newSize = ratio.scaled(
|
const auto desiredSize = ratio.scaled(
|
||||||
original.size(),
|
original.size(),
|
||||||
(((RectParts(by) & RectPart::AllCorners)
|
(((RectParts(by) & RectPart::AllCorners)
|
||||||
|| ((by == RectPart::Top || by == RectPart::Bottom)
|
|| ((by == RectPart::Top || by == RectPart::Bottom)
|
||||||
|
@ -119,6 +133,15 @@ constexpr auto kPipLoaderPriority = 2;
|
||||||
&& !widthLarger))
|
&& !widthLarger))
|
||||||
? Qt::KeepAspectRatio
|
? Qt::KeepAspectRatio
|
||||||
: Qt::KeepAspectRatioByExpanding));
|
: Qt::KeepAspectRatioByExpanding));
|
||||||
|
const auto newSize = QSize(
|
||||||
|
std::clamp(
|
||||||
|
desiredSize.width(),
|
||||||
|
minimalSize.width(),
|
||||||
|
maximalSize.width()),
|
||||||
|
std::clamp(
|
||||||
|
desiredSize.height(),
|
||||||
|
minimalSize.height(),
|
||||||
|
maximalSize.height()));
|
||||||
switch (by) {
|
switch (by) {
|
||||||
case RectPart::TopLeft:
|
case RectPart::TopLeft:
|
||||||
return QRect(
|
return QRect(
|
||||||
|
@ -280,15 +303,15 @@ void PipPanel::setPositionOnScreen(Position position, QRect available) {
|
||||||
: QSize(max * _ratio.width() / _ratio.height(), max);
|
: QSize(max * _ratio.width() / _ratio.height(), max);
|
||||||
|
|
||||||
// At least one side should not be greater than half of screen size.
|
// At least one side should not be greater than half of screen size.
|
||||||
const auto byHeight = (scaled.width() * screen.height())
|
const auto byWidth = (scaled.width() * screen.height())
|
||||||
> (scaled.height() * screen.width());
|
> (scaled.height() * screen.width());
|
||||||
const auto fit = QSize(screen.width() / 2, screen.height() / 2);
|
const auto fit = QSize(screen.width() / 2, screen.height() / 2);
|
||||||
const auto normalized = (byHeight && scaled.height() > fit.height())
|
const auto normalized = (byWidth && scaled.width() > fit.width())
|
||||||
|
? QSize(fit.width(), fit.width() * scaled.height() / scaled.width())
|
||||||
|
: (!byWidth && scaled.height() > fit.height())
|
||||||
? QSize(
|
? QSize(
|
||||||
fit.height() * scaled.width() / scaled.height(),
|
fit.height() * scaled.width() / scaled.height(),
|
||||||
fit.height())
|
fit.height())
|
||||||
: (!byHeight && scaled.width() > fit.width())
|
|
||||||
? QSize(fit.width(), fit.width() * scaled.height() / scaled.width())
|
|
||||||
: scaled;
|
: scaled;
|
||||||
|
|
||||||
// Apply minimal size.
|
// Apply minimal size.
|
||||||
|
@ -339,8 +362,7 @@ void PipPanel::paintEvent(QPaintEvent *e) {
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
|
|
||||||
auto request = FrameRequest();
|
auto request = FrameRequest();
|
||||||
request.outer = size();
|
request.resize = request.outer = size();
|
||||||
request.resize = _ratio.scaled(request.outer, Qt::KeepAspectRatio);
|
|
||||||
request.corners = RectPart(0)
|
request.corners = RectPart(0)
|
||||||
| ((_attached & (RectPart::Left | RectPart::Top))
|
| ((_attached & (RectPart::Left | RectPart::Top))
|
||||||
? RectPart(0)
|
? RectPart(0)
|
||||||
|
@ -446,7 +468,8 @@ void PipPanel::updatePosition(QPoint point) {
|
||||||
Expects(_dragStartGeometry.has_value());
|
Expects(_dragStartGeometry.has_value());
|
||||||
Expects(_pressState.has_value());
|
Expects(_pressState.has_value());
|
||||||
|
|
||||||
const auto screen = (*_pressState == RectPart::Center)
|
const auto dragPart = *_pressState;
|
||||||
|
const auto screen = (dragPart == RectPart::Center)
|
||||||
? ScreenFromPosition(point)
|
? ScreenFromPosition(point)
|
||||||
: myScreen()
|
: myScreen()
|
||||||
? myScreen()->availableGeometry()
|
? myScreen()->availableGeometry()
|
||||||
|
@ -454,18 +477,35 @@ void PipPanel::updatePosition(QPoint point) {
|
||||||
if (screen.isEmpty()) {
|
if (screen.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const auto minimalSize = _ratio.scaled(
|
||||||
|
st::pipMinimalSize,
|
||||||
|
st::pipMinimalSize,
|
||||||
|
Qt::KeepAspectRatioByExpanding);
|
||||||
|
const auto maximalSize = _ratio.scaled(
|
||||||
|
screen.width() / 2,
|
||||||
|
screen.height() / 2,
|
||||||
|
Qt::KeepAspectRatio);
|
||||||
const auto geometry = Transformed(
|
const auto geometry = Transformed(
|
||||||
*_dragStartGeometry,
|
*_dragStartGeometry,
|
||||||
|
minimalSize,
|
||||||
|
maximalSize,
|
||||||
point - _pressPoint,
|
point - _pressPoint,
|
||||||
*_pressState);
|
dragPart);
|
||||||
const auto valid = Constrained(geometry, _ratio, *_pressState);
|
const auto valid = Constrained(
|
||||||
//const auto clamped = ClampToEdges(screen, valid);
|
geometry,
|
||||||
//if (clamped != position) {
|
minimalSize,
|
||||||
// moveAnimated(clamped);
|
maximalSize,
|
||||||
//} else {
|
_ratio,
|
||||||
|
dragPart);
|
||||||
|
const auto clamped = (dragPart == RectPart::Center)
|
||||||
|
? ClampToEdges(screen, valid)
|
||||||
|
: valid.topLeft();
|
||||||
|
if (clamped != valid.topLeft()) {
|
||||||
|
moveAnimated(clamped);
|
||||||
|
} else {
|
||||||
_positionAnimation.stop();
|
_positionAnimation.stop();
|
||||||
setGeometry(valid);
|
setGeometry(valid);
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PipPanel::finishDrag(QPoint point) {
|
void PipPanel::finishDrag(QPoint point) {
|
||||||
|
|
Loading…
Reference in New Issue