eglfs: Generate enter and leave events

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 <jorgen.lind@theqtcompany.com>
This commit is contained in:
Laszlo Agocs 2015-03-06 10:36:43 +01:00
parent f5edf2b6fb
commit 048918d4bd
7 changed files with 69 additions and 3 deletions

View File

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

View File

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

View File

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

View File

@ -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<QEGLPlatformScreen *>(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()

View File

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

View File

@ -32,6 +32,8 @@
****************************************************************************/
#include "qeglplatformscreen_p.h"
#include <QtGui/qwindow.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtPlatformSupport/private/qopenglcompositor_p.h>
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<QOpenGLCompositorWindow *> 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

View File

@ -46,6 +46,7 @@
//
#include <QtCore/QList>
#include <QtCore/QPoint>
#include <QtCore/qtextstream.h>
#include <qpa/qplatformscreen.h>
#include <EGL/egl.h>
@ -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