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>
This commit is contained in:
Miikka Heikkinen 2012-10-22 14:43:38 +03:00 committed by The Qt Project
parent 8e002f1c0e
commit 9fc7fcb4c9
10 changed files with 124 additions and 2 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -868,6 +868,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
if (const QWindow *modalWindow = QGuiApplication::modalWindow())
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.

View File

@ -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;

View File

@ -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();

View File

@ -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();