summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp18
-rw-r--r--src/widgets/kernel/qapplication_qpa.cpp2
-rw-r--r--src/widgets/kernel/qwidgetwindow_qpa.cpp123
3 files changed, 117 insertions, 26 deletions
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 4cc07a06a4..f6d9c2f762 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -109,6 +109,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
| XCB_EVENT_MASK_BUTTON_MOTION
| XCB_EVENT_MASK_ENTER_WINDOW
| XCB_EVENT_MASK_LEAVE_WINDOW
+ | XCB_EVENT_MASK_POINTER_MOTION
| XCB_EVENT_MASK_PROPERTY_CHANGE
| XCB_EVENT_MASK_FOCUS_CHANGE
};
@@ -664,13 +665,26 @@ void QXcbWindow::handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_times
QWindowSystemInterface::handleMouseEvent(window(), time, local, global, buttons);
}
-void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *)
+void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
{
+ if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB)
+ || event->detail == XCB_NOTIFY_DETAIL_VIRTUAL
+ || event->detail == XCB_NOTIFY_DETAIL_NONLINEAR_VIRTUAL)
+ {
+ return;
+ }
+
QWindowSystemInterface::handleEnterEvent(window());
}
-void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *)
+void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
{
+ if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB)
+ || event->detail == XCB_NOTIFY_DETAIL_INFERIOR)
+ {
+ return;
+ }
+
QWindowSystemInterface::handleLeaveEvent(window());
}
diff --git a/src/widgets/kernel/qapplication_qpa.cpp b/src/widgets/kernel/qapplication_qpa.cpp
index 3930dc8d68..4ed8eda460 100644
--- a/src/widgets/kernel/qapplication_qpa.cpp
+++ b/src/widgets/kernel/qapplication_qpa.cpp
@@ -199,7 +199,7 @@ void QApplicationPrivate::closePopup(QWidget *popup)
}
-static int openPopupCount = 0;
+int openPopupCount = 0;
void QApplicationPrivate::openPopup(QWidget *popup)
{
openPopupCount++;
diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp
index e8b1a6d096..a63a6499fa 100644
--- a/src/widgets/kernel/qwidgetwindow_qpa.cpp
+++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp
@@ -48,6 +48,11 @@ QT_BEGIN_NAMESPACE
QWidget *qt_button_down = 0; // widget got last button-down
+// popup control
+static QWidget *qt_popup_down = 0; // popup that contains the pressed widget
+extern int openPopupCount;
+static bool replayPopupMouseEvent = false;
+
QWidgetWindow::QWidgetWindow(QWidget *widget)
: m_widget(widget)
{
@@ -111,43 +116,115 @@ void QWidgetWindow::handleEnterLeaveEvent(QEvent *event)
void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
{
+ if (qApp->d_func()->inPopupMode()) {
+ QWidget *activePopupWidget = qApp->activePopupWidget();
+ QWidget *popup = activePopupWidget;
+ QPoint mapped = event->pos();
+ if (popup != m_widget)
+ mapped = popup->mapFromGlobal(event->globalPos());
+ bool releaseAfter = false;
+ QWidget *popupChild = popup->childAt(mapped);
+
+ if (popup != qt_popup_down) {
+ qt_button_down = 0;
+ qt_popup_down = 0;
+ }
+
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
+ qt_button_down = popupChild;
+ qt_popup_down = popup;
+ break;
+ case QEvent::MouseButtonRelease:
+ releaseAfter = true;
+ break;
+ default:
+ break; // nothing for mouse move
+ }
+
+ int oldOpenPopupCount = openPopupCount;
+
+ if (popup->isEnabled()) {
+ // deliver event
+ replayPopupMouseEvent = false;
+ QWidget *receiver = popup;
+ QPoint widgetPos = mapped;
+ if (qt_button_down)
+ receiver = qt_button_down;
+ else if (popupChild)
+ receiver = popupChild;
+ if (receiver != popup)
+ widgetPos = receiver->mapFromGlobal(event->globalPos());
+ QWidget *alien = m_widget->childAt(m_widget->mapFromGlobal(event->globalPos()));
+ QMouseEvent e(event->type(), widgetPos, event->globalPos(), event->button(), event->buttons(), event->modifiers());
+ QApplicationPrivate::sendMouseEvent(receiver, &e, alien, m_widget, &qt_button_down, qt_last_mouse_receiver);
+ } else {
+ // close disabled popups when a mouse button is pressed or released
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonRelease:
+ popup->close();
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (qApp->activePopupWidget() != activePopupWidget
+ && replayPopupMouseEvent) {
+ if (m_widget->windowType() != Qt::Popup)
+ qt_button_down = 0;
+ replayPopupMouseEvent = false;
+ } else if (event->type() == QEvent::MouseButtonPress
+ && event->button() == Qt::RightButton
+ && (openPopupCount == oldOpenPopupCount)) {
+ QWidget *popupEvent = popup;
+ if (qt_button_down)
+ popupEvent = qt_button_down;
+ else if(popupChild)
+ popupEvent = popupChild;
+ QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPos(), event->modifiers());
+ QApplication::sendSpontaneousEvent(popupEvent, &e);
+ }
+
+ if (releaseAfter) {
+ qt_button_down = 0;
+ qt_popup_down = 0;
+ }
+ return;
+ }
+
// which child should have it?
+ QWidget *widget = m_widget->childAt(event->pos());
QPoint mapped = event->pos();
- QWidget *widget = 0;
- if (m_implicit_mouse_grabber) {
- widget = m_implicit_mouse_grabber.data();
- mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
- } else if ((widget = m_widget->childAt(event->pos()))) {
+ if (widget) {
mapped = widget->mapFrom(m_widget, event->pos());
- }
-
- if (qApp->d_func()->inPopupMode()) {
- widget = qApp->activePopupWidget();
- mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
- m_implicit_mouse_grabber.clear();
- }
-
- if (!widget)
+ } else {
widget = m_widget;
+ }
- if (event->type() == QEvent::MouseButtonPress && !m_implicit_mouse_grabber)
- m_implicit_mouse_grabber = widget;
+ if (event->type() == QEvent::MouseButtonPress && !qt_button_down)
+ qt_button_down = widget;
- if (event->buttons() == Qt::NoButton)
- m_implicit_mouse_grabber.clear();
+ QWidget *receiver = QApplicationPrivate::pickMouseReceiver(m_widget, event->globalPos(), mapped, event->type(), event->buttons(),
+ qt_button_down, widget);
- if (widget != qt_last_mouse_receiver) {
- QApplicationPrivate::dispatchEnterLeave(widget, qt_last_mouse_receiver);
- qt_last_mouse_receiver = widget;
+ if (!receiver) {
+ if (event->type() == QEvent::MouseButtonRelease)
+ QApplicationPrivate::mouse_buttons &= ~event->button();
+ return;
}
QMouseEvent translated(event->type(), mapped, event->globalPos(), event->button(), event->buttons(), event->modifiers());
- QGuiApplication::sendSpontaneousEvent(widget, &translated);
+ QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget, &qt_button_down,
+ qt_last_mouse_receiver);
if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::RightButton) {
QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPos(), event->modifiers());
- QGuiApplication::sendSpontaneousEvent(widget, &e);
+ QGuiApplication::sendSpontaneousEvent(receiver, &e);
}
}