未验证 提交 a539c26b 编写于 作者: S Sam Bent 提交者: GitHub

reset ContextMenu whose popup cannot be opened (#5843)

上级 1878ed9f
...@@ -266,7 +266,7 @@ private void UpdatePlacementTargetRegistration(UIElement oldValue, UIElement new ...@@ -266,7 +266,7 @@ private void UpdatePlacementTargetRegistration(UIElement oldValue, UIElement new
// for the the PlacementTarget is separate from that for the Popup itself. // for the the PlacementTarget is separate from that for the Popup itself.
// This causes Popup and its descedents to miss some change notifications. // This causes Popup and its descedents to miss some change notifications.
// Thus a Popup that isnt connected to the tree in any way should be // Thus a Popup that isnt connected to the tree in any way should be
// designated standalone and thus IsSelfInheritanceParent = true. // designated standalone and thus IsSelfInheritanceParent = true.
if (!this.IsSelfInheritanceParent) if (!this.IsSelfInheritanceParent)
{ {
this.SetIsSelfInheritanceParent(); this.SetIsSelfInheritanceParent();
...@@ -878,14 +878,14 @@ public static void CreateRootPopup(Popup popup, UIElement child) ...@@ -878,14 +878,14 @@ public static void CreateRootPopup(Popup popup, UIElement child)
} }
/// <summary> /// <summary>
/// Internal implementation of CreateRootPopup to allow tooltips to /// Internal implementation of CreateRootPopup to allow tooltips to
/// override the popup's placement in case the tooltip comes from keyboard focus. /// override the popup's placement in case the tooltip comes from keyboard focus.
/// </summary> /// </summary>
/// <param name="popup">The parent popup that the child will be hooked up to.</param> /// <param name="popup">The parent popup that the child will be hooked up to.</param>
/// <param name="child">The element to be the child of the popup.</param> /// <param name="child">The element to be the child of the popup.</param>
/// <param name="bindTreatMousePlacementAsBottomProperty">Whether to bind TreatMousePlacementAsBottomProperty to the child's FromKeyboard property</param> /// <param name="bindTreatMousePlacementAsBottomProperty">Whether to bind TreatMousePlacementAsBottomProperty to the child's FromKeyboard property</param>
internal static void CreateRootPopupInternal(Popup popup, UIElement child, bool bindTreatMousePlacementAsBottomProperty) internal static void CreateRootPopupInternal(Popup popup, UIElement child, bool bindTreatMousePlacementAsBottomProperty)
{ {
if (popup == null) if (popup == null)
{ {
throw new ArgumentNullException("popup"); throw new ArgumentNullException("popup");
...@@ -954,7 +954,7 @@ internal static void CreateRootPopupInternal(Popup popup, UIElement child, bool ...@@ -954,7 +954,7 @@ internal static void CreateRootPopupInternal(Popup popup, UIElement child, bool
binding.Mode = BindingMode.OneWay; binding.Mode = BindingMode.OneWay;
binding.Source = child; binding.Source = child;
popup.SetBinding(CustomPopupPlacementCallbackProperty, binding); popup.SetBinding(CustomPopupPlacementCallbackProperty, binding);
if (bindTreatMousePlacementAsBottomProperty) if (bindTreatMousePlacementAsBottomProperty)
{ {
binding = new Binding("FromKeyboard"); binding = new Binding("FromKeyboard");
...@@ -1490,6 +1490,12 @@ private void CreateWindow(bool asyncCall) ...@@ -1490,6 +1490,12 @@ private void CreateWindow(bool asyncCall)
// We'll defer until later if not already in an async call. // We'll defer until later if not already in an async call.
_asyncCreate = Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(AsyncCreateWindow), this); _asyncCreate = Dispatcher.BeginInvoke(DispatcherPriority.Input, new DispatcherOperationCallback(AsyncCreateWindow), this);
} }
else
{
// if the target is still not hooked up in the async call, the popup cannot
// be opened; raise the CouldClosed event, to inform the original caller
FirePopupCouldClose();
}
return; return;
} }
...@@ -1506,7 +1512,7 @@ private void CreateWindow(bool asyncCall) ...@@ -1506,7 +1512,7 @@ private void CreateWindow(bool asyncCall)
// When running in Per-Monitor DPI aware mode, always create a new window // When running in Per-Monitor DPI aware mode, always create a new window
// This ensures that a recycled HWND that is moving from one display // This ensures that a recycled HWND that is moving from one display
// to another does not undergo a WM_DPICHANGED event and thus cause a // to another does not undergo a WM_DPICHANGED event and thus cause a
// cascading failure. // cascading failure.
if (PopupInitialPlacementHelper.IsPerMonitorDpiScalingActive) if (PopupInitialPlacementHelper.IsPerMonitorDpiScalingActive)
{ {
...@@ -1583,8 +1589,8 @@ private void BuildWindow(Visual targetVisual) ...@@ -1583,8 +1589,8 @@ private void BuildWindow(Visual targetVisual)
// We many not have attempted to position the popup yet // We many not have attempted to position the popup yet
// //
// If we don't have prior position information and we are currently running in Per-Monitor DPI Aware mode, // If we don't have prior position information and we are currently running in Per-Monitor DPI Aware mode,
// we should build the window by specifying a point on the current monitor. // we should build the window by specifying a point on the current monitor.
// Doing so ensures that the underlying HWND is created with the right DPI. Otherwise, the HWND that is created at // Doing so ensures that the underlying HWND is created with the right DPI. Otherwise, the HWND that is created at
// (0,0) and then shown on another monitor with a different DPI, will immediately receive a WM_DPICHANGED message. This // (0,0) and then shown on another monitor with a different DPI, will immediately receive a WM_DPICHANGED message. This
// will in turn cause the HWND to be resized, and its layout to be updated. This layout-update can result in the dismissal // will in turn cause the HWND to be resized, and its layout to be updated. This layout-update can result in the dismissal
...@@ -1592,7 +1598,7 @@ private void BuildWindow(Visual targetVisual) ...@@ -1592,7 +1598,7 @@ private void BuildWindow(Visual targetVisual)
// //
// PopupInitialPlacementHelper.GetPlacementOrigin() will return (0,0) when running in SystemAware and Unaware mode. // PopupInitialPlacementHelper.GetPlacementOrigin() will return (0,0) when running in SystemAware and Unaware mode.
// When running in Per-Monitor DPI Aware mode, this method will obtain the screen coordinates of the (left, top) of // When running in Per-Monitor DPI Aware mode, this method will obtain the screen coordinates of the (left, top) of
// the Display on which the PopupRoot is situated, and return that value here. // the Display on which the PopupRoot is situated, and return that value here.
var origin = var origin =
_positionInfo != null _positionInfo != null
? new NativeMethods.POINT(_positionInfo.X, _positionInfo.Y) ? new NativeMethods.POINT(_positionInfo.X, _positionInfo.Y)
...@@ -1876,14 +1882,14 @@ private void OnWindowResize(object sender, AutoResizedEventArgs e) ...@@ -1876,14 +1882,14 @@ private void OnWindowResize(object sender, AutoResizedEventArgs e)
private void OnDpiChanged(object sender, HwndDpiChangedEventArgs e) private void OnDpiChanged(object sender, HwndDpiChangedEventArgs e)
{ {
// Popups do not handle layout updates due to DPI changes very well when they are visible. // Popups do not handle layout updates due to DPI changes very well when they are visible.
// Ignore DPI change induced layout-updates when visible. // Ignore DPI change induced layout-updates when visible.
// This brings the behavior of Popups in line with .NET 4.7.2. Currently, // This brings the behavior of Popups in line with .NET 4.7.2. Currently,
// there is no reliable way to opt-into the DPI improvements made in .NET 4.8 // there is no reliable way to opt-into the DPI improvements made in .NET 4.8
// wholesale for Popups. By creating the Popups more intelligently on the right // wholesale for Popups. By creating the Popups more intelligently on the right
// target monitor, we will vastly improve the DPI scaling of the Popups // target monitor, we will vastly improve the DPI scaling of the Popups
// in .NET 4.8. In rare situations where a DPI change requires a visible Popups // in .NET 4.8. In rare situations where a DPI change requires a visible Popups
// to adapt and resize itself on-the-fly while continuing to remain visible, // to adapt and resize itself on-the-fly while continuing to remain visible,
// it will fail to adapt to that particular DPI change. // it will fail to adapt to that particular DPI change.
if (IsOpen) if (IsOpen)
{ {
...@@ -3376,7 +3382,7 @@ private static Visual FindMainTreeVisual(Visual v) ...@@ -3376,7 +3382,7 @@ private static Visual FindMainTreeVisual(Visual v)
// add AddAutoResizedEventHandler event handler // add AddAutoResizedEventHandler event handler
newWindow.AutoResized += handler; newWindow.AutoResized += handler;
// add the DpiChagnedEventHandler // add the DpiChagnedEventHandler
newWindow.DpiChanged += dpiChangedHandler; newWindow.DpiChanged += dpiChangedHandler;
} }
...@@ -3507,21 +3513,21 @@ internal void DestroyWindow(HwndSourceHook hook, AutoResizedEventHandler onAutoR ...@@ -3507,21 +3513,21 @@ internal void DestroyWindow(HwndSourceHook hook, AutoResizedEventHandler onAutoR
#endregion #endregion
/// <summary> /// <summary>
/// Helper to find the (left, top) of the monitor that contains the placement target, in screen coordinates. /// Helper to find the (left, top) of the monitor that contains the placement target, in screen coordinates.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Normally, the HWND associated with a Popup is created at (0,0), and then 'moved' to the appropriate location.This can /// Normally, the HWND associated with a Popup is created at (0,0), and then 'moved' to the appropriate location.This can
/// lead to a DPI change when (0,0) lies on another monitor with a different DPI. DPI changes typically lead to size changes /// lead to a DPI change when (0,0) lies on another monitor with a different DPI. DPI changes typically lead to size changes
/// as well, which can lead to dismissals of Popups. To prevent this, we should create the HWND associated with a Popup /// as well, which can lead to dismissals of Popups. To prevent this, we should create the HWND associated with a Popup
/// on the correct monitor. This helper will identify the origin of the monitor associated with the placement target to help /// on the correct monitor. This helper will identify the origin of the monitor associated with the placement target to help
/// with this. /// with this.
/// </remarks> /// </remarks>
private static class PopupInitialPlacementHelper private static class PopupInitialPlacementHelper
{ {
/// <summary> /// <summary>
/// Decides whether this helper should be used. /// Decides whether this helper should be used.
/// This helper is used when - /// This helper is used when -
/// a. WPF supports DPI scaling (HwndTarget.IsPerMonitorDpiScalingEnabled), and /// a. WPF supports DPI scaling (HwndTarget.IsPerMonitorDpiScalingEnabled), and
/// b. The process is PMA (HwndTarget.IsProcessPerMonitorDpiAware) /// b. The process is PMA (HwndTarget.IsProcessPerMonitorDpiAware)
/// </summary> /// </summary>
/// <remarks> /// <remarks>
...@@ -3539,10 +3545,10 @@ internal static bool IsPerMonitorDpiScalingActive ...@@ -3539,10 +3545,10 @@ internal static bool IsPerMonitorDpiScalingActive
return HwndTarget.IsProcessPerMonitorDpiAware.Value; return HwndTarget.IsProcessPerMonitorDpiAware.Value;
} }
// WPF supports Per-Monitor scaling, but HwndTarget has not // WPF supports Per-Monitor scaling, but HwndTarget has not
// yet been initialized with the first HWND, and therefore // yet been initialized with the first HWND, and therefore
// HwndTarget.IsProcessPerMonitorDpiAware is not queryable. // HwndTarget.IsProcessPerMonitorDpiAware is not queryable.
// Let's use the current process' DPI awareness as a proxy. // Let's use the current process' DPI awareness as a proxy.
return DpiUtil.GetProcessDpiAwareness(IntPtr.Zero) == NativeMethods.PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE; return DpiUtil.GetProcessDpiAwareness(IntPtr.Zero) == NativeMethods.PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE;
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册