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,
wl_fixed_t sx, wl_fixed_t sy)
{
Q_UNUSED(sx);
Q_UNUSED(sy);
if (!surface)
return;
@ -358,15 +363,16 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf
window->window()->setCursor(window->window()->cursor());
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;
mEnterSerial = serial;
QWaylandWindow *grab = QWaylandWindow::mouseGrab();
if (!grab) {
window->handleMouseEnter(mParent);
window->handleMouse(mParent, mParent->mTime, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
EnterEvent evt(mSurfacePos, mGlobalPos);
window->handleMouse(mParent, evt);
}
}
@ -387,11 +393,17 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac
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)
{
Q_UNUSED(surface_x);
Q_UNUSED(surface_y);
QWaylandWindow *window = mFocus;
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.
pos = QPointF(-1, -1);
global = grab->window()->mapToGlobal(pos.toPoint());
grab->handleMouse(mParent, time, pos, global, mButtons, Qt::NoModifier);
} else
window->handleMouse(mParent, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
MotionEvent e(time, pos, global, mButtons, Qt::NoModifier);
grab->handleMouse(mParent, e);
} else {
MotionEvent e(time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
window->handleMouse(mParent, e);
}
}
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) {
QPointF pos = QPointF(-1, -1);
QPointF global = grab->window()->mapToGlobal(pos.toPoint());
grab->handleMouse(mParent, time, pos, global, mButtons, Qt::NoModifier);
} else if (window)
window->handleMouse(mParent, time, mSurfacePos, mGlobalPos, mButtons, Qt::NoModifier);
MotionEvent e(time, pos, global, mButtons, Qt::NoModifier);
grab->handleMouse(mParent, e);
} 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)

View File

@ -260,7 +260,29 @@ public:
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

View File

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

View File

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