Allow any window to be bounds-checked (#4802)

Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
nerix
2023-09-24 15:32:43 +02:00
committed by GitHub
parent 37009e8e6b
commit 783c7530f3
9 changed files with 122 additions and 88 deletions
+82
View File
@@ -0,0 +1,82 @@
#include "util/WidgetHelpers.hpp"
#include <QCursor>
#include <QGuiApplication>
#include <QPoint>
#include <QScreen>
#include <QWidget>
namespace {
/// Move the `window` into the `screen` geometry if it's not already in there.
void moveWithinScreen(QWidget *window, QScreen *screen, QPoint point)
{
if (screen == nullptr)
{
screen = QGuiApplication::primaryScreen();
}
const QRect bounds = screen->availableGeometry();
bool stickRight = false;
bool stickBottom = false;
const auto w = window->frameGeometry().width();
const auto h = window->frameGeometry().height();
if (point.x() < bounds.left())
{
point.setX(bounds.left());
}
if (point.y() < bounds.top())
{
point.setY(bounds.top());
}
if (point.x() + w > bounds.right())
{
stickRight = true;
point.setX(bounds.right() - w);
}
if (point.y() + h > bounds.bottom())
{
stickBottom = true;
point.setY(bounds.bottom() - h);
}
if (stickRight && stickBottom)
{
const QPoint globalCursorPos = QCursor::pos();
point.setY(globalCursorPos.y() - window->height() - 16);
}
window->move(point);
}
} // namespace
namespace chatterino::widgets {
void moveWindowTo(QWidget *window, QPoint position, BoundsChecking mode)
{
switch (mode)
{
case BoundsChecking::Off: {
window->move(position);
}
break;
case BoundsChecking::CursorPosition: {
moveWithinScreen(window, QGuiApplication::screenAt(QCursor::pos()),
position);
}
break;
case BoundsChecking::DesiredPosition: {
moveWithinScreen(window, QGuiApplication::screenAt(position),
position);
}
break;
}
}
} // namespace chatterino::widgets
+29
View File
@@ -0,0 +1,29 @@
#pragma once
class QWidget;
class QPoint;
class QScreen;
namespace chatterino::widgets {
enum class BoundsChecking {
/// Don't do any bounds checking (equivalent to `QWidget::move`).
Off,
/// Attempt to keep the window within bounds of the screen the cursor is on.
CursorPosition,
/// Attempt to keep the window within bounds of the screen the desired position is on.
DesiredPosition,
};
/// Moves the `window` to the (global) `position`
/// while doing bounds-checking according to `mode` to ensure the window stays on one screen.
///
/// @param window The window to move.
/// @param position The global position to move the window to.
/// @param mode The desired bounds checking.
void moveWindowTo(QWidget *window, QPoint position,
BoundsChecking mode = BoundsChecking::DesiredPosition);
} // namespace chatterino::widgets