[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


(cherry picked from commit f045cf306c)
wilder-5.25
Kai Uwe Broulik 4 years ago
parent 5ab0a0b222
commit 7139ebfb3d
  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