Send proper mouse enter events

The wl_pointer.event carries the surface local position of the pointer.
Notify Qt of it, without pretending it to be a motion event.

Change-Id: Ibbe1d125a93b478f9c350a50bfea25b01f628178
Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>
This commit is contained in:
Giulio Camuffo 2015-01-04 18:27:51 +02:00
parent 7fd1af437b
commit 92eac38d68
4 changed files with 91 additions and 49 deletions

View File

@ -345,12 +345,17 @@ void QWaylandInputDevice::setCursor(struct wl_buffer *buffer, struct wl_cursor_i
} }
} }
class EnterEvent : public QWaylandPointerEvent
{
public:
EnterEvent(const QPointF &l, const QPointF &g)
: QWaylandPointerEvent(QWaylandPointerEvent::Enter, 0, l, g, 0, Qt::NoModifier)
{}
};
void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surface *surface, void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surface *surface,
wl_fixed_t sx, wl_fixed_t sy) wl_fixed_t sx, wl_fixed_t sy)
{ {
Q_UNUSED(sx);
Q_UNUSED(sy);
if (!surface) if (!surface)
return; return;
@ -358,15 +363,16 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
window->window()->setCursor(window->window()->cursor()); window->window()->setCursor(window->window()->cursor());
mFocus = window; mFocus = window;
mSurfacePos = QPointF(wl_fixed_to_double(sx), wl_fixed_to_double(sy));
mGlobalPos = window->window()->mapToGlobal(mSurfacePos.toPoint());
mParent->mTime = QWaylandDisplay::currentTimeMillisec();
mParent->mSerial = serial; mParent->mSerial = serial;
mEnterSerial = serial; mEnterSerial = serial;
QWaylandWindow *grab = QWaylandWindow::mouseGrab(); QWaylandWindow *grab = QWaylandWindow::mouseGrab();
if (!grab) { if (!grab) {
window->handleMouseEnter(mParent); EnterEvent evt(mSurfacePos, mGlobalPos);
window->handleMouse(mParent, mParent->mTime, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier); window->handleMouse(mParent, evt);
} }
} }
@ -387,11 +393,17 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac
mParent->mTime = time; mParent->mTime = time;
} }
class MotionEvent : public QWaylandPointerEvent
{
public:
MotionEvent(ulong t, const QPointF &l, const QPointF &g, Qt::MouseButtons b, Qt::KeyboardModifiers m)
: QWaylandPointerEvent(QWaylandPointerEvent::Motion, t, l, g, b, m)
{
}
};
void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
{ {
Q_UNUSED(surface_x);
Q_UNUSED(surface_y);
QWaylandWindow *window = mFocus; QWaylandWindow *window = mFocus;
if (window == NULL) { if (window == NULL) {
@ -415,9 +427,12 @@ void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surf
// so we just set it outside of the window boundaries. // so we just set it outside of the window boundaries.
pos = QPointF(-1, -1); pos = QPointF(-1, -1);
global = grab->window()->mapToGlobal(pos.toPoint()); global = grab->window()->mapToGlobal(pos.toPoint());
grab->handleMouse(mParent, time, pos, global, mButtons, Qt::NoModifier); MotionEvent e(time, pos, global, mButtons, Qt::NoModifier);
} else grab->handleMouse(mParent, e);
window->handleMouse(mParent, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier); } else {
MotionEvent e(time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
window->handleMouse(mParent, e);
}
} }
void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time, void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time,
@ -461,9 +476,12 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time
if (grab && grab != mFocus) { if (grab && grab != mFocus) {
QPointF pos = QPointF(-1, -1); QPointF pos = QPointF(-1, -1);
QPointF global = grab->window()->mapToGlobal(pos.toPoint()); QPointF global = grab->window()->mapToGlobal(pos.toPoint());
grab->handleMouse(mParent, time, pos, global, mButtons, Qt::NoModifier); MotionEvent e(time, pos, global, mButtons, Qt::NoModifier);
} else if (window) grab->handleMouse(mParent, e);
window->handleMouse(mParent, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier); } else if (window) {
MotionEvent e(time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
window->handleMouse(mParent, e);
}
} }
void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, int32_t value) void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, int32_t value)

View File

@ -260,7 +260,29 @@ public:
QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints; QList<QWindowSystemInterface::TouchPoint> mPrevTouchPoints;
}; };
class QWaylandPointerEvent
{
public:
enum Type {
Enter,
Motion
};
inline QWaylandPointerEvent(Type t, ulong ts, const QPointF &l, const QPointF &g, Qt::MouseButtons b, Qt::KeyboardModifiers m)
: type(t)
, timestamp(ts)
, local(l)
, global(g)
, buttons(b)
, modifiers(m)
{}
Type type;
ulong timestamp;
QPointF local;
QPointF global;
Qt::MouseButtons buttons;
Qt::KeyboardModifiers modifiers;
};
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -603,27 +603,28 @@ QWaylandWindow *QWaylandWindow::transientParent() const
return 0; return 0;
} }
void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
{ {
if (b != Qt::NoButton) { if (e.buttons != Qt::NoButton) {
mMouseSerial = inputDevice->serial(); mMouseSerial = inputDevice->serial();
mMouseDevice = inputDevice; mMouseDevice = inputDevice;
} }
if (mWindowDecoration) { if (mWindowDecoration) {
handleMouseEventWithDecoration(inputDevice, timestamp,local,global,b,mods); handleMouseEventWithDecoration(inputDevice, e);
return; } else {
switch (e.type) {
case QWaylandPointerEvent::Enter:
QWindowSystemInterface::handleEnterEvent(window(), e.local, e.global);
break;
case QWaylandPointerEvent::Motion:
QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, e.local, e.global, e.buttons, e.modifiers);
break;
}
} }
QWindowSystemInterface::handleMouseEvent(window(),timestamp,local,global,b,mods); if (e.type == QWaylandPointerEvent::Enter)
} restoreMouseCursor(inputDevice);
void QWaylandWindow::handleMouseEnter(QWaylandInputDevice *inputDevice)
{
if (!mWindowDecoration) {
QWindowSystemInterface::handleEnterEvent(window());
}
restoreMouseCursor(inputDevice);
} }
void QWaylandWindow::handleMouseLeave(QWaylandInputDevice *inputDevice) void QWaylandWindow::handleMouseLeave(QWaylandInputDevice *inputDevice)
@ -645,19 +646,22 @@ bool QWaylandWindow::touchDragDecoration(QWaylandInputDevice *inputDevice, const
return mWindowDecoration->handleTouch(inputDevice, local, global, state, mods); return mWindowDecoration->handleTouch(inputDevice, local, global, state, mods);
} }
void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, ulong timestamp, const QPointF &local, const QPointF &global, Qt::MouseButtons b, Qt::KeyboardModifiers mods) void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e)
{ {
if (mWindowDecoration->handleMouse(inputDevice,local,global,b,mods)) if (mWindowDecoration->handleMouse(inputDevice, e.local, e.global, e.buttons, e.modifiers)) {
if (mMouseEventsInContentArea)
QWindowSystemInterface::handleLeaveEvent(window());
return; return;
}
QMargins marg = frameMargins(); QMargins marg = frameMargins();
QRect windowRect(0 + marg.left(), QRect windowRect(0 + marg.left(),
0 + marg.top(), 0 + marg.top(),
geometry().size().width() - marg.right(), geometry().size().width() - marg.right(),
geometry().size().height() - marg.bottom()); geometry().size().height() - marg.bottom());
if (windowRect.contains(local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) { if (windowRect.contains(e.local.toPoint()) || mMousePressedInContentArea != Qt::NoButton) {
QPointF localTranslated = local; QPointF localTranslated = e.local;
QPointF globalTranslated = global; QPointF globalTranslated = e.global;
localTranslated.setX(localTranslated.x() - marg.left()); localTranslated.setX(localTranslated.x() - marg.left());
localTranslated.setY(localTranslated.y() - marg.top()); localTranslated.setY(localTranslated.y() - marg.top());
globalTranslated.setX(globalTranslated.x() - marg.left()); globalTranslated.setX(globalTranslated.x() - marg.left());
@ -666,15 +670,23 @@ void QWaylandWindow::handleMouseEventWithDecoration(QWaylandInputDevice *inputDe
restoreMouseCursor(inputDevice); restoreMouseCursor(inputDevice);
QWindowSystemInterface::handleEnterEvent(window()); QWindowSystemInterface::handleEnterEvent(window());
} }
QWindowSystemInterface::handleMouseEvent(window(), timestamp, localTranslated, globalTranslated, b, mods);
switch (e.type) {
case QWaylandPointerEvent::Enter:
QWindowSystemInterface::handleEnterEvent(window(), localTranslated, globalTranslated);
break;
case QWaylandPointerEvent::Motion:
QWindowSystemInterface::handleMouseEvent(window(), e.timestamp, localTranslated, globalTranslated, e.buttons, e.modifiers);
break;
}
mMouseEventsInContentArea = true; mMouseEventsInContentArea = true;
mMousePressedInContentArea = b; mMousePressedInContentArea = e.buttons;
} else { } else {
if (mMouseEventsInContentArea) { if (mMouseEventsInContentArea) {
QWindowSystemInterface::handleLeaveEvent(window()); QWindowSystemInterface::handleLeaveEvent(window());
mMouseEventsInContentArea = false; mMouseEventsInContentArea = false;
} }
mWindowDecoration->handleMouse(inputDevice,local,global,b,mods);
} }
} }

View File

@ -64,6 +64,7 @@ class QWaylandAbstractDecoration;
class QWaylandInputDevice; class QWaylandInputDevice;
class QWaylandScreen; class QWaylandScreen;
class QWaylandShmBackingStore; class QWaylandShmBackingStore;
class QWaylandPointerEvent;
class Q_WAYLAND_CLIENT_EXPORT QWaylandWindowConfigure class Q_WAYLAND_CLIENT_EXPORT QWaylandWindowConfigure
{ {
@ -151,13 +152,7 @@ public:
QWaylandAbstractDecoration *decoration() const; QWaylandAbstractDecoration *decoration() const;
void handleMouse(QWaylandInputDevice *inputDevice, void handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
ulong timestamp,
const QPointF & local,
const QPointF & global,
Qt::MouseButtons b,
Qt::KeyboardModifiers mods);
void handleMouseEnter(QWaylandInputDevice *inputDevice);
void handleMouseLeave(QWaylandInputDevice *inputDevice); void handleMouseLeave(QWaylandInputDevice *inputDevice);
bool touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, bool touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,
@ -237,12 +232,7 @@ private:
bool setWindowStateInternal(Qt::WindowState flags); bool setWindowStateInternal(Qt::WindowState flags);
void setGeometry_helper(const QRect &rect); void setGeometry_helper(const QRect &rect);
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
ulong timestamp,
const QPointF & local,
const QPointF & global,
Qt::MouseButtons b,
Qt::KeyboardModifiers mods);
static const wl_callback_listener callbackListener; static const wl_callback_listener callbackListener;
static void frameCallback(void *data, struct wl_callback *wl_callback, uint32_t time); static void frameCallback(void *data, struct wl_callback *wl_callback, uint32_t time);