summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2012-10-22 14:43:38 +0300
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-10-25 10:08:04 +0200
commit9fc7fcb4c90f9fdc5bb3581609a1d5b01cfb7076 (patch)
tree205dd5103662563949f9bea6ca7c85aea905a33c
parent8e002f1c0e0e0605d6cdfb90cdf909035eb643c8 (diff)
Add ContextMenu event to QWindowSystemInterface
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>
-rw-r--r--src/gui/kernel/qguiapplication.cpp19
-rw-r--r--src/gui/kernel/qguiapplication_p.h3
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp12
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h5
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h18
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h5
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp23
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h3
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp35
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa_p.h3
10 files changed, 124 insertions, 2 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index a67917ca3b..64d2f8001f 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1211,6 +1211,12 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
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;
@@ -1639,6 +1645,19 @@ void QGuiApplicationPrivate::processPlatformPanelEvent(QWindowSystemInterfacePri
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;
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 0c81d78f86..44a9275688 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -138,6 +138,9 @@ public:
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);
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 82e0e44ac7..6fb10b6c75 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -630,6 +630,18 @@ void QWindowSystemInterface::handlePlatformPanelEvent(QWindow *w)
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);
}
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index 74b5a136f4..b4b2e845fc 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -175,6 +175,11 @@ public:
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);
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index 4e907f3f51..1b5351db71 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -77,7 +77,8 @@ public:
Tablet,
TabletEnterProximity,
TabletLeaveProximity,
- PlatformPanel
+ PlatformPanel,
+ ContextMenu
};
class WindowSystemEvent {
@@ -333,6 +334,21 @@ public:
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;
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index 73f963b6b8..7ff8edb588 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -105,6 +105,7 @@ enum WindowsEventType // Simplify event types
ThemeChanged = ThemingEventFlag + 1,
DisplayChangedEvent = 437,
SettingChangedEvent = DisplayChangedEvent + 1,
+ ContextMenu = 123,
UnknownEvent = 542
};
@@ -194,6 +195,10 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return QtWindows::DisplayChangedEvent;
case WM_THEMECHANGED:
return QtWindows::ThemeChanged;
+#ifndef QT_NO_CONTEXTMENU
+ case WM_CONTEXTMENU:
+ return QtWindows::ContextMenu;
+#endif
default:
break;
}
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 3d4871d7a2..42db58ae6c 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -869,6 +869,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
QWindowsWindow::baseWindowOf(modalWindow)->alertWindow();
break;
#endif
+#ifndef QT_NO_CONTEXTMENU
+ case QtWindows::ContextMenu:
+ handleContextMenuEvent(platformWindow->window(), msg);
+ return true;
+#endif
default:
break;
}
@@ -900,6 +905,24 @@ void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et,
}
}
+#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.
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index dcc636bfc0..ef48a52e07 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -187,6 +187,9 @@ public:
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;
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 5f25e1274e..900818d5c6 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -200,7 +200,11 @@ bool QWidgetWindow::event(QEvent *event)
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;
}
@@ -618,6 +622,35 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
}
#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();
diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h
index 80aa022ce2..e832249107 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa_p.h
+++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h
@@ -92,6 +92,9 @@ protected:
#ifndef QT_NO_TABLETEVENT
void handleTabletEvent(QTabletEvent *);
#endif
+#ifndef QT_NO_CONTEXTMENU
+ void handleContextMenuEvent(QContextMenuEvent *);
+#endif
private slots:
void updateObjectName();