Context menu key wasn't working, as QPA had no handling for it.
Added ContextMenu event to QWindowSystemInterface and proper handling
to QGuiApplication and QWidgetWindow.
Also provide Windows implementation.
Task-number: QTBUG-27648
Change-Id: I7ce71ec4b5cdcc7be758e67f9faf6d863f7b19be
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
QGuiApplicationPrivate::processFileOpenEvent(
static_cast<QWindowSystemInterfacePrivate::FileOpenEvent *>(e));
break;
+#ifndef QT_NO_CONTEXTMENU
+ case QWindowSystemInterfacePrivate::ContextMenu:
+ QGuiApplicationPrivate::processContextMenuEvent(
+ static_cast<QWindowSystemInterfacePrivate::ContextMenuEvent *>(e));
+ break;
+#endif
default:
qWarning() << "Unknown user input event type:" << e->type;
break;
QGuiApplication::sendSpontaneousEvent(e->window.data(), &ev);
}
+#ifndef QT_NO_CONTEXTMENU
+void QGuiApplicationPrivate::processContextMenuEvent(QWindowSystemInterfacePrivate::ContextMenuEvent *e)
+{
+ // Widgets do not care about mouse triggered context menu events. Also, do not forward event
+ // to a window blocked by a modal window.
+ if (!e->window || e->mouseTriggered || e->window->d_func()->blockedByModalWindow)
+ return;
+
+ QContextMenuEvent ev(QContextMenuEvent::Keyboard, e->pos, e->globalPos, e->modifiers);
+ QGuiApplication::sendSpontaneousEvent(e->window.data(), &ev);
+}
+#endif
+
Q_GUI_EXPORT uint qHash(const QGuiApplicationPrivate::ActiveTouchPointsKey &k)
{
return qHash(k.device) + k.touchPointId;
static void processTabletLeaveProximityEvent(QWindowSystemInterfacePrivate::TabletLeaveProximityEvent *e);
static void processPlatformPanelEvent(QWindowSystemInterfacePrivate::PlatformPanelEvent *e);
+#ifndef QT_NO_CONTEXTMENU
+ static void processContextMenuEvent(QWindowSystemInterfacePrivate::ContextMenuEvent *e);
+#endif
#ifndef QT_NO_DRAGANDDROP
static QPlatformDragQtResponse processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions);
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
+#ifndef QT_NO_CONTEXTMENU
+void QWindowSystemInterface::handleContextMenuEvent(QWindow *w, bool mouseTriggered,
+ const QPoint &pos, const QPoint &globalPos,
+ Qt::KeyboardModifiers modifiers)
+{
+ QWindowSystemInterfacePrivate::ContextMenuEvent *e =
+ new QWindowSystemInterfacePrivate::ContextMenuEvent(w, mouseTriggered, pos,
+ globalPos, modifiers);
+ QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
+}
+#endif
+
Q_GUI_EXPORT void qt_handleMouseEvent(QWindow *w, const QPointF & local, const QPointF & global, Qt::MouseButtons b, Qt::KeyboardModifiers mods = Qt::NoModifier) {
QWindowSystemInterface::handleMouseEvent(w, local, global, b, mods);
}
static void handleTabletLeaveProximityEvent(int device, int pointerType, qint64 uid);
static void handlePlatformPanelEvent(QWindow *w);
+#ifndef QT_NO_CONTEXTMENU
+ static void handleContextMenuEvent(QWindow *w, bool mouseTriggered,
+ const QPoint &pos, const QPoint &globalPos,
+ Qt::KeyboardModifiers modifiers);
+#endif
// For event dispatcher implementations
static bool sendWindowSystemEvents(QEventLoop::ProcessEventsFlags flags);
Tablet,
TabletEnterProximity,
TabletLeaveProximity,
- PlatformPanel
+ PlatformPanel,
+ ContextMenu
};
class WindowSystemEvent {
QPointer<QWindow> window;
};
+#ifndef QT_NO_CONTEXTMENU
+ class ContextMenuEvent : public WindowSystemEvent {
+ public:
+ explicit ContextMenuEvent(QWindow *w, bool mouseTriggered, const QPoint &pos,
+ const QPoint &globalPos, Qt::KeyboardModifiers modifiers)
+ : WindowSystemEvent(ContextMenu), window(w), mouseTriggered(mouseTriggered), pos(pos),
+ globalPos(globalPos), modifiers(modifiers) { }
+ QPointer<QWindow> window;
+ bool mouseTriggered;
+ QPoint pos; // Only valid if triggered by mouse
+ QPoint globalPos; // Only valid if triggered by mouse
+ Qt::KeyboardModifiers modifiers;
+ };
+#endif
+
class WindowSystemEventList {
QList<WindowSystemEvent *> impl;
mutable QMutex mutex;
ThemeChanged = ThemingEventFlag + 1,
DisplayChangedEvent = 437,
SettingChangedEvent = DisplayChangedEvent + 1,
+ ContextMenu = 123,
UnknownEvent = 542
};
return QtWindows::DisplayChangedEvent;
case WM_THEMECHANGED:
return QtWindows::ThemeChanged;
+#ifndef QT_NO_CONTEXTMENU
+ case WM_CONTEXTMENU:
+ return QtWindows::ContextMenu;
+#endif
default:
break;
}
QWindowsWindow::baseWindowOf(modalWindow)->alertWindow();
break;
#endif
+#ifndef QT_NO_CONTEXTMENU
+ case QtWindows::ContextMenu:
+ handleContextMenuEvent(platformWindow->window(), msg);
+ return true;
+#endif
default:
break;
}
}
}
+#ifndef QT_NO_CONTEXTMENU
+void QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
+{
+ bool mouseTriggered = false;
+ QPoint globalPos;
+ QPoint pos;
+ if (msg.lParam != (int)0xffffffff) {
+ mouseTriggered = true;
+ globalPos.setX(msg.pt.x);
+ globalPos.setY(msg.pt.y);
+ pos = QWindowsGeometryHint::mapFromGlobal(msg.hwnd, globalPos);
+ }
+
+ QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
+ QWindowsKeyMapper::queryKeyboardModifiers());
+}
+#endif
+
/*!
\brief Windows functions for actual windows.
private:
void handleFocusEvent(QtWindows::WindowsEventType et, QWindowsWindow *w);
+#ifndef QT_NO_CONTEXTMENU
+ void handleContextMenuEvent(QWindow *window, const MSG &msg);
+#endif
void unregisterWindowClasses();
QScopedPointer<QWindowsContextPrivate> d;
handleTabletEvent(static_cast<QTabletEvent *>(event));
return true;
#endif
-
+#ifndef QT_NO_CONTEXTMENU
+ case QEvent::ContextMenu:
+ handleContextMenuEvent(static_cast<QContextMenuEvent *>(event));
+ return true;
+#endif
default:
break;
}
}
#endif // QT_NO_TABLETEVENT
+#ifndef QT_NO_CONTEXTMENU
+void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e)
+{
+ // We are only interested in keyboard originating context menu events here,
+ // mouse originated context menu events for widgets are generated in mouse handling methods.
+ if (e->reason() != QContextMenuEvent::Keyboard)
+ return;
+
+ QWidget *fw = QWidget::keyboardGrabber();
+ if (!fw) {
+ if (QApplication::activePopupWidget()) {
+ fw = (QApplication::activePopupWidget()->focusWidget()
+ ? QApplication::activePopupWidget()->focusWidget()
+ : QApplication::activePopupWidget());
+ } else if (QApplication::focusWidget()) {
+ fw = QApplication::focusWidget();
+ } else {
+ fw = m_widget;
+ }
+ }
+ if (fw && fw->isEnabled()) {
+ QPoint pos = fw->inputMethodQuery(Qt::ImMicroFocus).toRect().center();
+ QContextMenuEvent widgetEvent(QContextMenuEvent::Keyboard, pos, fw->mapToGlobal(pos),
+ e->modifiers());
+ QGuiApplication::sendSpontaneousEvent(fw, &widgetEvent);
+ }
+}
+#endif // QT_NO_CONTEXTMENU
+
void QWidgetWindow::updateObjectName()
{
QString name = m_widget->objectName();
#ifndef QT_NO_TABLETEVENT
void handleTabletEvent(QTabletEvent *);
#endif
+#ifndef QT_NO_CONTEXTMENU
+ void handleContextMenuEvent(QContextMenuEvent *);
+#endif
private slots:
void updateObjectName();