mirror of
https://github.com/Chatterino/chatterino2.git
synced 2024-11-13 19:49:51 +01:00
Fix tooltip & popup positioning (#4740)
* Fix tooltip & popup positioning This tries to ensure the tooltip & popups are created on the correct monitor * Add changelog entry * Clean up debug output * Use the full frame geometry to figure out screen bound movements * Remove the now-unused `setStayInScreenRect` function * Change the UserInfoPopup offset to be based on its width & height instead * Remove more debug output
This commit is contained in:
parent
b98be3b0f3
commit
9e2eb0dd29
|
@ -28,6 +28,7 @@
|
||||||
- Bugfix: Fix visual glitches with smooth scrolling. (#4501)
|
- Bugfix: Fix visual glitches with smooth scrolling. (#4501)
|
||||||
- Bugfix: Fixed pings firing for the "Your username" highlight when not signed in. (#4698)
|
- Bugfix: Fixed pings firing for the "Your username" highlight when not signed in. (#4698)
|
||||||
- Bugfix: Fixed partially broken filters on Qt 6 builds. (#4702)
|
- Bugfix: Fixed partially broken filters on Qt 6 builds. (#4702)
|
||||||
|
- Bugfix: Fixed tooltips & popups sometimes showing up on the wrong monitor. (#4740)
|
||||||
- Bugfix: Fixed some network errors having `0` as their HTTP status. (#4704)
|
- Bugfix: Fixed some network errors having `0` as their HTTP status. (#4704)
|
||||||
- Bugfix: Fixed crash that could occurr when closing the usercard too quickly after blocking or unblocking a user. (#4711)
|
- Bugfix: Fixed crash that could occurr when closing the usercard too quickly after blocking or unblocking a user. (#4711)
|
||||||
- Bugfix: Fixed highlights sometimes not working after changing sound device, or switching users in your operating system. (#4729)
|
- Bugfix: Fixed highlights sometimes not working after changing sound device, or switching users in your operating system. (#4729)
|
||||||
|
|
|
@ -923,7 +923,8 @@ void CommandController::initialize(Settings &, Paths &paths)
|
||||||
static_cast<QWidget *>(&(getApp()->windows->getMainWindow())),
|
static_cast<QWidget *>(&(getApp()->windows->getMainWindow())),
|
||||||
currentSplit);
|
currentSplit);
|
||||||
userPopup->setData(userName, channel);
|
userPopup->setData(userName, channel);
|
||||||
userPopup->move(QCursor::pos());
|
userPopup->moveTo(QCursor::pos(), false,
|
||||||
|
BaseWindow::BoundsChecker::CursorPosition);
|
||||||
userPopup->show();
|
userPopup->show();
|
||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "widgets/helper/EffectLabel.hpp"
|
#include "widgets/helper/EffectLabel.hpp"
|
||||||
#include "widgets/Label.hpp"
|
#include "widgets/Label.hpp"
|
||||||
#include "widgets/TooltipWidget.hpp"
|
#include "widgets/TooltipWidget.hpp"
|
||||||
|
#include "widgets/Window.hpp"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QFont>
|
#include <QFont>
|
||||||
|
@ -240,18 +241,6 @@ void BaseWindow::init()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWindow::setStayInScreenRect(bool value)
|
|
||||||
{
|
|
||||||
this->stayInScreenRect_ = value;
|
|
||||||
|
|
||||||
this->moveIntoDesktopRect(this->pos());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BaseWindow::getStayInScreenRect() const
|
|
||||||
{
|
|
||||||
return this->stayInScreenRect_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BaseWindow::setActionOnFocusLoss(ActionOnFocusLoss value)
|
void BaseWindow::setActionOnFocusLoss(ActionOnFocusLoss value)
|
||||||
{
|
{
|
||||||
this->actionOnFocusLoss_ = value;
|
this->actionOnFocusLoss_ = value;
|
||||||
|
@ -514,7 +503,7 @@ void BaseWindow::leaveEvent(QEvent *)
|
||||||
TooltipWidget::instance()->hide();
|
TooltipWidget::instance()->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWindow::moveTo(QWidget *parent, QPoint point, bool offset)
|
void BaseWindow::moveTo(QPoint point, bool offset, BoundsChecker boundsChecker)
|
||||||
{
|
{
|
||||||
if (offset)
|
if (offset)
|
||||||
{
|
{
|
||||||
|
@ -522,7 +511,26 @@ void BaseWindow::moveTo(QWidget *parent, QPoint point, bool offset)
|
||||||
point.ry() += 16;
|
point.ry() += 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->moveIntoDesktopRect(point);
|
switch (boundsChecker)
|
||||||
|
{
|
||||||
|
case BoundsChecker::Off: {
|
||||||
|
// The bounds checker is off, *just* move the window
|
||||||
|
this->move(point);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BoundsChecker::CursorPosition: {
|
||||||
|
// The bounds checker is on, use the cursor position as the origin
|
||||||
|
this->moveWithinScreen(point, QCursor::pos());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BoundsChecker::DesiredPosition: {
|
||||||
|
// The bounds checker is on, use the desired position as the origin
|
||||||
|
this->moveWithinScreen(point, point);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWindow::resizeEvent(QResizeEvent *)
|
void BaseWindow::resizeEvent(QResizeEvent *)
|
||||||
|
@ -576,24 +584,13 @@ void BaseWindow::closeEvent(QCloseEvent *)
|
||||||
|
|
||||||
void BaseWindow::showEvent(QShowEvent *)
|
void BaseWindow::showEvent(QShowEvent *)
|
||||||
{
|
{
|
||||||
this->moveIntoDesktopRect(this->pos());
|
|
||||||
if (this->frameless_)
|
|
||||||
{
|
|
||||||
QTimer::singleShot(30, this, [this] {
|
|
||||||
this->moveIntoDesktopRect(this->pos());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseWindow::moveIntoDesktopRect(QPoint point)
|
void BaseWindow::moveWithinScreen(QPoint point, QPoint origin)
|
||||||
{
|
{
|
||||||
if (!this->stayInScreenRect_)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// move the widget into the screen geometry if it's not already in there
|
// move the widget into the screen geometry if it's not already in there
|
||||||
auto *screen = QApplication::screenAt(point);
|
auto *screen = QApplication::screenAt(origin);
|
||||||
|
|
||||||
if (screen == nullptr)
|
if (screen == nullptr)
|
||||||
{
|
{
|
||||||
screen = QApplication::primaryScreen();
|
screen = QApplication::primaryScreen();
|
||||||
|
@ -603,6 +600,9 @@ void BaseWindow::moveIntoDesktopRect(QPoint point)
|
||||||
bool stickRight = false;
|
bool stickRight = false;
|
||||||
bool stickBottom = false;
|
bool stickBottom = false;
|
||||||
|
|
||||||
|
const auto w = this->frameGeometry().width();
|
||||||
|
const auto h = this->frameGeometry().height();
|
||||||
|
|
||||||
if (point.x() < bounds.left())
|
if (point.x() < bounds.left())
|
||||||
{
|
{
|
||||||
point.setX(bounds.left());
|
point.setX(bounds.left());
|
||||||
|
@ -611,15 +611,15 @@ void BaseWindow::moveIntoDesktopRect(QPoint point)
|
||||||
{
|
{
|
||||||
point.setY(bounds.top());
|
point.setY(bounds.top());
|
||||||
}
|
}
|
||||||
if (point.x() + this->width() > bounds.right())
|
if (point.x() + w > bounds.right())
|
||||||
{
|
{
|
||||||
stickRight = true;
|
stickRight = true;
|
||||||
point.setX(bounds.right() - this->width());
|
point.setX(bounds.right() - w);
|
||||||
}
|
}
|
||||||
if (point.y() + this->height() > bounds.bottom())
|
if (point.y() + h > bounds.bottom())
|
||||||
{
|
{
|
||||||
stickBottom = true;
|
stickBottom = true;
|
||||||
point.setY(bounds.bottom() - this->height());
|
point.setY(bounds.bottom() - h);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stickRight && stickBottom)
|
if (stickRight && stickBottom)
|
||||||
|
|
|
@ -36,6 +36,17 @@ public:
|
||||||
DisableLayoutSave = 128,
|
DisableLayoutSave = 128,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class BoundsChecker {
|
||||||
|
// Don't attempt to do any "stay in screen" stuff, just move me!
|
||||||
|
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,
|
||||||
|
};
|
||||||
|
|
||||||
enum ActionOnFocusLoss { Nothing, Delete, Close, Hide };
|
enum ActionOnFocusLoss { Nothing, Delete, Close, Hide };
|
||||||
|
|
||||||
explicit BaseWindow(FlagsEnum<Flags> flags_ = None,
|
explicit BaseWindow(FlagsEnum<Flags> flags_ = None,
|
||||||
|
@ -51,15 +62,12 @@ public:
|
||||||
std::function<void()> onClicked);
|
std::function<void()> onClicked);
|
||||||
EffectLabel *addTitleBarLabel(std::function<void()> onClicked);
|
EffectLabel *addTitleBarLabel(std::function<void()> onClicked);
|
||||||
|
|
||||||
void setStayInScreenRect(bool value);
|
|
||||||
bool getStayInScreenRect() const;
|
|
||||||
|
|
||||||
void setActionOnFocusLoss(ActionOnFocusLoss value);
|
void setActionOnFocusLoss(ActionOnFocusLoss value);
|
||||||
ActionOnFocusLoss getActionOnFocusLoss() const;
|
ActionOnFocusLoss getActionOnFocusLoss() const;
|
||||||
|
|
||||||
void moveTo(QWidget *widget, QPoint point, bool offset = true);
|
void moveTo(QPoint point, bool offset, BoundsChecker boundsChecker);
|
||||||
|
|
||||||
virtual float scale() const override;
|
float scale() const override;
|
||||||
float qtFontScale() const;
|
float qtFontScale() const;
|
||||||
|
|
||||||
pajlada::Signals::NoArgSignal closing;
|
pajlada::Signals::NoArgSignal closing;
|
||||||
|
@ -101,7 +109,12 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init();
|
||||||
void moveIntoDesktopRect(QPoint point);
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
void moveWithinScreen(QPoint point, QPoint origin);
|
||||||
|
|
||||||
void calcButtonsSizes();
|
void calcButtonsSizes();
|
||||||
void drawCustomWindowFrame(QPainter &painter);
|
void drawCustomWindowFrame(QPainter &painter);
|
||||||
void onFocusLost();
|
void onFocusLost();
|
||||||
|
@ -121,7 +134,6 @@ private:
|
||||||
bool enableCustomFrame_;
|
bool enableCustomFrame_;
|
||||||
ActionOnFocusLoss actionOnFocusLoss_ = Nothing;
|
ActionOnFocusLoss actionOnFocusLoss_ = Nothing;
|
||||||
bool frameless_;
|
bool frameless_;
|
||||||
bool stayInScreenRect_ = false;
|
|
||||||
bool shown_ = false;
|
bool shown_ = false;
|
||||||
FlagsEnum<Flags> flags_;
|
FlagsEnum<Flags> flags_;
|
||||||
float nativeScale_ = 1;
|
float nativeScale_ = 1;
|
||||||
|
|
|
@ -27,8 +27,6 @@ TooltipWidget::TooltipWidget(BaseWidget *parent)
|
||||||
this->setAttribute(Qt::WA_TranslucentBackground);
|
this->setAttribute(Qt::WA_TranslucentBackground);
|
||||||
this->setWindowFlag(Qt::WindowStaysOnTopHint, true);
|
this->setWindowFlag(Qt::WindowStaysOnTopHint, true);
|
||||||
|
|
||||||
this->setStayInScreenRect(true);
|
|
||||||
|
|
||||||
// Default to using vertical layout
|
// Default to using vertical layout
|
||||||
this->initializeVLayout();
|
this->initializeVLayout();
|
||||||
this->setLayout(this->vLayout_);
|
this->setLayout(this->vLayout_);
|
||||||
|
|
|
@ -206,8 +206,9 @@ EmotePopup::EmotePopup(QWidget *parent)
|
||||||
, search_(new QLineEdit())
|
, search_(new QLineEdit())
|
||||||
, notebook_(new Notebook(this))
|
, notebook_(new Notebook(this))
|
||||||
{
|
{
|
||||||
this->setStayInScreenRect(true);
|
// this->setStayInScreenRect(true);
|
||||||
this->moveTo(this, getApp()->windows->emotePopupPos(), false);
|
this->moveTo(getApp()->windows->emotePopupPos(), false,
|
||||||
|
BaseWindow::BoundsChecker::DesiredPosition);
|
||||||
|
|
||||||
auto *layout = new QVBoxLayout();
|
auto *layout = new QVBoxLayout();
|
||||||
this->getLayoutContainer()->setLayout(layout);
|
this->getLayoutContainer()->setLayout(layout);
|
||||||
|
|
|
@ -29,7 +29,6 @@ ReplyThreadPopup::ReplyThreadPopup(bool closeAutomatically, QWidget *parent,
|
||||||
, split_(split)
|
, split_(split)
|
||||||
{
|
{
|
||||||
this->setWindowTitle(QStringLiteral("Reply Thread"));
|
this->setWindowTitle(QStringLiteral("Reply Thread"));
|
||||||
this->setStayInScreenRect(true);
|
|
||||||
|
|
||||||
HotkeyController::HotkeyMap actions{
|
HotkeyController::HotkeyMap actions{
|
||||||
{"delete",
|
{"delete",
|
||||||
|
|
|
@ -142,7 +142,6 @@ UserInfoPopup::UserInfoPopup(bool closeAutomatically, QWidget *parent,
|
||||||
assert(split != nullptr &&
|
assert(split != nullptr &&
|
||||||
"split being nullptr causes lots of bugs down the road");
|
"split being nullptr causes lots of bugs down the road");
|
||||||
this->setWindowTitle("Usercard");
|
this->setWindowTitle("Usercard");
|
||||||
this->setStayInScreenRect(true);
|
|
||||||
|
|
||||||
HotkeyController::HotkeyMap actions{
|
HotkeyController::HotkeyMap actions{
|
||||||
{"delete",
|
{"delete",
|
||||||
|
@ -715,9 +714,6 @@ void UserInfoPopup::setData(const QString &name,
|
||||||
this->userStateChanged_.invoke();
|
this->userStateChanged_.invoke();
|
||||||
|
|
||||||
this->updateLatestMessages();
|
this->updateLatestMessages();
|
||||||
QTimer::singleShot(1, this, [this] {
|
|
||||||
this->setStayInScreenRect(true);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UserInfoPopup::updateLatestMessages()
|
void UserInfoPopup::updateLatestMessages()
|
||||||
|
|
|
@ -46,7 +46,6 @@ QuickSwitcherPopup::QuickSwitcherPopup(QWidget *parent)
|
||||||
|
|
||||||
this->initWidgets();
|
this->initWidgets();
|
||||||
|
|
||||||
this->setStayInScreenRect(true);
|
|
||||||
const QRect geom = parent->geometry();
|
const QRect geom = parent->geometry();
|
||||||
// This places the popup in the middle of the parent widget
|
// This places the popup in the middle of the parent widget
|
||||||
this->setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter,
|
this->setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter,
|
||||||
|
|
|
@ -1810,7 +1810,8 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tooltipWidget->moveTo(this, event->globalPos());
|
tooltipWidget->moveTo(event->globalPos(), true,
|
||||||
|
BaseWindow::BoundsChecker::CursorPosition);
|
||||||
tooltipWidget->setWordWrap(isLinkValid);
|
tooltipWidget->setWordWrap(isLinkValid);
|
||||||
tooltipWidget->show();
|
tooltipWidget->show();
|
||||||
}
|
}
|
||||||
|
@ -2663,8 +2664,9 @@ void ChannelView::showUserInfoPopup(const QString &userName,
|
||||||
: this->underlyingChannel_;
|
: this->underlyingChannel_;
|
||||||
userPopup->setData(userName, contextChannel, openingChannel);
|
userPopup->setData(userName, contextChannel, openingChannel);
|
||||||
|
|
||||||
QPoint offset(int(150 * this->scale()), int(70 * this->scale()));
|
QPoint offset(userPopup->width() / 3, userPopup->height() / 5);
|
||||||
userPopup->move(QCursor::pos() - offset);
|
userPopup->moveTo(QCursor::pos() - offset, false,
|
||||||
|
BaseWindow::BoundsChecker::CursorPosition);
|
||||||
userPopup->show();
|
userPopup->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -964,7 +964,7 @@ void SplitHeader::enterEvent(QEvent *event)
|
||||||
auto pos = this->mapToGlobal(this->rect().bottomLeft()) +
|
auto pos = this->mapToGlobal(this->rect().bottomLeft()) +
|
||||||
QPoint((this->width() - tooltip->width()) / 2, 1);
|
QPoint((this->width() - tooltip->width()) / 2, 1);
|
||||||
|
|
||||||
tooltip->moveTo(this, pos, false);
|
tooltip->moveTo(pos, false, BaseWindow::BoundsChecker::CursorPosition);
|
||||||
tooltip->show();
|
tooltip->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue