Finally figured out how to filter out double activation signals from QSystemTrayIcon.
Additionally, main window toggling is now controlled by the systray notification backends
rather than the tray itself. This ensures that we don't get a race condition where the
notification wants to activate the window, and the tray wants to hide it.
Consequently removing the crude inhibitActivation hack.
}
void KNotificationBackend::notificationActivated(SystemTray::ActivationReason reason) {
- if(reason == SystemTray::Trigger && _notifications.count()) {
- notificationActivated(_notifications.first().first); // oldest one
+ if(reason == SystemTray::Trigger) {
+ if( _notifications.count())
+ notificationActivated(_notifications.first().first); // oldest one
+ else
+ GraphicalUi::toggleMainWidget();
}
}
void KNotificationBackend::notificationActivated(uint notificationId) {
- QtUi::mainWindow()->systemTray()->setInhibitActivation();
emit activated(notificationId);
-
}
SettingsPage *KNotificationBackend::createConfigWidget() const {
: QObject(parent),
_mode(Invalid),
_state(Passive),
- _inhibitActivation(false),
_passiveIcon(DesktopIcon("quassel_inactive")),
_activeIcon(DesktopIcon("quassel")),
_needsAttentionIcon(DesktopIcon("quassel_message")),
_associatedWidget(parent)
{
Q_ASSERT(parent);
-
- qApp->installEventFilter(this);
}
SystemTray::~SystemTray() {
}
void SystemTray::activate(SystemTray::ActivationReason reason) {
-
emit activated(reason);
-
- if(reason == Trigger && !isActivationInhibited()) {
- GraphicalUi::toggleMainWidget();
- }
-}
-
-bool SystemTray::eventFilter(QObject *obj, QEvent *event) {
- if(event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonRelease) {
- _inhibitActivation = false;
- }
- return QObject::eventFilter(obj, event);
}
virtual inline bool isSystemTrayAvailable() const;
void setAlert(bool alerted);
- virtual inline void setInhibitActivation();
virtual inline bool isVisible() const { return false; }
- inline bool isActivationInhibited() const;
QWidget *associatedWidget() const;
inline QMenu *trayMenu() const;
void setTrayMenu(QMenu *);
- virtual bool eventFilter(QObject *obj, QEvent *event);
-
private slots:
private:
Mode _mode;
State _state;
- bool _inhibitActivation;
-
QString _toolTipTitle, _toolTipSubTitle;
Icon _passiveIcon, _activeIcon, _needsAttentionIcon;
bool SystemTray::isSystemTrayAvailable() const { return false; }
bool SystemTray::isAlerted() const { return state() == NeedsAttention; }
-void SystemTray::setInhibitActivation() { _inhibitActivation = true; }
-bool SystemTray::isActivationInhibited() const { return _inhibitActivation; }
SystemTray::Mode SystemTray::mode() const { return _mode; }
SystemTray::State SystemTray::state() const { return _state; }
QMenu *SystemTray::trayMenu() const { return _trayMenu; }
#include "systemtray.h"
SystrayNotificationBackend::SystrayNotificationBackend(QObject *parent)
- : AbstractNotificationBackend(parent)
+ : AbstractNotificationBackend(parent),
+ _blockActivation(false)
{
NotificationSettings notificationSettings;
_showBubble = notificationSettings.value("Systray/ShowBubble", true).toBool();
notificationSettings.notify("Systray/ShowBubble", this, SLOT(showBubbleChanged(const QVariant &)));
notificationSettings.notify("Systray/Animate", this, SLOT(animateChanged(const QVariant &)));
+ connect(QtUi::mainWindow()->systemTray(), SIGNAL(messageClicked()), SLOT(notificationActivated()));
connect(QtUi::mainWindow()->systemTray(), SIGNAL(activated(SystemTray::ActivationReason)),
SLOT(notificationActivated(SystemTray::ActivationReason)));
- connect(QtUi::mainWindow()->systemTray(), SIGNAL(messageClicked()), SLOT(notificationActivated()));
+
+ QApplication::instance()->installEventFilter(this);
}
void SystrayNotificationBackend::notify(const Notification ¬ification) {
}
void SystrayNotificationBackend::notificationActivated() {
- if(QtUi::mainWindow()->systemTray()->isAlerted() && !QtUi::mainWindow()->systemTray()->isActivationInhibited()) {
- QtUi::mainWindow()->systemTray()->setInhibitActivation();
- uint id = _notifications.count()? _notifications.last().notificationId : 0;
- emit activated(id);
+ if(!_blockActivation) {
+ if(QtUi::mainWindow()->systemTray()->isAlerted()) {
+ _blockActivation = true; // prevent double activation because both tray icon and bubble might send a signal
+ uint id = _notifications.count()? _notifications.last().notificationId : 0;
+ emit activated(id);
+ } else
+ GraphicalUi::toggleMainWidget();
}
}
}
}
+// moving the mouse or releasing the button means that we're not dealing with a double activation
+bool SystrayNotificationBackend::eventFilter(QObject *obj, QEvent *event) {
+ if(event->type() == QEvent::MouseMove || event->type() == QEvent::MouseButtonRelease) {
+ _blockActivation = false;
+ }
+ return AbstractNotificationBackend::eventFilter(obj, event);
+}
+
void SystrayNotificationBackend::showBubbleChanged(const QVariant &v) {
_showBubble = v.toBool();
}
void close(uint notificationId);
virtual SettingsPage *createConfigWidget() const;
+protected:
+ virtual bool eventFilter(QObject *obj, QEvent *event);
+
private slots:
void showBubble();
void closeBubble();
bool _showBubble;
bool _animate;
QList<Notification> _notifications;
+ bool _blockActivation;
};
class SystrayNotificationBackend::ConfigWidget : public SettingsPage {