From d9efefe2c168c91c41ff7f65af6112c5b243b1bd Mon Sep 17 00:00:00 2001 From: Patrick von Reth Date: Thu, 20 Feb 2014 11:02:27 +0100 Subject: [PATCH] use shared mem to prevent two apps from hiding their notifications --- src/core/notification/notification.h | 9 ++- src/plugins/backends/snore/notifywidget.cpp | 51 ++++++++++++++-- src/plugins/backends/snore/notifywidget.h | 8 +++ src/plugins/backends/snore/snorenotifier.cpp | 64 ++++++++++++++------ src/plugins/backends/snore/snorenotifier.h | 2 + 5 files changed, 111 insertions(+), 23 deletions(-) diff --git a/src/core/notification/notification.h b/src/core/notification/notification.h index ac7ca3d..2a35057 100644 --- a/src/core/notification/notification.h +++ b/src/core/notification/notification.h @@ -299,11 +299,16 @@ inline QDebug operator<< ( QDebug debug, const Snore::Notification ¬i ) { if(noti.isValid()) { - debug << "Snore::Notification(" << noti.title() << ", " << noti.text() << "," << noti.id() << ")" ; + debug.nospace() << "Snore::Notification(" << noti.title() << ", " << noti.text() << ", id = " << noti.id(); + if(noti.isUpdate()) + { + debug << ", oldID = " << noti.old().id(); + } + debug << ")" ; } else { - debug << "Snore::Notification(0x00)" ; + debug.nospace() << "Snore::Notification(0x00)" ; } return debug.maybeSpace(); } diff --git a/src/plugins/backends/snore/notifywidget.cpp b/src/plugins/backends/snore/notifywidget.cpp index 75dbf5b..3e6a801 100644 --- a/src/plugins/backends/snore/notifywidget.cpp +++ b/src/plugins/backends/snore/notifywidget.cpp @@ -30,9 +30,21 @@ NotifyWidget::NotifyWidget(int pos,QWidget *parent) : QWidget(parent, Qt::SplashScreen | Qt::WindowStaysOnTopHint), ui(new Ui::NotifyWidget), m_desktop(QDesktopWidget().availableGeometry()), - m_id(pos) + m_id(pos), + m_mem(QString("SnoreNotifyWidget%1").arg(QString::number(m_id))) { ui->setupUi(this); + if(m_mem.create(sizeof(SHARED_MEM_TYPE))) + { + m_mem.lock(); + bool *data = (bool*)m_mem.data(); + *data = true; + m_mem.unlock(); + } + else + { + m_mem.attach(); + } TomahawkUtils::DpiScaler::setFontSize(10); m_scaler = new TomahawkUtils::DpiScaler(this); @@ -40,11 +52,13 @@ NotifyWidget::NotifyWidget(int pos,QWidget *parent) : setFixedSize( m_scaler->scaled(300, 80)); - m_dest = QPoint(m_desktop.topRight().x() - width(), m_desktop.topRight().y() + (m_scaler->scaledY(10) + height()) * pos); + m_dest = QPoint(m_desktop.topRight().x() - width(), m_desktop.topRight().y() + m_scaler->scaledY(10) + (m_scaler->scaledY(10) + height()) * pos); + m_start = QPoint(m_desktop.topRight().x(), m_dest.y()); } NotifyWidget::~NotifyWidget() { + release(); delete m_scaler; delete ui; } @@ -52,13 +66,13 @@ NotifyWidget::~NotifyWidget() void NotifyWidget::display(const Notification ¬ification) { update(notification); - move(m_desktop.topRight().x(), m_desktop.topRight().y() + (m_scaler->scaledY(10) + height()) * m_id); + move(m_start); show(); m_moveTimer = new QTimer(this); m_moveTimer->setInterval(2); connect( m_moveTimer, SIGNAL(timeout()), this, SLOT(slotMove())); m_moveTimer->start(); - snoreDebug( SNORE_DEBUG ) << size(); + snoreDebug( SNORE_DEBUG ) << notification; } @@ -77,6 +91,35 @@ void NotifyWidget::update(const Notification ¬ification) setPalette(img); } +bool NotifyWidget::acquire() +{ + bool out = false; + m_mem.lock(); + bool *data = (bool*)m_mem.data(); + if(*data) + { + *data = false; + out = true; + } + m_mem.unlock(); + return out; +} + +bool NotifyWidget::release() +{ + snoreDebug( SNORE_DEBUG ) << notification(); + bool out = false; + m_mem.lock(); + bool *data = (bool*)m_mem.data(); + if(!*data) + { + *data = true; + out = true; + } + m_mem.unlock(); + return out; +} + Notification &NotifyWidget::notification() { return m_notification; diff --git a/src/plugins/backends/snore/notifywidget.h b/src/plugins/backends/snore/notifywidget.h index d9b56e8..22933dc 100644 --- a/src/plugins/backends/snore/notifywidget.h +++ b/src/plugins/backends/snore/notifywidget.h @@ -22,6 +22,7 @@ #include #include +#include #include "core/notification/notification.h" #include "DpiScaler.h" @@ -29,6 +30,7 @@ namespace Ui { class NotifyWidget; } +typedef bool SHARED_MEM_TYPE; class NotifyWidget : public QWidget { Q_OBJECT @@ -40,11 +42,15 @@ public: void display(const Snore::Notification ¬ification); void update(const Snore::Notification ¬ification); + bool acquire(); + bool release(); + Snore::Notification ¬ification(); int id(); + signals: void invoked(); void dismissed(); @@ -65,11 +71,13 @@ private: Ui::NotifyWidget *ui; QTimer *m_moveTimer; QPoint m_dest; + QPoint m_start; QRect m_desktop; TomahawkUtils::DpiScaler *m_scaler; Snore::Notification m_notification; int m_id; + QSharedMemory m_mem; }; #endif // NOTIFYWIDGET_H diff --git a/src/plugins/backends/snore/snorenotifier.cpp b/src/plugins/backends/snore/snorenotifier.cpp index ca28f12..b4a8406 100644 --- a/src/plugins/backends/snore/snorenotifier.cpp +++ b/src/plugins/backends/snore/snorenotifier.cpp @@ -23,6 +23,7 @@ #include "core/notification/notification_p.h" #include "core/snore_p.h" #include +#include Q_EXPORT_PLUGIN2(libsnore_backend_snore,SnoreNotifier) @@ -48,16 +49,19 @@ void SnoreNotifier::slotNotify(Snore::Notification notification) if(notification.isUpdate()) { NotifyWidget *w = m_widgets[notification.old().hints().privateValue(this, "id").toInt()]; - w->update(notification); - notification.hints().setPrivateValue(this, "id", w->id()); - startTimeout(notification); - return; + if(w->isVisible() && w->notification().id() == notification.old().id()) + { + w->update(notification); + notification.hints().setPrivateValue(this, "id", w->id()); + startTimeout(notification); + return; + } } - else if(m_queue.isEmpty()) + if(m_queue.isEmpty()) { foreach (NotifyWidget *w, m_widgets) { - if(w->isHidden()) + if(w->acquire()) { w->display(notification); notification.hints().setPrivateValue(this, "id", w->id()); @@ -67,22 +71,15 @@ void SnoreNotifier::slotNotify(Snore::Notification notification) } } m_queue.append(notification); + m_timer->start(); } void SnoreNotifier::slotCloseNotification(Snore::Notification notification) { NotifyWidget *w = m_widgets[notification.hints().privateValue(this, "id").toInt()]; - if(!m_queue.isEmpty()) - { - Notification nextNoti = m_queue.takeLast(); - w->display(nextNoti); - nextNoti.hints().setPrivateValue(this, "id", w->id()); - startTimeout(nextNoti); - } - else - { - w->hide(); - } + w->hide(); + w->release(); + //the timer will show the next } @@ -103,6 +100,33 @@ void SnoreNotifier::slotInvoked() slotCloseNotification(notification); } +void SnoreNotifier::slotProcessQueue() +{ + if(m_queue.isEmpty()) + { + + snoreDebug( SNORE_DEBUG ) << "queue is empty"; + m_timer->stop(); + } + else + { + foreach (NotifyWidget *w, m_widgets) + { + bool free = false; + if(w->acquire()) + { + Notification notification = m_queue.takeFirst(); + w->display(notification); + notification.hints().setPrivateValue(this, "id", w->id()); + startTimeout(notification); + free = true; + } + snoreDebug( SNORE_DEBUG ) << w << free; + } + } + +} + void SnoreNotifier::setup() { for(int i=0;isetInterval(500); + connect(m_timer, SIGNAL(timeout()), this, SLOT(slotProcessQueue())); } @@ -132,6 +161,7 @@ bool SnoreNotifier::deinitialize() { m_widgets[i]->deleteLater(); } + m_timer->deleteLater(); return true; } return false; diff --git a/src/plugins/backends/snore/snorenotifier.h b/src/plugins/backends/snore/snorenotifier.h index e729569..68416f1 100644 --- a/src/plugins/backends/snore/snorenotifier.h +++ b/src/plugins/backends/snore/snorenotifier.h @@ -43,6 +43,7 @@ public slots: private slots: void slotDismissed(); void slotInvoked(); + void slotProcessQueue(); void setup(); @@ -50,6 +51,7 @@ private: QList m_queue; QVector m_widgets; + QTimer *m_timer; };