/** * @brief Called when we are in UI mode and down a mouse button * @sa UI_LeftClick * @sa UI_RightClick * @sa UI_MiddleClick */ void UI_MouseDown (int x, int y, int button) { /* disable old long click event */ if (longPressTimer) UI_TimerStop(longPressTimer); uiNode_t* node; /* captured or hover node */ node = capturedNode ? capturedNode : hoveredNode; if (node != nullptr) { UI_MoveWindowOnTop(node->root); UI_Node_MouseDown(node, x, y, button); } /* select clickableNode on button up, and detect multipress button */ if (pressedNode == nullptr) { pressedNode = node; pressedNodeLocationX = x; pressedNodeLocationY = y; pressedNodeButton = button; /** @todo find a way to create the timer when UI loading and remove "if (longPressTimer)" */ if (longPressTimer == nullptr) { longPressTimer = UI_AllocTimer(nullptr, LONGPRESS_DELAY, UI_LongPressCallback); } UI_TimerStart(longPressTimer); } else { pressedNode = nullptr; } }
/** * @brief unittest around timer data structure. * It not test timer execution. */ TEST_F(UITest, TimerDataStructure) { uiNode_t* dummyNode = (uiNode_t*) 0x1; timerCallback_t dummyCallback = (timerCallback_t) 0x1; uiTimer_t* a, *b, *c; a = UI_AllocTimer(dummyNode, 10, dummyCallback); b = UI_AllocTimer(dummyNode, 20, dummyCallback); c = UI_AllocTimer(dummyNode, 30, dummyCallback); ASSERT_TRUE(UI_PrivateGetFirstTimer() == nullptr); UI_TimerStart(b); ASSERT_TRUE(UI_PrivateGetFirstTimer() == b); UI_TimerStart(a); ASSERT_TRUE(UI_PrivateGetFirstTimer() == a); UI_TimerStart(c); ASSERT_TRUE(UI_PrivateGetFirstTimer()->next->next == c); UI_TimerStop(a); UI_TimerStop(b); ASSERT_TRUE(a->owner != nullptr); ASSERT_TRUE(UI_PrivateGetFirstTimer() == c); ASSERT_TRUE(UI_PrivateGetFirstTimer()->next == nullptr); UI_TimerStart(a); ASSERT_TRUE(UI_PrivateGetFirstTimer() == a); ASSERT_TRUE(UI_PrivateGetFirstTimer()->next == c); UI_PrivateInsertTimerInActiveList(a->next, b); ASSERT_TRUE(UI_PrivateGetFirstTimer() == a); ASSERT_TRUE(UI_PrivateGetFirstTimer()->next == b); ASSERT_TRUE(UI_PrivateGetFirstTimer()->next->next == c); UI_TimerRelease(b); ASSERT_TRUE(UI_PrivateGetFirstTimer() == a); ASSERT_TRUE(UI_PrivateGetFirstTimer()->next == c); UI_TimerRelease(a); ASSERT_TRUE(UI_PrivateGetFirstTimer() == c); UI_TimerRelease(c); ASSERT_TRUE(UI_PrivateGetFirstTimer() == nullptr); ASSERT_TRUE(c->owner == nullptr); }
/** * Callback function waked up to send long click event */ static void UI_LongPressCallback (uiNode_t* , uiTimer_t* timer) { UI_TimerStop(timer); /* make sure the event still make sense */ if (pressedNode == nullptr) return; uiNode_t* node = pressedNode; while (node) { if (UI_Node_MouseLongPress(node, pressedNodeLocationX, pressedNodeLocationY, pressedNodeButton)) break; node = node->parent; } }
/** * @brief Called when we are in UI mode and up a mouse button * @sa UI_LeftClick * @sa UI_RightClick * @sa UI_MiddleClick */ void UI_MouseUp (int x, int y, int button) { /* disable long click event */ if (longPressTimer) UI_TimerStop(longPressTimer); /* send click event */ /** @todo it is really need to clean up this subfunctions */ if (pressedNode || capturedNode) { switch (button) { case K_MOUSE1: UI_LeftClick(x, y); break; case K_MOUSE2: UI_RightClick(x, y); break; case K_MOUSE3: UI_MiddleClick(x, y); break; } } /* captured or hovered node */ uiNode_t* node = nullptr; if (capturedNode) { node = capturedNode; } else if (pressedNode == hoveredNode) { node = hoveredNode; } pressedNode = nullptr; if (node == nullptr) return; UI_Node_MouseUp(node, x, y, button); }
/** * @brief Is called every time the mouse position change */ void UI_MouseMove (int x, int y) { if (UI_DNDIsDragging()) return; if (pressedNode && !capturedNode) { if (pressedNodeLocationX != UI_STARTDRAG_ALREADY_SENT) { UI_TimerStop(longPressTimer); int dist = abs(pressedNodeLocationX - x) + abs(pressedNodeLocationY - y); if (dist > 4) { uiNode_t* node = pressedNode; while (node) { if (UI_Node_StartDragging(node, pressedNodeLocationX, pressedNodeLocationY, x, y, pressedNodeButton)) break; node = node->parent; } pressedNodeLocationX = UI_STARTDRAG_ALREADY_SENT; } } } /* send the captured move mouse event */ if (capturedNode) { UI_Node_CapturedMouseMove(capturedNode, x, y); return; } hoveredNode = UI_GetNodeAtPosition(x, y); /* update houvered node by sending messages */ if (oldHoveredNode != hoveredNode) { uiNode_t* commonNode = hoveredNode; uiNode_t* node; /* search the common node */ while (commonNode) { node = oldHoveredNode; while (node) { if (node == commonNode) break; node = node->parent; } if (node != nullptr) break; commonNode = commonNode->parent; } /* send 'leave' event from old node to common node */ node = oldHoveredNode; while (node != commonNode) { UI_Node_MouseLeave(node); node = node->parent; } if (oldHoveredNode) oldHoveredNode->state = false; /* send 'enter' event from common node to new node */ while (commonNode != hoveredNode) { /** @todo we can remove that loop with an array allocation */ node = hoveredNode; while (node->parent != commonNode) node = node->parent; commonNode = node; UI_Node_MouseEnter(node); } if (hoveredNode) { hoveredNode->state = true; UI_Node_MouseEnter(node); } } oldHoveredNode = hoveredNode; /* send the move event */ if (hoveredNode) UI_Node_MouseMove(hoveredNode, x, y); }