From 048918d4bd73886e1a8999a06b7af2cd2ddbe5f2 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 6 Mar 2015 10:36:43 +0100 Subject: eglfs: Generate enter and leave events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In addition the logic in QGuiApplication that picks the target window for input events with a null window has to be enhanced to be compatible with how real windowing systems work: mouse events following a press are delivered to the same window until the release, even if the cursor has left the original target window. Task-number: QTBUG-44814 Change-Id: I3fea84ac77a5ccebeae5def64f92d8d2e03d13ff Reviewed-by: Jørgen Lind --- src/gui/kernel/qguiapplication.cpp | 14 ++++++++ src/gui/kernel/qguiapplication_p.h | 1 + src/gui/kernel/qwindow.cpp | 2 ++ .../eglconvenience/qeglplatformcursor.cpp | 5 ++- .../eglconvenience/qeglplatformcursor_p.h | 3 +- .../eglconvenience/qeglplatformscreen.cpp | 42 +++++++++++++++++++++- .../eglconvenience/qeglplatformscreen_p.h | 5 +++ 7 files changed, 69 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 60b289bacb..3d21b4affc 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -147,12 +147,15 @@ QString *QGuiApplicationPrivate::displayName = 0; QPalette *QGuiApplicationPrivate::app_pal = 0; // default application palette Qt::MouseButtons QGuiApplicationPrivate::buttons = Qt::NoButton; + ulong QGuiApplicationPrivate::mousePressTime = 0; Qt::MouseButton QGuiApplicationPrivate::mousePressButton = Qt::NoButton; int QGuiApplicationPrivate::mousePressX = 0; int QGuiApplicationPrivate::mousePressY = 0; int QGuiApplicationPrivate::mouse_double_click_distance = -1; +QWindow *QGuiApplicationPrivate::currentMousePressWindow = 0; + static Qt::LayoutDirection layout_direction = Qt::LeftToRight; static bool force_reverse = false; @@ -1703,6 +1706,17 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo if (e->nullWindow()) { window = QGuiApplication::topLevelAt(globalPoint.toPoint()); if (window) { + // Moves and the release following a press must go to the same + // window, even if the cursor has moved on over another window. + if (e->buttons != Qt::NoButton) { + if (!currentMousePressWindow) + currentMousePressWindow = window; + else + window = currentMousePressWindow; + } else if (currentMousePressWindow) { + window = currentMousePressWindow; + currentMousePressWindow = 0; + } QPointF delta = globalPoint - globalPoint.toPoint(); localPoint = window->mapFromGlobal(globalPoint.toPoint()) + delta; } diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 0c00e06499..7ae6e64b26 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -200,6 +200,7 @@ public: static Qt::MouseButtons tabletState; static QWindow *tabletPressTarget; static QWindow *currentMouseWindow; + static QWindow *currentMousePressWindow; static Qt::ApplicationState applicationState; #ifndef QT_NO_CLIPBOARD diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 06db4e81fa..06674d204d 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1599,6 +1599,8 @@ void QWindow::destroy() QGuiApplicationPrivate::focus_window = parent(); if (QGuiApplicationPrivate::currentMouseWindow == this) QGuiApplicationPrivate::currentMouseWindow = parent(); + if (QGuiApplicationPrivate::currentMousePressWindow == this) + QGuiApplicationPrivate::currentMousePressWindow = parent(); if (QGuiApplicationPrivate::tabletPressTarget == this) QGuiApplicationPrivate::tabletPressTarget = parent(); diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp index bf23d52465..5023efbaf6 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp @@ -43,6 +43,7 @@ #include "qeglplatformcursor_p.h" #include "qeglplatformintegration_p.h" +#include "qeglplatformscreen_p.h" QT_BEGIN_NAMESPACE @@ -56,7 +57,7 @@ QT_BEGIN_NAMESPACE QEGLPlatformCursor::QEGLPlatformCursor(QPlatformScreen *screen) : m_visible(true), - m_screen(screen), + m_screen(static_cast(screen)), m_program(0), m_vertexCoordEntry(0), m_textureCoordEntry(0), @@ -300,6 +301,7 @@ void QEGLPlatformCursor::setPos(const QPoint &pos) const QRect oldCursorRect = cursorRect(); m_cursor.pos = pos; update(oldCursorRect | cursorRect()); + m_screen->handleCursorMove(m_cursor.pos); } void QEGLPlatformCursor::pointerEvent(const QMouseEvent &event) @@ -309,6 +311,7 @@ void QEGLPlatformCursor::pointerEvent(const QMouseEvent &event) const QRect oldCursorRect = cursorRect(); m_cursor.pos = event.screenPos().toPoint(); update(oldCursorRect | cursorRect()); + m_screen->handleCursorMove(m_cursor.pos); } void QEGLPlatformCursor::paintOnScreen() diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h index 481bb3c74c..b89dd1ca43 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h @@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE class QOpenGLShaderProgram; class QEGLPlatformCursor; +class QEGLPlatformScreen; class QEGLPlatformCursorDeviceListener : public QObject { @@ -127,7 +128,7 @@ private: } m_cursorAtlas; bool m_visible; - QPlatformScreen *m_screen; + QEGLPlatformScreen *m_screen; QOpenGLShaderProgram *m_program; int m_vertexCoordEntry; int m_textureCoordEntry; diff --git a/src/platformsupport/eglconvenience/qeglplatformscreen.cpp b/src/platformsupport/eglconvenience/qeglplatformscreen.cpp index dd4a97cdf5..6e2fc81c42 100644 --- a/src/platformsupport/eglconvenience/qeglplatformscreen.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformscreen.cpp @@ -32,6 +32,8 @@ ****************************************************************************/ #include "qeglplatformscreen_p.h" +#include +#include #include QT_BEGIN_NAMESPACE @@ -45,7 +47,8 @@ QT_BEGIN_NAMESPACE */ QEGLPlatformScreen::QEGLPlatformScreen(EGLDisplay dpy) - : m_dpy(dpy) + : m_dpy(dpy), + m_pointerWindow(0) { } @@ -54,4 +57,41 @@ QEGLPlatformScreen::~QEGLPlatformScreen() QOpenGLCompositor::destroy(); } +void QEGLPlatformScreen::handleCursorMove(const QPoint &pos) +{ + const QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); + const QList windows = compositor->windows(); + + // Generate enter and leave events like a real windowing system would do. + if (windows.isEmpty()) + return; + + // First window is always fullscreen. + if (windows.count() == 1) { + QWindow *window = windows[0]->sourceWindow(); + if (m_pointerWindow != window) { + m_pointerWindow = window; + QWindowSystemInterface::handleEnterEvent(window, window->mapFromGlobal(pos), pos); + } + return; + } + + QWindow *enter = 0, *leave = 0; + for (int i = windows.count() - 1; i >= 0; --i) { + QWindow *window = windows[i]->sourceWindow(); + const QRect geom = window->geometry(); + if (geom.contains(pos)) { + if (m_pointerWindow != window) { + leave = m_pointerWindow; + m_pointerWindow = window; + enter = window; + } + break; + } + } + + if (enter && leave) + QWindowSystemInterface::handleEnterLeaveEvent(enter, leave, enter->mapFromGlobal(pos), pos); +} + QT_END_NAMESPACE diff --git a/src/platformsupport/eglconvenience/qeglplatformscreen_p.h b/src/platformsupport/eglconvenience/qeglplatformscreen_p.h index 33528e61a7..98a108c4b7 100644 --- a/src/platformsupport/eglconvenience/qeglplatformscreen_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformscreen_p.h @@ -46,6 +46,7 @@ // #include +#include #include #include #include @@ -53,6 +54,7 @@ QT_BEGIN_NAMESPACE class QOpenGLContext; +class QWindow; class QEGLPlatformWindow; class QEGLPlatformScreen : public QPlatformScreen @@ -63,8 +65,11 @@ public: EGLDisplay display() const { return m_dpy; } + void handleCursorMove(const QPoint &pos); + private: EGLDisplay m_dpy; + QWindow *m_pointerWindow; }; QT_END_NAMESPACE -- cgit v1.2.3