Refactor QMouseEvent to contain the position inside the window

Rename the default accessors for positions to localPos, windowPos
and screenPos, to be explicit about their use.
Introduce a QT_NO_INTEGER_EVENT_COORDINATES define so one can make sure
to always use the float based coordinates.
Fixup all Qt code to use the correct constructor that specifies all
three coordinates.

Change-Id: If4bb93b8d1e2eb2440260d99680c468706cfe68f
Reviewed-on: http://codereview.qt.nokia.com/4058
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
This commit is contained in:
Lars Knoll 2011-09-01 11:13:35 +02:00
parent cf5e669a06
commit c2aea75c22
16 changed files with 126 additions and 59 deletions

View File

@ -149,33 +149,50 @@ QInputEvent::~QInputEvent()
QEvent::MouseButtonRelease, QEvent::MouseButtonDblClick,
or QEvent::MouseMove.
The \a position is the mouse cursor's position relative to the
receiving widget.
The \a localPos is the mouse cursor's position relative to the
receiving widget or item. The window position is set to the same value
as \a localPos.
The \a button that caused the event is given as a value from
the Qt::MouseButton enum. If the event \a type is
\l MouseMove, the appropriate button for this event is Qt::NoButton.
The mouse and keyboard states at the time of the event are specified by
\a buttons and \a modifiers.
The globalPos() is initialized to QCursor::pos(), which may not
The screenPos() is initialized to QCursor::pos(), which may not
be appropriate. Use the other constructor to specify the global
position explicitly.
*/
QMouseEvent::QMouseEvent(Type type, const QPointF &position, Qt::MouseButton button,
QMouseEvent::QMouseEvent(Type type, const QPointF &localPos, Qt::MouseButton button,
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
: QInputEvent(type, modifiers), p(position), b(button), mouseState(buttons)
: QInputEvent(type, modifiers), l(localPos), w(localPos), b(button), mouseState(buttons)
{
g = QCursor::pos();
s = QCursor::pos();
}
/*!
\internal
*/
QMouseEvent::~QMouseEvent()
{
}
Constructs a mouse event object.
The \a type parameter must be QEvent::MouseButtonPress,
QEvent::MouseButtonRelease, QEvent::MouseButtonDblClick,
or QEvent::MouseMove.
The \a localPos is the mouse cursor's position relative to the
receiving widget or item. The cursor's position in screen coordinates is
specified by \a screenPos. The window position is set to the same value
as \a localPos. The \a button that caused the event is
given as a value from the \l Qt::MouseButton enum. If the event \a
type is \l MouseMove, the appropriate button for this event is
Qt::NoButton. \a buttons is the state of all buttons at the
time of the event, \a modifiers the state of all keyboard
modifiers.
*/
QMouseEvent::QMouseEvent(Type type, const QPointF &localPos, const QPointF &screenPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers)
: QInputEvent(type, modifiers), l(localPos), w(localPos), s(screenPos), b(button), mouseState(buttons)
{}
/*!
Constructs a mouse event object.
@ -194,30 +211,59 @@ QMouseEvent::~QMouseEvent()
modifiers.
*/
QMouseEvent::QMouseEvent(Type type, const QPointF &pos, const QPointF &globalPos,
QMouseEvent::QMouseEvent(Type type, const QPointF &localPos, const QPointF &windowPos, const QPointF &screenPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers)
: QInputEvent(type, modifiers), p(pos), g(globalPos), b(button), mouseState(buttons)
: QInputEvent(type, modifiers), l(localPos), w(windowPos), s(screenPos), b(button), mouseState(buttons)
{}
/*!
\fn bool QMouseEvent::hasExtendedInfo() const
\internal
*/
QMouseEvent::~QMouseEvent()
{
}
/*!
\fn QPointF QMouseEvent::localPos() const
\since 5.0
Returns the position of the mouse cursor as a QPointF, relative to the
widget or item that received the event.
If you move the widget as a result of the mouse event, use the
screen position returned by screenPos() to avoid a shaking
motion.
\sa x() y() windowPos() screenPos()
*/
/*!
\fn QPointF QMouseEvent::posF() const
\fn QPointF QMouseEvent::windowPos() const
\since 4.4
\since 5.0
Returns the position of the mouse cursor as a QPointF, relative to the
widget that received the event.
window that received the event.
If you move the widget as a result of the mouse event, use the
global position returned by globalPos() to avoid a shaking
motion.
\sa x() y() pos() globalPos()
\sa x() y() pos() localPos() screenPos()
*/
/*!
\fn QPointF QMouseEvent::screenPos() const
\since 5.0
Returns the position of the mouse cursor as a QPointF, relative to the
screen that received the event.
\sa x() y() pos() localPos() screenPos()
*/
/*!

View File

@ -89,22 +89,32 @@ public:
QMouseEvent(Type type, const QPointF &pos, const QPointF &globalPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers);
QMouseEvent(Type type, const QPointF &pos, const QPointF &windowPos, const QPointF &globalPos,
Qt::MouseButton button, Qt::MouseButtons buttons,
Qt::KeyboardModifiers modifiers);
~QMouseEvent();
inline QPoint pos() const { return p.toPoint(); }
inline QPoint globalPos() const { return g.toPoint(); }
inline int x() const { return qRound(p.x()); }
inline int y() const { return qRound(p.y()); }
inline int globalX() const { return qRound(g.x()); }
inline int globalY() const { return qRound(g.y()); }
#ifndef QT_NO_INTEGER_EVENT_COORDINATES
inline QPoint pos() const { return l.toPoint(); }
inline QPoint globalPos() const { return s.toPoint(); }
inline int x() const { return qRound(l.x()); }
inline int y() const { return qRound(l.y()); }
inline int globalX() const { return qRound(s.x()); }
inline int globalY() const { return qRound(s.y()); }
#endif
const QPointF &localPos() const { return l; }
const QPointF &windowPos() const { return w; }
const QPointF &screenPos() const { return s; }
inline Qt::MouseButton button() const { return b; }
inline Qt::MouseButtons buttons() const { return mouseState; }
const QPointF &posF() const { return p; }
const QPointF &globalPosF() const { return g; }
#if QT_DEPRECATED_SINCE(5, 0)
Q_DEPRECATED inline QPointF posF() const { return l; }
#endif
protected:
QPointF p, g;
QPointF l, w, s;
Qt::MouseButton b;
Qt::MouseButtons mouseState;
};
@ -115,8 +125,10 @@ public:
QHoverEvent(Type type, const QPointF &pos, const QPointF &oldPos, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
~QHoverEvent();
#ifndef QT_NO_INTEGER_EVENT_COORDINATES
inline QPoint pos() const { return p.toPoint(); }
inline QPoint oldPos() const { return op.toPoint(); }
#endif
inline const QPointF &posF() const { return p; }
inline const QPointF &oldPosF() const { return op; }
@ -138,18 +150,20 @@ public:
~QWheelEvent();
inline int delta() const { return d; }
#ifndef QT_NO_INTEGER_EVENT_COORDINATES
inline QPoint pos() const { return p.toPoint(); }
inline QPoint globalPos() const { return g.toPoint(); }
inline int x() const { return p.x(); }
inline int y() const { return p.y(); }
inline int globalX() const { return g.x(); }
inline int globalY() const { return g.y(); }
#endif
inline const QPointF &posF() const { return p; }
inline const QPointF &globalPosF() const { return g; }
inline Qt::MouseButtons buttons() const { return mouseState; }
Qt::Orientation orientation() const { return o; }
inline const QPointF &posF() const { return p; }
inline const QPointF &globalPosF() const { return g; }
protected:
QPointF p;

View File

@ -590,7 +590,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
if (window) {
QMouseEvent ev(type, localPoint, globalPoint, button, buttons, QGuiApplication::keyboardModifiers());
QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, QGuiApplication::keyboardModifiers());
#ifndef QT_NO_CURSOR
QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances();
for (int i = 0; i < cursors.count(); ++i)

View File

@ -191,7 +191,8 @@ void QXcbDrag::startDrag()
atom(QXcbAtom::XdndTypelist),
XCB_ATOM_ATOM, 32, drag_types.size(), (const void *)drag_types.constData());
QMouseEvent me(QEvent::MouseMove, QCursor::pos(), QCursor::pos(), Qt::LeftButton,
QPointF pos = QCursor::pos();
QMouseEvent me(QEvent::MouseMove, pos, pos, pos, Qt::LeftButton,
QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
move(&me);
@ -1044,7 +1045,8 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event, bool)
void QXcbDrag::timerEvent(QTimerEvent* e)
{
if (e->timerId() == heartbeat && source_sameanswer.isNull()) {
QMouseEvent me(QEvent::MouseMove, QCursor::pos(), QCursor::pos(), Qt::LeftButton,
QPointF pos = QCursor::pos();
QMouseEvent me(QEvent::MouseMove, pos, pos, pos, Qt::LeftButton,
QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers());
move(&me);
} else if (e->timerId() == transaction_expiry_timer) {

View File

@ -274,9 +274,9 @@ void QGraphicsProxyWidgetPrivate::sendWidgetMouseEvent(QGraphicsSceneMouseEvent
pos = mapToReceiver(pos, receiver);
// Send mouse event.
QMouseEvent mouseEvent(type, pos,
receiver->mapToGlobal(pos.toPoint()), event->button(),
event->buttons(), event->modifiers());
QMouseEvent mouseEvent(type, pos, receiver->mapTo(receiver->topLevelWidget(), pos.toPoint()),
receiver->mapToGlobal(pos.toPoint()),
event->button(), event->buttons(), event->modifiers());
QWidget *embeddedMouseGrabberPtr = (QWidget *)embeddedMouseGrabber;
QApplicationPrivate::sendMouseEvent(receiver, &mouseEvent, alienWidget, widget,

View File

@ -339,7 +339,7 @@ QGraphicsViewPrivate::QGraphicsViewPrivate()
hasUpdateClip(false),
mousePressButton(Qt::NoButton),
leftIndent(0), topIndent(0),
lastMouseEvent(QEvent::None, QPoint(), Qt::NoButton, 0, 0),
lastMouseEvent(QEvent::None, QPointF(), QPointF(), QPointF(), Qt::NoButton, 0, 0),
alignment(Qt::AlignCenter),
transformationAnchor(QGraphicsView::AnchorViewCenter), resizeAnchor(QGraphicsView::NoAnchor),
viewportUpdateMode(QGraphicsView::MinimalViewportUpdate),
@ -610,7 +610,7 @@ void QGraphicsViewPrivate::replayLastMouseEvent()
void QGraphicsViewPrivate::storeMouseEvent(QMouseEvent *event)
{
useLastMouseEvent = true;
lastMouseEvent = QMouseEvent(QEvent::MouseMove, event->pos(), event->globalPos(),
lastMouseEvent = QMouseEvent(QEvent::MouseMove, event->localPos(), event->windowPos(), event->screenPos(),
event->button(), event->buttons(), event->modifiers());
}

View File

@ -1880,8 +1880,8 @@ void QAbstractItemView::mouseDoubleClickEvent(QMouseEvent *event)
|| !d->isIndexEnabled(index)
|| (d->pressedIndex != index)) {
QMouseEvent me(QEvent::MouseButtonPress,
event->pos(), event->button(),
event->buttons(), event->modifiers());
event->localPos(), event->windowPos(), event->screenPos(),
event->button(), event->buttons(), event->modifiers());
mousePressEvent(&me);
return;
}

View File

@ -3054,16 +3054,15 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
return; // Mouse cursor not inside the widget's top-level.
const QPoint globalPos(QCursor::pos());
QPoint pos = tlw->mapFromGlobal(globalPos);
QPoint windowPos = tlw->mapFromGlobal(globalPos);
// Find the current widget under the mouse. If this function was called from
// the widget's destructor, we have to make sure childAt() doesn't take into
// account widgets that are about to be destructed.
QWidget *widgetUnderCursor = tlw->d_func()->childAt_helper(pos, widget->data->in_destructor);
QWidget *widgetUnderCursor = tlw->d_func()->childAt_helper(windowPos, widget->data->in_destructor);
if (!widgetUnderCursor)
widgetUnderCursor = tlw;
else
pos = widgetUnderCursor->mapFrom(tlw, pos);
QPoint pos = widgetUnderCursor->mapFrom(tlw, windowPos);
if (widgetInShow && widgetUnderCursor != widget && !widget->isAncestorOf(widgetUnderCursor))
return; // Mouse cursor not inside the widget or any of its children.
@ -3072,7 +3071,7 @@ void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
qt_button_down = 0;
// Send enter/leave events followed by a mouse move on the entered widget.
QMouseEvent e(QEvent::MouseMove, pos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
QMouseEvent e(QEvent::MouseMove, pos, windowPos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier);
sendMouseEvent(widgetUnderCursor, &e, widgetUnderCursor, tlw, &qt_button_down, qt_last_mouse_receiver);
#endif // QT_NO_CURSOR
}
@ -3788,7 +3787,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QPointer<QWidget> pw = w;
while (w) {
QMouseEvent me(mouse->type(), relpos, mouse->globalPos(), mouse->button(), mouse->buttons(),
QMouseEvent me(mouse->type(), relpos, mouse->windowPos(), mouse->globalPos(), mouse->button(), mouse->buttons(),
mouse->modifiers());
me.spont = mouse->spontaneous();
// throw away any mouse-tracking-only mouse events

View File

@ -8713,8 +8713,9 @@ bool QWidget::event(QEvent *event)
break;
QMouseEvent mouseEvent(eventType,
touchPoint.pos().toPoint(),
touchPoint.screenPos().toPoint(),
touchPoint.pos(),
touchPoint.scenePos(),
touchPoint.screenPos(),
Qt::LeftButton,
Qt::LeftButton,
touchEvent->modifiers());

View File

@ -188,7 +188,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
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());
QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(), 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
@ -253,7 +253,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
return;
}
QMouseEvent translated(event->type(), mapped, event->globalPos(), event->button(), event->buttons(), event->modifiers());
QMouseEvent translated(event->type(), mapped, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers());
QApplicationPrivate::sendMouseEvent(receiver, &translated, widget, m_widget, &qt_button_down,
qt_last_mouse_receiver);

View File

@ -73,7 +73,7 @@ static QMouseEvent *copyMouseEvent(QEvent *e)
case QEvent::MouseButtonRelease:
case QEvent::MouseMove: {
QMouseEvent *me = static_cast<QMouseEvent *>(e);
return new QMouseEvent(me->type(), QPoint(0, 0), me->globalPos(), me->button(), me->buttons(), me->modifiers());
return new QMouseEvent(me->type(), QPoint(0, 0), me->windowPos(), me->screenPos(), me->button(), me->buttons(), me->modifiers());
}
#ifndef QT_NO_GRAPHICSVIEW
case QEvent::GraphicsSceneMousePress:
@ -83,7 +83,7 @@ static QMouseEvent *copyMouseEvent(QEvent *e)
#if 1
QEvent::Type met = me->type() == QEvent::GraphicsSceneMousePress ? QEvent::MouseButtonPress :
(me->type() == QEvent::GraphicsSceneMouseRelease ? QEvent::MouseButtonRelease : QEvent::MouseMove);
return new QMouseEvent(met, QPoint(0, 0), me->screenPos(), me->button(), me->buttons(), me->modifiers());
return new QMouseEvent(met, QPoint(0, 0), QPoint(0, 0), me->screenPos(), me->button(), me->buttons(), me->modifiers());
#else
QGraphicsSceneMouseEvent *copy = new QGraphicsSceneMouseEvent(me->type());
copy->setPos(me->pos());
@ -237,7 +237,7 @@ public:
QPoint farFarAway(-QWIDGETSIZE_MAX, -QWIDGETSIZE_MAX);
qFGDebug() << "QFG: sending a fake mouse release at far-far-away to " << mouseTarget;
QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway,
QMouseEvent re(QEvent::MouseButtonRelease, QPoint(), farFarAway, farFarAway,
mouseButton, QApplication::mouseButtons() & ~mouseButton,
QApplication::keyboardModifiers());
sendMouseEvent(&re, RegrabMouseAfterwards);
@ -287,7 +287,9 @@ protected:
#endif // QT_NO_GRAPHICSVIEW
if (me) {
QMouseEvent copy(me->type(), mouseTarget->mapFromGlobal(me->globalPos()), me->globalPos(), me->button(), me->buttons(), me->modifiers());
QMouseEvent copy(me->type(), mouseTarget->mapFromGlobal(me->globalPos()),
mouseTarget->topLevelWidget()->mapFromGlobal(me->globalPos()), me->screenPos(),
me->button(), me->buttons(), me->modifiers());
qt_sendSpontaneousEvent(mouseTarget, &copy);
}

View File

@ -994,7 +994,8 @@ bool QMenuPrivate::mouseEventTaken(QMouseEvent *e)
}
if (passOnEvent) {
if(e->type() != QEvent::MouseButtonRelease || mouseDown == caused) {
QMouseEvent new_e(e->type(), cpos, e->button(), e->buttons(), e->modifiers());
QMouseEvent new_e(e->type(), cpos, caused->mapTo(caused->topLevelWidget(), cpos), e->screenPos(),
e->button(), e->buttons(), e->modifiers());
QApplication::sendEvent(caused, &new_e);
return true;
}

View File

@ -1525,7 +1525,8 @@ void QPlainTextEdit::timerEvent(QTimerEvent *e)
} else {
const QPoint globalPos = QCursor::pos();
pos = d->viewport->mapFromGlobal(globalPos);
QMouseEvent ev(QEvent::MouseMove, pos, globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QMouseEvent ev(QEvent::MouseMove, pos, d->viewport->mapTo(d->viewport->topLevelWidget(), pos), globalPos,
Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
mouseMoveEvent(&ev);
}
int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height();

View File

@ -1086,7 +1086,7 @@ void QTextEdit::timerEvent(QTimerEvent *e)
} else {
const QPoint globalPos = QCursor::pos();
pos = d->viewport->mapFromGlobal(globalPos);
QMouseEvent ev(QEvent::MouseMove, pos, globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
QMouseEvent ev(QEvent::MouseMove, pos, mapTo(topLevelWidget(), pos), globalPos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
mouseMoveEvent(&ev);
}
int deltaY = qMax(pos.y() - visible.top(), visible.bottom() - pos.y()) - visible.height();

View File

@ -1412,7 +1412,7 @@ bool QWidgetLineControl::processEvent(QEvent* ev)
case QEvent::GraphicsSceneMousePress:{
QGraphicsSceneMouseEvent *gvEv = static_cast<QGraphicsSceneMouseEvent*>(ev);
QMouseEvent mouse(ev->type(),
gvEv->pos().toPoint(), gvEv->button(), gvEv->buttons(), gvEv->modifiers());
gvEv->pos(), gvEv->pos(), gvEv->screenPos(), gvEv->button(), gvEv->buttons(), gvEv->modifiers());
processMouseEvent(&mouse); break;
}
#endif

View File

@ -1800,7 +1800,8 @@ bool QWidgetTextControlPrivate::sendMouseEventToInputContext(
return true;
}
if (ctx) {
QMouseEvent ev(eventType, contextWidget->mapFromGlobal(globalPos), globalPos,
QMouseEvent ev(eventType, contextWidget->mapFromGlobal(globalPos),
contextWidget->topLevelWidget()->mapFromGlobal(globalPos), globalPos,
button, buttons, modifiers);
ctx->mouseHandler(cursorPos, &ev);
e->setAccepted(ev.isAccepted());