Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ private void UpdatePlacementTargetRegistration(UIElement oldValue, UIElement new
// for the the PlacementTarget is separate from that for the Popup itself.
// 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
// designated standalone and thus IsSelfInheritanceParent = true.
// designated standalone and thus IsSelfInheritanceParent = true.
if (!this.IsSelfInheritanceParent)
{
this.SetIsSelfInheritanceParent();
Expand Down Expand Up @@ -878,14 +878,14 @@ public static void CreateRootPopup(Popup popup, UIElement child)
}

/// <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.
/// </summary>
/// <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="bindTreatMousePlacementAsBottomProperty">Whether to bind TreatMousePlacementAsBottomProperty to the child's FromKeyboard property</param>
internal static void CreateRootPopupInternal(Popup popup, UIElement child, bool bindTreatMousePlacementAsBottomProperty)
{
{
if (popup == null)
{
throw new ArgumentNullException("popup");
Expand Down Expand Up @@ -954,7 +954,7 @@ internal static void CreateRootPopupInternal(Popup popup, UIElement child, bool
binding.Mode = BindingMode.OneWay;
binding.Source = child;
popup.SetBinding(CustomPopupPlacementCallbackProperty, binding);

if (bindTreatMousePlacementAsBottomProperty)
{
binding = new Binding("FromKeyboard");
Expand Down Expand Up @@ -1490,6 +1490,12 @@ private void CreateWindow(bool asyncCall)
// We'll defer until later if not already in an async call.
_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;
}
Expand All @@ -1506,7 +1512,7 @@ private void CreateWindow(bool asyncCall)

// 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
// 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.
if (PopupInitialPlacementHelper.IsPerMonitorDpiScalingActive)
{
Expand Down Expand Up @@ -1583,16 +1589,16 @@ private void BuildWindow(Visual targetVisual)

// 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,
// we should build the window by specifying a point on the current monitor.
// 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.
// 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
// will in turn cause the HWND to be resized, and its layout to be updated. This layout-update can result in the dismissal
// of the popup itself, esp. if this Popup is rooted on another Popup.
//
// 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
// 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 =
_positionInfo != null
? new NativeMethods.POINT(_positionInfo.X, _positionInfo.Y)
Expand Down Expand Up @@ -1876,14 +1882,14 @@ private void OnWindowResize(object sender, AutoResizedEventArgs e)

private void OnDpiChanged(object sender, HwndDpiChangedEventArgs e)
{
// Popups do not handle layout updates due to DPI changes very well when they are visible.
// Ignore DPI change induced layout-updates when visible.
// This brings the behavior of Popups in line with .NET 4.7.2. Currently,
// Popups do not handle layout updates due to DPI changes very well when they are visible.
// Ignore DPI change induced layout-updates when visible.
// 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
// wholesale for Popups. By creating the Popups more intelligently on the right
// 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
// 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.
if (IsOpen)
{
Expand Down Expand Up @@ -3376,7 +3382,7 @@ internal void BuildWindow(int x, int y, Visual placementTarget,
// add AddAutoResizedEventHandler event handler
newWindow.AutoResized += handler;

// add the DpiChagnedEventHandler
// add the DpiChagnedEventHandler
newWindow.DpiChanged += dpiChangedHandler;
}

Expand Down Expand Up @@ -3507,21 +3513,21 @@ internal void DestroyWindow(HwndSourceHook hook, AutoResizedEventHandler onAutoR
#endregion

/// <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>
/// <remarks>
/// 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
/// 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
/// with this.
/// with this.
/// </remarks>
private static class PopupInitialPlacementHelper
{
/// <summary>
/// Decides whether this helper should be used.
/// This helper is used when -
/// a. WPF supports DPI scaling (HwndTarget.IsPerMonitorDpiScalingEnabled), and
/// Decides whether this helper should be used.
/// This helper is used when -
/// a. WPF supports DPI scaling (HwndTarget.IsPerMonitorDpiScalingEnabled), and
/// b. The process is PMA (HwndTarget.IsProcessPerMonitorDpiAware)
/// </summary>
/// <remarks>
Expand All @@ -3539,10 +3545,10 @@ internal static bool IsPerMonitorDpiScalingActive
return HwndTarget.IsProcessPerMonitorDpiAware.Value;
}

// WPF supports Per-Monitor scaling, but HwndTarget has not
// yet been initialized with the first HWND, and therefore
// HwndTarget.IsProcessPerMonitorDpiAware is not queryable.
// Let's use the current process' DPI awareness as a proxy.
// WPF supports Per-Monitor scaling, but HwndTarget has not
// yet been initialized with the first HWND, and therefore
// HwndTarget.IsProcessPerMonitorDpiAware is not queryable.
// 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;
}
}
Expand Down