void DispatchMouseOverMouseOut(VisualElement previousTopElementUnderMouse, VisualElement currentTopElementUnderMouse, IMouseEvent triggerEvent) { if (previousTopElementUnderMouse == currentTopElementUnderMouse) { return; } // Send MouseOut event for element no longer under the mouse. if (previousTopElementUnderMouse != null && previousTopElementUnderMouse.panel != null) { using (var outEvent = (triggerEvent == null) ? MouseOutEvent.GetPooled(m_LastMousePosition) : MouseOutEvent.GetPooled(triggerEvent)) { outEvent.target = previousTopElementUnderMouse; previousTopElementUnderMouse.SendEvent(outEvent); } } // Send MouseOver event for element now under the mouse if (currentTopElementUnderMouse != null) { using (var overEvent = (triggerEvent == null) ? MouseOverEvent.GetPooled(m_LastMousePosition) : MouseOverEvent.GetPooled(triggerEvent)) { overEvent.target = currentTopElementUnderMouse; currentTopElementUnderMouse.SendEvent(overEvent); } } }
private void UpdateSubTree(VisualElement root) { Rect yogaRect = new Rect(root.yogaNode.LayoutX, root.yogaNode.LayoutY, root.yogaNode.LayoutWidth, root.yogaNode.LayoutHeight); Rect lastRect = root.renderData.lastLayout; bool rectChanged = lastRect != yogaRect; // If the last layout rect is different than the current one we must dirty transform on children if (rectChanged) { if (yogaRect.position != lastRect.position) { root.IncrementVersion(VersionChangeType.Transform); } root.IncrementVersion(VersionChangeType.Clip); root.renderData.lastLayout = yogaRect; } // ignore clean sub trees bool hasNewLayout = root.yogaNode.HasNewLayout; if (hasNewLayout) { for (int i = 0; i < root.shadow.childCount; ++i) { UpdateSubTree(root.shadow[i]); } } if (rectChanged) { using (var evt = GeometryChangedEvent.GetPooled(lastRect, yogaRect)) { evt.target = root; root.SendEvent(evt); } } if (hasNewLayout) { root.yogaNode.MarkLayoutSeen(); // Layout change require a repaint root.IncrementVersion(VersionChangeType.Repaint); } }
void DispatchEnterLeave(VisualElement previousTopElementUnderMouse, VisualElement currentTopElementUnderMouse, Func <EventBase> getEnterEventFunc, Func <EventBase> getLeaveEventFunc) { if (previousTopElementUnderMouse == currentTopElementUnderMouse) { return; } if (previousTopElementUnderMouse != null && previousTopElementUnderMouse.panel == null) { // If previousTopElementUnderMouse has been removed from panel, // do as if there is no element under the mouse. previousTopElementUnderMouse = null; } // We want to find the common ancestor CA of previousTopElementUnderMouse and currentTopElementUnderMouse, // send Leave (MouseLeave or DragLeave) events to elements between CA and previousTopElementUnderMouse // and send Enter (MouseEnter or DragEnter) events to elements between CA and currentTopElementUnderMouse. int prevDepth = 0; var p = previousTopElementUnderMouse; while (p != null) { prevDepth++; p = p.shadow.parent; } int currDepth = 0; var c = currentTopElementUnderMouse; while (c != null) { currDepth++; c = c.shadow.parent; } p = previousTopElementUnderMouse; c = currentTopElementUnderMouse; while (prevDepth > currDepth) { using (var leaveEvent = getLeaveEventFunc()) { leaveEvent.target = p; p.SendEvent(leaveEvent); } prevDepth--; p = p.shadow.parent; } // We want to send enter events after all the leave events. // We will store the elements being entered in this list. List <VisualElement> enteringElements = VisualElementListPool.Get(currDepth); while (currDepth > prevDepth) { enteringElements.Add(c); currDepth--; c = c.shadow.parent; } // Now p and c are at the same depth. Go up the tree until p == c. while (p != c) { using (var leaveEvent = getLeaveEventFunc()) { leaveEvent.target = p; p.SendEvent(leaveEvent); } enteringElements.Add(c); p = p.shadow.parent; c = c.shadow.parent; } for (var i = enteringElements.Count - 1; i >= 0; i--) { using (var enterEvent = getEnterEventFunc()) { enterEvent.target = enteringElements[i]; enteringElements[i].SendEvent(enterEvent); } } VisualElementListPool.Release(enteringElements); }