diff --git a/linphone-desktop/resources.qrc b/linphone-desktop/resources.qrc index c605eb269..8f9d12273 100644 --- a/linphone-desktop/resources.qrc +++ b/linphone-desktop/resources.qrc @@ -320,7 +320,6 @@ ui/modules/Linphone/Styles/Notifications/NotificationReceivedCallStyle.qml ui/modules/Linphone/Styles/Notifications/NotificationReceivedFileMessageStyle.qml ui/modules/Linphone/Styles/Notifications/NotificationReceivedMessageStyle.qml - ui/modules/Linphone/Styles/Notifications/NotificationStyle.qml ui/modules/Linphone/Styles/qmldir ui/modules/Linphone/Styles/SmartSearchBar/SmartSearchBarStyle.qml ui/modules/Linphone/Styles/TelKeypad/TelKeypadStyle.qml diff --git a/linphone-desktop/src/components/notifier/Notifier.cpp b/linphone-desktop/src/components/notifier/Notifier.cpp index 27fc761ea..d91ac4f81 100644 --- a/linphone-desktop/src/components/notifier/Notifier.cpp +++ b/linphone-desktop/src/components/notifier/Notifier.cpp @@ -20,35 +20,53 @@ * Author: Ronan Abhamon */ +#include +#include +#include +#include +#include + #include "../../app/App.hpp" #include "../../Utils.hpp" #include "../core/CoreManager.hpp" #include "Notifier.hpp" -#include -#include -#include -#include - +// ----------------------------------------------------------------------------- // Notifications QML properties/methods. +// ----------------------------------------------------------------------------- + #define NOTIFICATION_SHOW_METHOD_NAME "show" #define NOTIFICATION_PROPERTY_DATA "notificationData" -#define NOTIFICATION_PROPERTY_HEIGHT "notificationHeight" -#define NOTIFICATION_PROPERTY_OFFSET "notificationOffset" + +#define NOTIFICATION_PROPERTY_X "popupX" +#define NOTIFICATION_PROPERTY_Y "popupY" + +#define NOTIFICATION_PROPERTY_WINDOW "__internalWindow" #define NOTIFICATION_PROPERTY_TIMER "__timer" +// ----------------------------------------------------------------------------- +// Paths. +// ----------------------------------------------------------------------------- + #define QML_NOTIFICATION_PATH_RECEIVED_MESSAGE "qrc:/ui/modules/Linphone/Notifications/NotificationReceivedMessage.qml" #define QML_NOTIFICATION_PATH_RECEIVED_FILE_MESSAGE "qrc:/ui/modules/Linphone/Notifications/NotificationReceivedFileMessage.qml" #define QML_NOTIFICATION_PATH_RECEIVED_CALL "qrc:/ui/modules/Linphone/Notifications/NotificationReceivedCall.qml" +// ----------------------------------------------------------------------------- +// Timeouts. +// ----------------------------------------------------------------------------- + #define NOTIFICATION_TIMEOUT_RECEIVED_MESSAGE 10000 #define NOTIFICATION_TIMEOUT_RECEIVED_FILE_MESSAGE 10000 #define NOTIFICATION_TIMEOUT_RECEIVED_CALL 30000 +// ----------------------------------------------------------------------------- // Arbitrary hardcoded values. +// ----------------------------------------------------------------------------- + #define NOTIFICATION_SPACING 10 #define N_MAX_NOTIFICATIONS 5 #define MAX_TIMEOUT 30000 @@ -57,29 +75,25 @@ using namespace std; // ============================================================================= -inline int getNotificationSize (const QObject &object, const char *property) { +inline int getIntegerFromNotification (const QObject &object, const char *property) { QVariant variant = object.property(property); bool soFarSoGood; - int size = variant.toInt(&soFarSoGood); - if (!soFarSoGood || size < 0) { - qWarning() << "Unable to get notification size."; - return -1; + int value = variant.toInt(&soFarSoGood); + if (!soFarSoGood) { + qWarning() << QStringLiteral("Unable to get int from: `%1`.").arg(property); + abort(); } - return size; + return value; } template -bool setProperty (QObject &object, const char *property, const T &value) { - QVariant qvariant(value); - - if (!object.setProperty(property, qvariant)) { +void setProperty (QObject &object, const char *property, const T &value) { + if (!object.setProperty(property, QVariant(value))) { qWarning() << QStringLiteral("Unable to set property: `%1`.").arg(property); - return false; + abort(); } - - return true; } // ----------------------------------------------------------------------------- @@ -117,29 +131,46 @@ QObject *Notifier::createNotification (Notifier::NotificationType type) { // Check existing instances. if (mInstancesNumber == N_MAX_NOTIFICATIONS) { - qWarning() << "Unable to create another notification"; + qWarning() << QStringLiteral("Unable to create another notification."); mMutex.unlock(); return nullptr; } // Create instance and set attributes. - QObject *object = mComponents[type]->create(); - int offset = getNotificationSize(*object, NOTIFICATION_PROPERTY_HEIGHT); + QObject *instance = mComponents[type]->create(); + qInfo() << QStringLiteral("Create notification:") << instance; - if (offset == -1 || !::setProperty(*object, NOTIFICATION_PROPERTY_OFFSET, mOffset)) { - delete object; - mMutex.unlock(); - return nullptr; - } - - mOffset = (offset + mOffset) + NOTIFICATION_SPACING; mInstancesNumber++; + { + QQuickWindow *window = instance->findChild(NOTIFICATION_PROPERTY_WINDOW); + Q_ASSERT(window != nullptr); + + QScreen *screen = window->screen(); + Q_ASSERT(screen != nullptr); + + QRect geometry = screen->availableGeometry(); + + // Set X/Y. (Not Pokémon games.) + int windowHeight = window->height(); + int offset = geometry.y() + geometry.height() - windowHeight; + + ::setProperty(*instance, NOTIFICATION_PROPERTY_X, geometry.x() + geometry.width() - window->width()); + ::setProperty(*instance, NOTIFICATION_PROPERTY_Y, offset - (mOffset % offset)); + + // Update offset. + mOffset = (windowHeight + mOffset) + NOTIFICATION_SPACING; + if (mOffset - offset + geometry.y() >= 0) + mOffset = 0; + } + mMutex.unlock(); - return object; + return instance; } +// ----------------------------------------------------------------------------- + void Notifier::showNotification (QObject *notification, int timeout) { // Display notification. QMetaObject::invokeMethod(notification, NOTIFICATION_SHOW_METHOD_NAME, Qt::DirectConnection); @@ -175,7 +206,7 @@ void Notifier::deleteNotification (QVariant notification) { return; } - qDebug() << "Delete notification."; + qInfo() << QStringLiteral("Delete notification:") << instance; instance->setProperty("__valid", true); instance->property(NOTIFICATION_PROPERTY_TIMER).value()->stop(); @@ -191,7 +222,7 @@ void Notifier::deleteNotification (QVariant notification) { instance->deleteLater(); } -// ----------------------------------------------------------------------------- +// ============================================================================= void Notifier::notifyReceivedMessage (const shared_ptr &message) { QObject *notification = createNotification(Notifier::MessageReceived); diff --git a/linphone-desktop/ui/modules/Common/Popup/DesktopPopup.qml b/linphone-desktop/ui/modules/Common/Popup/DesktopPopup.qml index aeac9b130..3c6f9573f 100644 --- a/linphone-desktop/ui/modules/Common/Popup/DesktopPopup.qml +++ b/linphone-desktop/ui/modules/Common/Popup/DesktopPopup.qml @@ -47,6 +47,9 @@ Item { Window { id: popup + // Used for internal purposes only. Like Notifications. + objectName: '__internalWindow' + flags: wrapper.flags opacity: 0 height: _content[0] != null ? _content[0].height : 0 diff --git a/linphone-desktop/ui/modules/Linphone/Notifications/Notification.qml b/linphone-desktop/ui/modules/Linphone/Notifications/Notification.qml index 3c517eb4f..18d740f4f 100644 --- a/linphone-desktop/ui/modules/Linphone/Notifications/Notification.qml +++ b/linphone-desktop/ui/modules/Linphone/Notifications/Notification.qml @@ -1,29 +1,14 @@ import QtQuick 2.7 -// Warning: This import is necessary to use the attached property `Screen`. -// See: https://doc-snapshots.qt.io/qt5-5.7/qml-qtquick-window-screen.html -import QtQuick.Window 2.2 - import Common 1.0 -import Linphone.Styles 1.0 -import Utils 1.0 // ============================================================================= DesktopPopup { id: notification - // --------------------------------------------------------------------------- - - property alias notificationHeight: notification.popupHeight - property int notificationOffset: 0 property var notificationData: ({}) - readonly property var window: _window - property var _window - - // --------------------------------------------------------------------------- - signal deleteNotification (var notification) function _close (cb) { @@ -34,34 +19,5 @@ DesktopPopup { deleteNotification(notification) } - // --------------------------------------------------------------------------- - - flags: Qt.Window | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint - - Component.onCompleted: { - var window = _window = data[0] - - Utils.assert( - Utils.qmlTypeof(window, 'QQuickWindowQmlImpl'), true, - 'Unable to found `Window` object in `DesktopPopup`.' - ) - - window.x = Qt.binding(function () { - var screen = window.Screen - return screen != null - ? screen.width - window.width - NotificationStyle.margin - : 0 - }) - - window.y = Qt.binding(function () { - var screen = window.Screen - - if (screen == null) { - return 0 - } - - var height = screen.desktopAvailableHeight - window.height - return height - (notificationOffset % height) - }) - } + flags: Qt.Tool | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint } diff --git a/linphone-desktop/ui/modules/Linphone/Notifications/Notification.spec.qml b/linphone-desktop/ui/modules/Linphone/Notifications/Notification.spec.qml index f1398a92f..7254b799f 100644 --- a/linphone-desktop/ui/modules/Linphone/Notifications/Notification.spec.qml +++ b/linphone-desktop/ui/modules/Linphone/Notifications/Notification.spec.qml @@ -15,12 +15,20 @@ TestCase { compare(Utils.isObject(notification.notificationData), true) } - function test_notificationHeightProperty () { - compare(Utils.isInteger(notification.notificationHeight), true) + function test_notificationPopupX () { + compare(Utils.isInteger(notification.popupX), true) } - function test_notificationOffsetProperty () { - compare(Utils.isInteger(notification.notificationOffset), true) + function test_notificationPopupY () { + compare(Utils.isInteger(notification.popupY), true) + } + + function test_notificationPopupHeight () { + compare(Utils.isInteger(notification.popupHeight), true) + } + + function test_notificationPopupWidth () { + compare(Utils.isInteger(notification.popupWidth), true) } function test_notificationShowMethod () { @@ -28,6 +36,9 @@ TestCase { } function test_childWindow () { - compare(Utils.qmlTypeof(notification.data[0], 'QQuickWindowQmlImpl'), true) + var window = notification.data[0] + + compare(Utils.qmlTypeof(window, 'QQuickWindowQmlImpl'), true) + compare(window.objectName === '__internalWindow', true) } } diff --git a/linphone-desktop/ui/modules/Linphone/Styles/Notifications/NotificationStyle.qml b/linphone-desktop/ui/modules/Linphone/Styles/Notifications/NotificationStyle.qml deleted file mode 100644 index 50b95a441..000000000 --- a/linphone-desktop/ui/modules/Linphone/Styles/Notifications/NotificationStyle.qml +++ /dev/null @@ -1,8 +0,0 @@ -pragma Singleton -import QtQuick 2.7 - -// ============================================================================= - -QtObject { - property int margin: 0 -} diff --git a/linphone-desktop/ui/modules/Linphone/Styles/qmldir b/linphone-desktop/ui/modules/Linphone/Styles/qmldir index 0094337f5..69a04d187 100644 --- a/linphone-desktop/ui/modules/Linphone/Styles/qmldir +++ b/linphone-desktop/ui/modules/Linphone/Styles/qmldir @@ -24,7 +24,6 @@ singleton MessagesCounterStyle 1.0 Contact/MessagesCounterStyle. singleton SipAddressesMenuStyle 1.0 Menus/SipAddressesMenuStyle.qml -singleton NotificationStyle 1.0 Notifications/NotificationStyle.qml singleton NotificationReceivedCallStyle 1.0 Notifications/NotificationReceivedCallStyle.qml singleton NotificationReceivedMessageStyle 1.0 Notifications/NotificationReceivedMessageStyle.qml singleton NotificationReceivedFileMessageStyle 1.0 Notifications/NotificationReceivedFileMessageStyle.qml