diff --git a/CHANGELOG.md b/CHANGELOG.md index cc7fadb58..47422626d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ - Bugfix: Fix visual glitches with smooth scrolling. (#4501) - 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 tooltips & popups sometimes showing up on the wrong monitor. (#4740) - 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 highlights sometimes not working after changing sound device, or switching users in your operating system. (#4729) diff --git a/src/controllers/commands/CommandController.cpp b/src/controllers/commands/CommandController.cpp index 62da0b83b..fa1255a9a 100644 --- a/src/controllers/commands/CommandController.cpp +++ b/src/controllers/commands/CommandController.cpp @@ -923,7 +923,8 @@ void CommandController::initialize(Settings &, Paths &paths) static_cast(&(getApp()->windows->getMainWindow())), currentSplit); userPopup->setData(userName, channel); - userPopup->move(QCursor::pos()); + userPopup->moveTo(QCursor::pos(), false, + BaseWindow::BoundsChecker::CursorPosition); userPopup->show(); return ""; }); diff --git a/src/widgets/BaseWindow.cpp b/src/widgets/BaseWindow.cpp index 60365081e..f02cdf472 100644 --- a/src/widgets/BaseWindow.cpp +++ b/src/widgets/BaseWindow.cpp @@ -10,6 +10,7 @@ #include "widgets/helper/EffectLabel.hpp" #include "widgets/Label.hpp" #include "widgets/TooltipWidget.hpp" +#include "widgets/Window.hpp" #include #include @@ -240,18 +241,6 @@ void BaseWindow::init() #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) { this->actionOnFocusLoss_ = value; @@ -514,7 +503,7 @@ void BaseWindow::leaveEvent(QEvent *) TooltipWidget::instance()->hide(); } -void BaseWindow::moveTo(QWidget *parent, QPoint point, bool offset) +void BaseWindow::moveTo(QPoint point, bool offset, BoundsChecker boundsChecker) { if (offset) { @@ -522,7 +511,26 @@ void BaseWindow::moveTo(QWidget *parent, QPoint point, bool offset) 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 *) @@ -576,24 +584,13 @@ void BaseWindow::closeEvent(QCloseEvent *) 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 - auto *screen = QApplication::screenAt(point); + auto *screen = QApplication::screenAt(origin); + if (screen == nullptr) { screen = QApplication::primaryScreen(); @@ -603,6 +600,9 @@ void BaseWindow::moveIntoDesktopRect(QPoint point) bool stickRight = false; bool stickBottom = false; + const auto w = this->frameGeometry().width(); + const auto h = this->frameGeometry().height(); + if (point.x() < bounds.left()) { point.setX(bounds.left()); @@ -611,15 +611,15 @@ void BaseWindow::moveIntoDesktopRect(QPoint point) { point.setY(bounds.top()); } - if (point.x() + this->width() > bounds.right()) + if (point.x() + w > bounds.right()) { 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; - point.setY(bounds.bottom() - this->height()); + point.setY(bounds.bottom() - h); } if (stickRight && stickBottom) diff --git a/src/widgets/BaseWindow.hpp b/src/widgets/BaseWindow.hpp index 106cc1a3e..ec043f694 100644 --- a/src/widgets/BaseWindow.hpp +++ b/src/widgets/BaseWindow.hpp @@ -36,6 +36,17 @@ public: 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 }; explicit BaseWindow(FlagsEnum flags_ = None, @@ -51,15 +62,12 @@ public: std::function onClicked); EffectLabel *addTitleBarLabel(std::function onClicked); - void setStayInScreenRect(bool value); - bool getStayInScreenRect() const; - void setActionOnFocusLoss(ActionOnFocusLoss value); 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; pajlada::Signals::NoArgSignal closing; @@ -101,7 +109,12 @@ protected: private: void init(); - void moveIntoDesktopRect(QPoint point); + + /** + * + **/ + void moveWithinScreen(QPoint point, QPoint origin); + void calcButtonsSizes(); void drawCustomWindowFrame(QPainter &painter); void onFocusLost(); @@ -121,7 +134,6 @@ private: bool enableCustomFrame_; ActionOnFocusLoss actionOnFocusLoss_ = Nothing; bool frameless_; - bool stayInScreenRect_ = false; bool shown_ = false; FlagsEnum flags_; float nativeScale_ = 1; diff --git a/src/widgets/TooltipWidget.cpp b/src/widgets/TooltipWidget.cpp index 98ad4b971..f979c03d2 100644 --- a/src/widgets/TooltipWidget.cpp +++ b/src/widgets/TooltipWidget.cpp @@ -27,8 +27,6 @@ TooltipWidget::TooltipWidget(BaseWidget *parent) this->setAttribute(Qt::WA_TranslucentBackground); this->setWindowFlag(Qt::WindowStaysOnTopHint, true); - this->setStayInScreenRect(true); - // Default to using vertical layout this->initializeVLayout(); this->setLayout(this->vLayout_); diff --git a/src/widgets/dialogs/EmotePopup.cpp b/src/widgets/dialogs/EmotePopup.cpp index 2c4d91256..2876d88ca 100644 --- a/src/widgets/dialogs/EmotePopup.cpp +++ b/src/widgets/dialogs/EmotePopup.cpp @@ -206,8 +206,9 @@ EmotePopup::EmotePopup(QWidget *parent) , search_(new QLineEdit()) , notebook_(new Notebook(this)) { - this->setStayInScreenRect(true); - this->moveTo(this, getApp()->windows->emotePopupPos(), false); + // this->setStayInScreenRect(true); + this->moveTo(getApp()->windows->emotePopupPos(), false, + BaseWindow::BoundsChecker::DesiredPosition); auto *layout = new QVBoxLayout(); this->getLayoutContainer()->setLayout(layout); diff --git a/src/widgets/dialogs/ReplyThreadPopup.cpp b/src/widgets/dialogs/ReplyThreadPopup.cpp index b2abd5fd9..5d688d7f2 100644 --- a/src/widgets/dialogs/ReplyThreadPopup.cpp +++ b/src/widgets/dialogs/ReplyThreadPopup.cpp @@ -29,7 +29,6 @@ ReplyThreadPopup::ReplyThreadPopup(bool closeAutomatically, QWidget *parent, , split_(split) { this->setWindowTitle(QStringLiteral("Reply Thread")); - this->setStayInScreenRect(true); HotkeyController::HotkeyMap actions{ {"delete", diff --git a/src/widgets/dialogs/UserInfoPopup.cpp b/src/widgets/dialogs/UserInfoPopup.cpp index 2c0fa10fd..d3d9f952e 100644 --- a/src/widgets/dialogs/UserInfoPopup.cpp +++ b/src/widgets/dialogs/UserInfoPopup.cpp @@ -142,7 +142,6 @@ UserInfoPopup::UserInfoPopup(bool closeAutomatically, QWidget *parent, assert(split != nullptr && "split being nullptr causes lots of bugs down the road"); this->setWindowTitle("Usercard"); - this->setStayInScreenRect(true); HotkeyController::HotkeyMap actions{ {"delete", @@ -715,9 +714,6 @@ void UserInfoPopup::setData(const QString &name, this->userStateChanged_.invoke(); this->updateLatestMessages(); - QTimer::singleShot(1, this, [this] { - this->setStayInScreenRect(true); - }); } void UserInfoPopup::updateLatestMessages() diff --git a/src/widgets/dialogs/switcher/QuickSwitcherPopup.cpp b/src/widgets/dialogs/switcher/QuickSwitcherPopup.cpp index dd33ad54a..40792d3ff 100644 --- a/src/widgets/dialogs/switcher/QuickSwitcherPopup.cpp +++ b/src/widgets/dialogs/switcher/QuickSwitcherPopup.cpp @@ -46,7 +46,6 @@ QuickSwitcherPopup::QuickSwitcherPopup(QWidget *parent) this->initWidgets(); - this->setStayInScreenRect(true); const QRect geom = parent->geometry(); // This places the popup in the middle of the parent widget this->setGeometry(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index 4f8017009..a18680441 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -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->show(); } @@ -2663,8 +2664,9 @@ void ChannelView::showUserInfoPopup(const QString &userName, : this->underlyingChannel_; userPopup->setData(userName, contextChannel, openingChannel); - QPoint offset(int(150 * this->scale()), int(70 * this->scale())); - userPopup->move(QCursor::pos() - offset); + QPoint offset(userPopup->width() / 3, userPopup->height() / 5); + userPopup->moveTo(QCursor::pos() - offset, false, + BaseWindow::BoundsChecker::CursorPosition); userPopup->show(); } diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index d8eb2829a..4bce72ba6 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -964,7 +964,7 @@ void SplitHeader::enterEvent(QEvent *event) auto pos = this->mapToGlobal(this->rect().bottomLeft()) + QPoint((this->width() - tooltip->width()) / 2, 1); - tooltip->moveTo(this, pos, false); + tooltip->moveTo(pos, false, BaseWindow::BoundsChecker::CursorPosition); tooltip->show(); }