diff --git a/src/Gui/NotificationArea.cpp b/src/Gui/NotificationArea.cpp index 53e27c644f..8e81a502cc 100644 --- a/src/Gui/NotificationArea.cpp +++ b/src/Gui/NotificationArea.cpp @@ -234,7 +234,7 @@ void NotificationAreaObserver::SendLog(const std::string& notifiername, const st .trimmed();// remove any leading and trailing whitespace character ('\n') // avoid processing empty strings - if(simplifiedstring.isEmpty()) + if (simplifiedstring.isEmpty()) return; if (level == Base::LogStyle::TranslatedNotification) { @@ -827,7 +827,7 @@ void NotificationArea::pushNotification(const QString& notifiername, const QStri auto timer_thread = pImp->inhibitTimer.thread(); auto current_thread = QThread::currentThread(); - if(timer_thread == current_thread) + if (timer_thread == current_thread) pImp->inhibitTimer.start(pImp->inhibitNotificationTime); } @@ -939,7 +939,8 @@ void NotificationArea::showInNotificationArea() iconstr = QStringLiteral(":/icons/info.svg"); } - QString tmpmessage = convertFromPlainText(item->msg, Qt::WhiteSpaceMode::WhiteSpaceNormal); + QString tmpmessage = + convertFromPlainText(item->msg, Qt::WhiteSpaceMode::WhiteSpaceNormal); msgw += QString::fromLatin1( @@ -990,11 +991,17 @@ void NotificationArea::showInNotificationArea() msgw += QString::fromLatin1("

"); + // Calculate the main window QRect in global screen coordinates. + auto mainwindow = getMainWindow(); + auto mainwindowrect = mainwindow->rect(); + auto globalmainwindowrect = + QRect(mainwindow->mapToGlobal(mainwindowrect.topLeft()), mainwindowrect.size()); NotificationBox::showText(this->mapToGlobal(QPoint()), msgw, pImp->notificationExpirationTime, pImp->minimumOnScreenTime, + globalmainwindowrect, pImp->notificationWidth); } } diff --git a/src/Gui/NotificationBox.cpp b/src/Gui/NotificationBox.cpp index 41bfe05d16..79e528d069 100644 --- a/src/Gui/NotificationBox.cpp +++ b/src/Gui/NotificationBox.cpp @@ -73,6 +73,8 @@ public: bool notificationLabelChanged(const QString& text); /// Place the notification at the given position void placeNotificationLabel(const QPoint& pos); + /// Set the windowrect defining an area to which the label should be constrained + void setTipRect(const QRect &restrictionarea); /// The instance static qobject_delete_later_unique_ptr instance; @@ -91,6 +93,8 @@ private: int minShowTime; QTimer hideTimer; QTimer expireTimer; + + QRect restrictionArea; }; qobject_delete_later_unique_ptr NotificationLabel::instance = nullptr; @@ -263,25 +267,36 @@ void NotificationLabel::placeNotificationLabel(const QPoint& pos) p += offset; - QRect screenRect = screen->geometry(); + QRect actinglimit = screen->geometry(); - if (p.x() + this->width() > screenRect.x() + screenRect.width()) - p.rx() -= 4 + this->width(); - if (p.y() + this->height() > screenRect.y() + screenRect.height()) - p.ry() -= 24 + this->height(); - if (p.y() < screenRect.y()) - p.setY(screenRect.y()); - if (p.x() + this->width() > screenRect.x() + screenRect.width()) - p.setX(screenRect.x() + screenRect.width() - this->width()); - if (p.x() < screenRect.x()) - p.setX(screenRect.x()); - if (p.y() + this->height() > screenRect.y() + screenRect.height()) - p.setY(screenRect.y() + screenRect.height() - this->height()); + if(!restrictionArea.isNull()) + actinglimit = restrictionArea; + + const int standard_x_padding = 4; + const int standard_y_padding = 24; + + if (p.x() + this->width() > actinglimit.x() + actinglimit.width()) + p.rx() -= standard_x_padding + this->width(); + if (p.y() + standard_y_padding + this->height() > actinglimit.y() + actinglimit.height()) + p.ry() -= standard_y_padding + this->height(); + if (p.y() < actinglimit.y()) + p.setY(actinglimit.y()); + if (p.x() + this->width() > actinglimit.x() + actinglimit.width()) + p.setX(actinglimit.x() + actinglimit.width() - this->width()); + if (p.x() < actinglimit.x()) + p.setX(actinglimit.x()); + if (p.y() + this->height() > actinglimit.y() + actinglimit.height()) + p.setY(actinglimit.y() + actinglimit.height() - this->height()); } this->move(p); } +void NotificationLabel::setTipRect(const QRect &restrictionarea) +{ + restrictionArea = restrictionarea; +} + bool NotificationLabel::notificationLabelChanged(const QString& text) { return NotificationLabel::instance->text() != text; @@ -290,7 +305,7 @@ bool NotificationLabel::notificationLabelChanged(const QString& text) /***************************** NotificationBox **********************************/ void NotificationBox::showText(const QPoint& pos, const QString& text, int displayTime, - unsigned int minShowTime, int width) + unsigned int minShowTime, const QRect &restrictionarea, int width) { // a label does already exist if (NotificationLabel::instance && NotificationLabel::instance->isVisible()) { @@ -301,6 +316,7 @@ void NotificationBox::showText(const QPoint& pos, const QString& text, int displ else { // If the label has changed, reuse the one that is showing (removes flickering) if (NotificationLabel::instance->notificationLabelChanged(text)) { + NotificationLabel::instance->setTipRect(restrictionarea); NotificationLabel::instance->reuseNotification(text, displayTime, pos, width); NotificationLabel::instance->placeNotificationLabel(pos); } @@ -310,12 +326,16 @@ void NotificationBox::showText(const QPoint& pos, const QString& text, int displ // no label can be reused, create new label: if (!text.isEmpty()) { + // Note: The Label takes no parent, as on windows, we can't use the widget as parent + // otherwise the window will be raised when the tooltip will be shown. We do not use + // it on Linux either for consistency. new NotificationLabel(text, pos, displayTime, minShowTime, width);// sets NotificationLabel::instance to itself + NotificationLabel::instance->setTipRect(restrictionarea); NotificationLabel::instance->placeNotificationLabel(pos); NotificationLabel::instance->setObjectName(QLatin1String("NotificationBox_label")); diff --git a/src/Gui/NotificationBox.h b/src/Gui/NotificationBox.h index 0008d5ad7e..4ddcd93083 100644 --- a/src/Gui/NotificationBox.h +++ b/src/Gui/NotificationBox.h @@ -54,11 +54,16 @@ public: * an event, see class documentation above) * @param minShowTime Time during which the notification can only be made disappear by popping * it out (clicking inside it). - * @param width Fixes the width of the notification. Default value makes the width to be system determined (dependent on - * the text). + * @param restrictionarea Try to keep the NotificationBox within this area. If this area is not + * provided, the whole screen is used as restriction area. This are must be provided in global + * screen coordinates. + * @param width Fixes the width of the notification. Default value makes the width to be system + * determined (dependent on the text). If a fixed width is provided it is enforced over the + * restrictionarea. */ static void showText(const QPoint& pos, const QString& text, int displayTime = -1, - unsigned int minShowTime = 0, int width = 0); + unsigned int minShowTime = 0, const QRect& restrictionarea = {}, + int width = 0); /// Hides a notification. static inline void hideText() {