Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Context Menus (Popup) are sometimes broken in High-DPI applications in .NET 4.8 #2088

Open
vatsan-madhavan opened this issue Oct 22, 2019 · 1 comment
Labels
Bug Product bug (most likely) issue-type-netfx-port Ports from .NET Framework .NET Framework regression status: This issue is a regression from a previous build or release tenet-reliability Reliability related issue
Milestone

Comments

@vatsan-madhavan
Copy link
Member

microsoft/dotnet#1036 (comment)

After installing .NET 4.8 we have observed that Context menus via the Popup class show strange effects.

  1. Popup is placed at top left corner
  2. Popup comes up empty
  3. Popup has no styles applied
  4. Alternating behavior:
    a) Popup works.
    b) Popup comes up empty
    ....

I have debugged that issue and found that the is Popup is sometimes destroyed while the popup window is meant to be created:

The diff from .NET 4.7.2 to 4.8 shows this new code was added:

image

This leads to the call stack that the popup is killed while it is beeing created:

0:000> !ClrStack
OS Thread Id: 0x2180 (0)
Call Site
System.Windows.Controls.Primitives.Popup.DestroyWindow()
System.Windows.Controls.Primitives.Popup.CreateWindow(Boolean)

System.Windows.Controls.Primitives.Popup.OnIsOpenChanged(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.DependencyObject.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.FrameworkElement.OnPropertyChanged(System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex, System.Windows.DependencyProperty, System.Windows.PropertyMetadata, System.Windows.EffectiveValueEntry, System.Windows.EffectiveValueEntry ByRef, Boolean, Boolean, System.Windows.OperationType)
System.Windows.DependencyObject.InvalidateProperty(System.Windows.DependencyProperty, Boolean)
System.Windows.Data.BindingExpressionBase.Invalidate(Boolean)
System.Windows.Data.BindingExpression.TransferValue(System.Object, Boolean)
MS.Internal.Data.ClrBindingWorker.NewValueAvailable(Boolean, Boolean, Boolean)
MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32, System.ComponentModel.ICollectionView, System.Object, Boolean)
MS.Internal.Data.PropertyPathWorker.OnDependencyPropertyChanged(System.Windows.DependencyObject, System.Windows.DependencyProperty, Boolean)
System.Windows.Data.BindingExpression.HandlePropertyInvalidation(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.Data.BindingExpressionBase.OnPropertyInvalidation(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.Data.BindingExpression.OnPropertyInvalidation(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.DependentList.InvalidateDependents(System.Windows.DependencyObject, System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.DependencyObject.NotifyPropertyChange(System.Windows.DependencyPropertyChangedEventArgs)
System.Windows.DependencyObject.UpdateEffectiveValue(System.Windows.EntryIndex, System.Windows.DependencyProperty, System.Windows.PropertyMetadata, System.Windows.EffectiveValueEntry, System.Windows.EffectiveValueEntry ByRef, Boolean, Boolean, System.Windows.OperationType)
System.Windows.DependencyObject.SetValueCommon(System.Windows.DependencyProperty, System.Object, System.Windows.PropertyMetadata, Boolean, Boolean, System.Windows.OperationType, Boolean)
System.Windows.DependencyObject.SetCurrentValueInternal(System.Windows.DependencyProperty, System.Object)

System.Windows.Controls.PopupControlService.**RaiseContextMenuOpeningEvent**(System.Windows.IInputElement, Double, Double, Boolean)

System.Windows.Controls.PopupControlService.ProcessMouseUp(System.Object, System.Windows.Input.MouseButtonEventArgs)
System.Windows.Controls.PopupControlService.OnPostProcessInput(System.Object, System.Windows.Input.ProcessInputEventArgs)
System.Windows.Input.InputManager.RaiseProcessInputEventHandlers(System.Windows.Input.ProcessInputEventHandler, System.Windows.Input.ProcessInputEventArgs)
System.Windows.Input.InputManager.ProcessStagingArea()
System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs)
System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport)
System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr, System.Windows.Input.InputMode, Int32, System.Windows.Input.RawMouseActions, Int32, Int32, Int32)
System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr, MS.Internal.Interop.WindowMessage, IntPtr, IntPtr, Boolean ByRef)
System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)

To me this looks like an error. The window should not be killed when it is already (partially) active. This call should therefore be moved to the check where BuildWindow is beeing called.
After setting the AppContext switch

  <runtime>
    <AppContextSwitchOverrides value="Switch.System.Windows.DoNotScaleForDpiChanges=true" />
  </runtime>

the issue does go away. This has therefore something to do with the monitor scaling flag during Popup.CreateWindow.

@ryalanms
Copy link
Member

@vatsan-madhavan: Was this fixed with your PR #2098?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Product bug (most likely) issue-type-netfx-port Ports from .NET Framework .NET Framework regression status: This issue is a regression from a previous build or release tenet-reliability Reliability related issue
Projects
None yet
Development

No branches or pull requests

2 participants