[System Tray] Emit pressed signal on compact representation in popup, too

Some actions, such as middle click to mute, trigger only on press. Some applets
also need a pressed-click because of some legacy autoclose on focus change
bug.

Unfortunately, QML does not disambiguate the "pressed" property and "pressed(mouse)"
signal with argument, so this has to be done awkwardly through QMetaObject on C++ side.

BUG: 426646
BUG: 452893
FIXED-IN: 5.25.0
wilder-5.26
Kai Uwe Broulik 4 years ago committed by Nate Graham
parent 853c29bf7d
commit f045cf306c
  1. 9
      applets/systemtray/package/contents/ui/items/PlasmoidItem.qml
  2. 25
      applets/systemtray/systemtray.cpp
  3. 8
      applets/systemtray/systemtray.h

@ -40,7 +40,7 @@ AbstractItem {
//forward click event to the applet
var appletItem = applet.compactRepresentationItem ? applet.compactRepresentationItem : applet.fullRepresentationItem
const mouseArea = findMouseArea(appletItem)
if (mouseArea) {
if (mouseArea && mouse.button !== Qt.RightButton) {
mouseArea.clicked(mouse)
} else if (mouse.button === Qt.LeftButton) {//falback
plasmoidContainer.activated(null)
@ -51,6 +51,13 @@ AbstractItem {
// SNI has few problems, for example legacy applications that still use XEmbed require mouse to be released.
if (mouse.button === Qt.RightButton) {
plasmoidContainer.contextMenu(mouse);
} else {
const appletItem = applet.compactRepresentationItem ? applet.compactRepresentationItem : applet.fullRepresentationItem
const mouseArea = findMouseArea(appletItem)
if (mouseArea) {
// HACK QML only sees the "mouseArea.pressed" property, not the signal.
Plasmoid.nativeInterface.emitPressed(mouseArea, mouse);
}
}
}
onContextMenu: if (applet) {

@ -13,6 +13,8 @@
#include "systemtraysettings.h"
#include <QMenu>
#include <QMetaMethod>
#include <QMetaObject>
#include <QQuickItem>
#include <QQuickWindow>
#include <QScreen>
@ -244,6 +246,29 @@ bool SystemTray::isSystemTrayApplet(const QString &appletId)
return false;
}
void SystemTray::emitPressed(QQuickItem *mouseArea, QObject *mouseEvent)
{
if (!mouseArea || !mouseEvent) {
return;
}
// QQuickMouseEvent is also private, so we cannot use QMetaObject::invokeMethod with Q_ARG
const QMetaObject *mo = mouseArea->metaObject();
const int pressedIdx = mo->indexOfSignal("pressed(QQuickMouseEvent*)");
if (pressedIdx < 0) {
qCWarning(SYSTEM_TRAY) << "Failed to find onPressed signal on" << mouseArea;
return;
}
QMetaMethod pressedMethod = mo->method(pressedIdx);
if (!pressedMethod.invoke(mouseArea, Q_ARG(QObject *, mouseEvent))) {
qCWarning(SYSTEM_TRAY) << "Failed to invoke onPressed signal on" << mouseArea << "with" << mouseEvent;
return;
}
}
SystemTrayModel *SystemTray::systemTrayModel()
{
if (!m_systemTrayModel) {

@ -66,6 +66,14 @@ public:
*/
Q_INVOKABLE bool isSystemTrayApplet(const QString &appletId);
/**
* @brief Emits the "onPressed(mouse)" signal of a MouseArea
*
* This is needed because calling mouseArea.pressed from QML
* only sees the "pressed" property, not the signal
*/
Q_INVOKABLE void emitPressed(QQuickItem *mouseArea, QObject /*QQuickMouseEvent*/ *mouseEvent);
/**
* Needed to preserve keyboard navigation
*/

Loading…
Cancel
Save