summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qwidgetwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel/qwidgetwindow.cpp')
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp62
1 files changed, 59 insertions, 3 deletions
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 10ec4d3745..900818d5c6 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -47,6 +47,7 @@
#include <QtGui/qaccessible.h>
#endif
#include <private/qwidgetbackingstore_p.h>
+#include <qpa/qwindowsysteminterface_p.h>
QT_BEGIN_NAMESPACE
@@ -199,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;
}
@@ -212,9 +217,31 @@ QPointer<QWidget> qt_last_mouse_receiver = 0;
void QWidgetWindow::handleEnterLeaveEvent(QEvent *event)
{
if (event->type() == QEvent::Leave) {
+ QWidget *enter = 0;
+ // Check from window system event queue if the next queued enter targets a window
+ // in the same window hierarchy (e.g. enter a child of this window). If so,
+ // remove the enter event from queue and handle both in single dispatch.
+ QWindowSystemInterfacePrivate::EnterEvent *systemEvent =
+ static_cast<QWindowSystemInterfacePrivate::EnterEvent *>
+ (QWindowSystemInterfacePrivate::peekWindowSystemEvent(QWindowSystemInterfacePrivate::Enter));
+ if (systemEvent) {
+ if (QWidgetWindow *enterWindow = qobject_cast<QWidgetWindow *>(systemEvent->enter))
+ {
+ QWindow *thisParent = this;
+ QWindow *enterParent = enterWindow;
+ while (thisParent->parent())
+ thisParent = thisParent->parent();
+ while (enterParent->parent())
+ enterParent = enterParent->parent();
+ if (thisParent == enterParent) {
+ enter = enterWindow->widget();
+ QWindowSystemInterfacePrivate::removeWindowSystemEvent(systemEvent);
+ }
+ }
+ }
QWidget *leave = qt_last_mouse_receiver ? qt_last_mouse_receiver.data() : m_widget;
- QApplicationPrivate::dispatchEnterLeave(0, leave);
- qt_last_mouse_receiver = 0;
+ QApplicationPrivate::dispatchEnterLeave(enter, leave);
+ qt_last_mouse_receiver = enter;
} else {
QApplicationPrivate::dispatchEnterLeave(m_widget, 0);
qt_last_mouse_receiver = m_widget;
@@ -595,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();