microsoft / microsoft-ui-xaml

Windows UI Library: the latest Windows 10 native controls and Fluent styles for your applications
MIT License
6.26k stars 672 forks source link

DisplayAreaWatcher Added and Removed events is not triggered when monitors are added or removed #9244

Open torfluor opened 9 months ago

torfluor commented 9 months ago

Describe the bug

I'm making a presentation application, and I need to update the UI when an external monitor is connected or disconnected. For this I have implemented DisplayAreaWatcher where I listen for Added and Removed events. These events are not triggered when I connect or disconnect physical monitors to the PC while the application is running.

I have made a test application that shows the issue: https://github.com/torfluor/DisplayAreaWatcherTest

Please let me know if I'm using the wrong method and if there is a better way to detect when monitors are connected and disconnected

Steps to reproduce the bug

  1. Create a new WinUI3 application
  2. In the MainWindow class add a new DisplayAreaWatcher and subscribe to Added and Removed events with printouts to the debug console.
  3. Run the application on a laptop not connected to an external montor.
  4. Watch that the Added event is triggered during startup
  5. Connect an external monitor
  6. Observe that no Added event is triggered
  7. Disconnect the external monitor
  8. Observe that on Removed event is triggered

Expected behavior

I expected that if I connect an external monitor to the PC while the application was running an Added event would be triggered. I also expected that if I disconnected an external monitor from the PC while the application was running a Removed event would be triggered.

Screenshots

No response

NuGet package version

Windows App SDK 1.4.3: 1.4.231115000

Packaging type

Packaged (MSIX)

Windows version

Windows 11 version 22H2 (22621, 2022 Update)

IDE

Visual Studio 2022

Additional context

Note that I'm running Windows 11 Pro 23H2, but that is not an option in the Windows version selector above

castorix commented 9 months ago

if there is a better way to detect when monitors are connected and disconnected

I cannot test with an external monitor but old MSDN docs say that _WMDISPLAYCHANGE should be received (with SetWindowSubclass) : https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms695534(v=vs.85)?redirectedfrom=MSDN

ShortDevelopment commented 2 months ago

When the monitor-configuration changes EnterContextAndProcessDisplayAreaWatcherMessage gets called but fails to decode the handle of the watcher (Core::Util::DecodeHandle throws an exception). Therefore Windowing::DisplayAreaWatcher::OnDisplayChange is never called.

Exception

Exception thrown at 0x00007FFF681EF39C (KernelBase.dll) in ShortDev.Windows.Shell.exe: WinRT originate error - 0x80070006 : Invalid Handle.'.
Exception thrown at 0x00007FFF681EF39C in ShortDev.Windows.Shell.exe: Microsoft C++ exception: Core::ApiException::Holder$ at memory location 0x000000ADECB7DE48.

Callstack

    Microsoft.UI.Windowing.dll!System::Exception::Throw$(void)  Unknown
    Microsoft.UI.Windowing.dll!Core::Util::ValidateCondition(bool,enum Core::Win32Error,class System::String *) Unknown
    Microsoft.UI.Windowing.dll!Core::Util::DecodeHandle(enum Core::Handle,class System::Type *,enum Core::AllowMissing,enum Core::Win32Error)   Unknown
    Microsoft.UI.Windowing.dll!EnterContextAndProcessDisplayAreaWatcherMessage()    Unknown
    Microsoft.UI.Windowing.dll!Windowing::DisplayAreaWatcherFeatureProc(struct FEATURECALL *,struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
    Microsoft.UI.Windowing.Core.dll!Core::YieldAndCall::FeatureProc(enum Core::FunctionPointer,struct CFlat::Ref<struct Api::FeatureCallInfo>,enum Core::WindowHandle,enum Core::WindowMessage,enum Core::WParam,enum Core::LParam) Unknown
    Microsoft.UI.Windowing.Core.dll!Windowing::ExternalFeature::FeatureProc(class Windowing::Window *,enum Core::WindowMessage,enum Core::WParam,enum Core::LParam) Unknown
    Microsoft.UI.Windowing.Core.dll!Windowing::FeatureCallContext::CallNextHandler(enum Core::WParam,enum Core::LParam) Unknown
    Microsoft.UI.Windowing.Core.dll!Windowing::FeatureCallManager::CallFeatureChain(class Windowing::Window *,enum Core::WindowMessage,enum Core::WParam,enum Core::LParam) Unknown
    Microsoft.UI.Windowing.Core.dll!Windowing::Window::ProcessMessage(enum Core::WindowMessage,enum Core::WParam,enum Core::LParam) Unknown
    Microsoft.UI.Windowing.Core.dll!EnterContextAndProcessWindowMessage()   Unknown
    user32.dll!UserCallWinProcCheckWow()    Unknown