Skip to content

Commit 5fe7795

Browse files
committed
Send mouse release events to hovered and previously clicked items
1 parent ed4ef5b commit 5fe7795

File tree

3 files changed

+33
-12
lines changed

3 files changed

+33
-12
lines changed

src/mouseeventhandler.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,19 @@ bool MouseEventHandler::eventFilter(QObject *obj, QEvent *event)
5555
forwardPointEvent(static_cast<QSinglePointEvent *>(event));
5656
return true;
5757

58-
case QEvent::MouseButtonRelease:
58+
case QEvent::MouseButtonRelease: {
5959
emit mouseReleased();
60+
QQuickItem *oldClickedItem = m_clickedItem;
6061

6162
if (m_clickedItem) {
6263
sendPointEventToItem(static_cast<QSinglePointEvent *>(event), m_clickedItem);
6364
m_clickedItem = nullptr;
64-
} else
65-
forwardPointEvent(static_cast<QSinglePointEvent *>(event));
65+
}
66+
67+
forwardPointEvent(static_cast<QSinglePointEvent *>(event), oldClickedItem);
6668

6769
return true;
70+
}
6871

6972
default:
7073
break;
@@ -73,7 +76,7 @@ bool MouseEventHandler::eventFilter(QObject *obj, QEvent *event)
7376
return QObject::eventFilter(obj, event);
7477
}
7578

76-
void MouseEventHandler::forwardPointEvent(QSinglePointEvent *event)
79+
void MouseEventHandler::forwardPointEvent(QSinglePointEvent *event, QQuickItem *oldClickedItem)
7780
{
7881
Q_ASSERT(m_spriteRepeater);
7982

@@ -97,22 +100,33 @@ void MouseEventHandler::forwardPointEvent(QSinglePointEvent *event)
97100
// Sort the list by layer order
98101
std::sort(sprites.begin(), sprites.end(), [](IRenderedTarget *t1, IRenderedTarget *t2) { return t1->scratchTarget()->layerOrder() > t2->scratchTarget()->layerOrder(); });
99102

100-
// Send the event to the hovered sprite
103+
// Find hovered sprite
104+
QQuickItem *hoveredItem = nullptr;
105+
101106
for (IRenderedTarget *sprite : sprites) {
102107
// contains() expects position in the item's coordinate system
103108
QPointF localPos = sprite->mapFromScene(event->scenePosition());
104109

105110
if (sprite->contains(localPos)) {
106-
sendPointEventToItem(event, sprite);
107-
return;
111+
hoveredItem = sprite;
112+
break;
108113
}
109114
}
110115

111116
// If there wasn't any hovered sprite, send the event to the stage
112-
Q_ASSERT(m_stage);
117+
if (!hoveredItem) {
118+
hoveredItem = m_stage;
119+
Q_ASSERT(m_stage);
120+
}
113121

114-
if (m_stage)
115-
sendPointEventToItem(event, m_stage);
122+
// Send the event to the item
123+
if (hoveredItem) {
124+
// Since both the hovered item and previously clicked item should receive mouse release event,
125+
// avoid duplicate events by checking whether the previously clicked item is the hovered item.
126+
if (!(event->type() == QEvent::MouseButtonRelease && hoveredItem == oldClickedItem)) {
127+
sendPointEventToItem(event, hoveredItem);
128+
}
129+
}
116130
}
117131

118132
void MouseEventHandler::sendPointEventToItem(QSinglePointEvent *event, QQuickItem *item)

src/mouseeventhandler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class MouseEventHandler : public QObject
3434
void mouseReleased();
3535

3636
private:
37-
void forwardPointEvent(QSinglePointEvent *event);
37+
void forwardPointEvent(QSinglePointEvent *event, QQuickItem *oldClickedItem = nullptr);
3838
void sendPointEventToItem(QSinglePointEvent *event, QQuickItem *item);
3939
void sendHoverEventToItem(QHoverEvent *originalEvent, QEvent::Type newType, QQuickItem *item);
4040

test/mouseeventhandler/mouseeventhandler_test.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ TEST(MouseEventHandlerTest, MousePressReleaseEvent)
304304
releasedSpy.clear();
305305

306306
// Send release (should be sent to sprite 1)
307+
EXPECT_CALL(renderedTarget3, contains(localPos)).WillOnce(Return(false));
308+
EXPECT_CALL(renderedTarget1, contains(localPos)).WillOnce(Return(true));
307309
EXPECT_CALL(renderedTarget1, mouseReleaseEvent(_)).WillOnce(WithArgs<0>(Invoke(checkReleaseEvent)));
308310
ASSERT_TRUE(handler.eventFilter(nullptr, &releaseEvent));
309311
ASSERT_EQ(pressedSpy.count(), 0);
@@ -321,8 +323,10 @@ TEST(MouseEventHandlerTest, MousePressReleaseEvent)
321323
pressedSpy.clear();
322324
releasedSpy.clear();
323325

324-
// Send release (should be sent to sprite 1)
326+
// Send release while sprite 3 is hovered (should be sent to both sprites)
327+
EXPECT_CALL(renderedTarget3, contains(localPos)).WillOnce(Return(true));
325328
EXPECT_CALL(renderedTarget1, mouseReleaseEvent(_)).WillOnce(WithArgs<0>(Invoke(checkReleaseEvent)));
329+
EXPECT_CALL(renderedTarget3, mouseReleaseEvent(_)).WillOnce(WithArgs<0>(Invoke(checkReleaseEvent)));
326330
ASSERT_TRUE(handler.eventFilter(nullptr, &releaseEvent));
327331
ASSERT_EQ(pressedSpy.count(), 0);
328332
ASSERT_EQ(releasedSpy.count(), 1);
@@ -351,6 +355,9 @@ TEST(MouseEventHandlerTest, MousePressReleaseEvent)
351355
releasedSpy.clear();
352356

353357
// Send release (should be sent to stage)
358+
EXPECT_CALL(renderedTarget3, contains(localPos)).WillOnce(Return(false));
359+
EXPECT_CALL(renderedTarget1, contains(localPos)).WillOnce(Return(false));
360+
EXPECT_CALL(renderedTarget2, contains(localPos)).WillOnce(Return(false));
354361
EXPECT_CALL(stage, mouseReleaseEvent(_)).WillOnce(WithArgs<0>(Invoke(checkReleaseEvent)));
355362
ASSERT_TRUE(handler.eventFilter(nullptr, &releaseEvent));
356363
ASSERT_EQ(pressedSpy.count(), 0);

0 commit comments

Comments
 (0)