@@ -1558,39 +1558,56 @@ private void AddPoints(PointList points, in NativeMethods.RECT rect, bool rectIs
1558
1558
// Test whether the current mouse point lies within the convex hull
1559
1559
internal bool ContainsMousePoint ( )
1560
1560
{
1561
- IInputElement rootElement = _source . RootVisual as IInputElement ;
1562
- if ( rootElement != null )
1561
+ // get the coordinates of the current mouse point, relative to the Active source
1562
+ PresentationSource mouseSource = Mouse . PrimaryDevice . CriticalActiveSource ;
1563
+ System . Windows . Point pt = Mouse . PrimaryDevice . NonRelativePosition ;
1564
+
1565
+ // translate the point to our source's coordinates, if necessary
1566
+ // (e.g. if the tooltip's owner comes from a window with capture,
1567
+ // such as the popup of a ComboBox)
1568
+ if ( mouseSource != _source )
1563
1569
{
1564
- // get the coordinates of the current mouse point, relative to our PresentationSource
1565
- System . Windows . Point pt = Mouse . PrimaryDevice . GetPosition ( rootElement ) ;
1566
-
1567
- // check whether the point lies within the hull
1568
- return ContainsPoint ( _source , ( int ) pt . X , ( int ) pt . Y ) ;
1569
-
1570
- // NOTE: GetPosition doesn't actually return the position of the current mouse point,
1571
- // but rather the last recorded position. (See MouseDevice.GetScreenPositionFromSystem,
1572
- // which says that "Win32 has issues reliably returning where the mouse is".)
1573
- // This causes a small problem when (a) the PresentationSource has capture, e.g.
1574
- // the popup of a ComboBox, and (b) the mouse moves to a position that lies outside both the
1575
- // capturing PresentationSource (popup window) and the input-providing PresentationSource
1576
- // (main window). The MouseDevice only records positions within the input-providing
1577
- // PresentationSource, so we'll test the position where the mouse left the main window,
1578
- // rather than the current position.
1579
- // This means we may leave a tooltip open even when the mouse leaves its SafeArea,
1580
- // but only when the tooltip belongs to a capturing source, and the "leaving the SafeArea"
1581
- // action occurs outside the surrounding main window. For our example, it can happen
1582
- // when the ComboBox is close to the edge of the main window so that a tooltip from its
1583
- // popup content extends beyond the main window.
1584
- // This can only be fixed by changing MouseDevice.GetScreenPositionFromSystem to
1585
- // use a "better way" to find the current mouse position, which allegedly needs work from the OS.
1586
- // But we can live with this behavior, because
1587
- // * this is a corner case - tooltips from popup content that extend beyond the main window
1588
- // * the effect is transient - the tooltip will close when the user dismisses the popup
1589
- // * there's no accessibility issue - WCAG 2.1 only requires that the tooltip stays open under
1590
- // proscribed conditions, not that it has to close when the conditions cease to apply
1570
+ System . Windows . Point ptScreen = PointUtil . ClientToScreen ( pt , mouseSource ) ;
1571
+ pt = PointUtil . ScreenToClient ( ptScreen , _source ) ;
1591
1572
}
1592
- else
1593
- return false ;
1573
+
1574
+ #if DEBUG
1575
+ // NonRelativePosition returns the mouse point in unscaled screen coords, relative
1576
+ // to the active window's client area (despite the name).
1577
+ // Compute the point a different way, and check that it agrees. The second
1578
+ // way uses public API, but in our case ends up doing a lot of transforms
1579
+ // and multiplications that should simply cancel each other out.
1580
+ System . Windows . Interop . HwndSource hwndSource = _source as System . Windows . Interop . HwndSource ;
1581
+ IInputElement rootElement = hwndSource ? . RootVisual as IInputElement ;
1582
+ Debug . Assert ( hwndSource != null && rootElement != null , "expect non-null hwndSource and rootElement" ) ;
1583
+ System . Windows . Point pt2 = hwndSource . TransformToDevice ( Mouse . PrimaryDevice . GetPosition ( rootElement ) ) ;
1584
+ Debug . Assert ( ( ( int ) pt . X == ( int ) Math . Round ( pt2 . X ) ) && ( ( int ) pt . Y == ( int ) Math . Round ( pt2 . Y ) ) , "got incorrect mouse point" ) ;
1585
+ #endif
1586
+
1587
+ // check whether the point lies within the hull
1588
+ return ContainsPoint ( _source , ( int ) pt . X , ( int ) pt . Y ) ;
1589
+
1590
+ // NOTE: NonRelativePosition doesn't actually return the position of the current mouse point,
1591
+ // but rather the last recorded position. (See MouseDevice.GetScreenPositionFromSystem,
1592
+ // which says that "Win32 has issues reliably returning where the mouse is".)
1593
+ // This causes a small problem when (a) the PresentationSource has capture, e.g.
1594
+ // the popup of a ComboBox, and (b) the mouse moves to a position that lies outside both the
1595
+ // capturing PresentationSource (popup window) and the input-providing PresentationSource
1596
+ // (main window). The MouseDevice only records positions within the input-providing
1597
+ // PresentationSource, so we'll test the position where the mouse left the main window,
1598
+ // rather than the current position.
1599
+ // This means we may leave a tooltip open even when the mouse leaves its SafeArea,
1600
+ // but only when the tooltip belongs to a capturing source, and the "leaving the SafeArea"
1601
+ // action occurs outside the surrounding main window. For our example, it can happen
1602
+ // when the ComboBox is close to the edge of the main window so that a tooltip from its
1603
+ // popup content extends beyond the main window.
1604
+ // This can only be fixed by changing MouseDevice.GetScreenPositionFromSystem to
1605
+ // use a "better way" to find the current mouse position, which allegedly needs work from the OS.
1606
+ // But we can live with this behavior, because
1607
+ // * this is a corner case - tooltips from popup content that extend beyond the main window
1608
+ // * the effect is transient - the tooltip will close when the user dismisses the popup
1609
+ // * there's no accessibility issue - WCAG 2.1 only requires that the tooltip stays open under
1610
+ // proscribed conditions, not that it has to close when the conditions cease to apply
1594
1611
}
1595
1612
1596
1613
// Test whether a given mouse point (x,y) lies within the convex hull
0 commit comments