mirror of
https://gitlab.linphone.org/BC/public/linphone-desktop.git
synced 2026-02-07 15:08:24 +00:00
feat(src/components/notifier/Notifier): reworking, handle virtual desktops
This commit is contained in:
parent
d114d858fd
commit
9d056093ff
7 changed files with 84 additions and 93 deletions
|
|
@ -320,7 +320,6 @@
|
|||
<file>ui/modules/Linphone/Styles/Notifications/NotificationReceivedCallStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Notifications/NotificationReceivedFileMessageStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Notifications/NotificationReceivedMessageStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/Notifications/NotificationStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/qmldir</file>
|
||||
<file>ui/modules/Linphone/Styles/SmartSearchBar/SmartSearchBarStyle.qml</file>
|
||||
<file>ui/modules/Linphone/Styles/TelKeypad/TelKeypadStyle.qml</file>
|
||||
|
|
|
|||
|
|
@ -20,35 +20,53 @@
|
|||
* Author: Ronan Abhamon
|
||||
*/
|
||||
|
||||
#include <QQmlComponent>
|
||||
#include <QQuickWindow>
|
||||
#include <QScreen>
|
||||
#include <QtDebug>
|
||||
#include <QTimer>
|
||||
|
||||
#include "../../app/App.hpp"
|
||||
#include "../../Utils.hpp"
|
||||
#include "../core/CoreManager.hpp"
|
||||
|
||||
#include "Notifier.hpp"
|
||||
|
||||
#include <QQmlComponent>
|
||||
#include <QQuickWindow>
|
||||
#include <QtDebug>
|
||||
#include <QTimer>
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// 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<class T>
|
||||
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<QQuickWindow *>(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<QTimer *>()->stop();
|
||||
|
|
@ -191,7 +222,7 @@ void Notifier::deleteNotification (QVariant notification) {
|
|||
instance->deleteLater();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
void Notifier::notifyReceivedMessage (const shared_ptr<linphone::ChatMessage> &message) {
|
||||
QObject *notification = createNotification(Notifier::MessageReceived);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
pragma Singleton
|
||||
import QtQuick 2.7
|
||||
|
||||
// =============================================================================
|
||||
|
||||
QtObject {
|
||||
property int margin: 0
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue