mgaffigan / WpfAppBar

AppBar implementation for WPF
MIT License
70 stars 10 forks source link

Multiple Monitors #2

Closed SurajitDas1991 closed 3 months ago

SurajitDas1991 commented 4 years ago

In case we have a second monitor attached , trying to move the app bar from Bottom to Right results in the app bar being moved further to the left from the right corner of the primary screen .

Note : The app bar is in the primary screen throughout

mgaffigan commented 3 years ago

@SurajitDas1991, I am not sure I understand the question. We use this with multiple monitors and do not have issues. Perhaps this is a mixed-DPI issue?

blakepell commented 3 years ago

I just observed the same behavior. It's when you go from bottom to right on a higher DPI monitor that is scaled up if you have other monitors that extend the desktop. If I just use a single high DPI monitor it all works fine.

Funny enough, if you go from top to right then right is positioned fine (but bottom to right, it ends up at the 2/3 mark of the screen. It's kind of wild, I stepped through it expecting to see different values going to SHAppBarMessage(ABM.SETPOS, ref abd) but I saw the same values going through when it positioned correctly and when it didn't so I need to do some more tracing.

blakepell commented 3 years ago

Here's an illustration with screen shots with the Left position binding displayed. You can see, when it goes from top to right, it says the Left position is 2360 and it is flush against the right side of the screen. If you go from Bottom to Right it STILL says the left is 2360 but you can see the position is somewhere farther left. I put traces everywhere and the structs all seem to have the right values, so IMO it's got to be something with the call to the API that's missing or something in the API.

image

image

Edit: Actually, on second look, 2360 is the location 2/3 of the way through the screen. It's a wrong value when the bar is correctly displayed.

blakepell commented 3 years ago

So the bug is somewhere in here it is related to having multiple monitors with different DPI's:

        private int WpfDimensionToDesktop(double dim)
        {
            var dpi = VisualTreeHelper.GetDpi(this);

            return (int)Math.Ceiling(dim * dpi.PixelsPerDip);
        }

        private double DesktopDimensionToWpf(double dim)
        {
            var dpi = VisualTreeHelper.GetDpi(this);

            return dim / dpi.PixelsPerDip;
        }

When it goes from Bottom->Right the DPI in the DesktopDimensionToWpf fluctuates from the high DPI monitor to the low DPI monitor (96). But, since the window is on the high DPI monitor (at least at the end) it calculates the wrong position. Why is it getting 96DPI? That I don't know, I do observe that while it's moving dock position the window does flash on the lower DPI monitor.

mgaffigan commented 3 months ago

Seems like this is related to https://github.com/dotnet/wpf/issues/3105. Short version is that the WPF API of setting a window position (Window.Left, Window.Top, ...) are not able to set position reliably with PerMonitorV2 since they cannot be all set at once.

I replaced the call with SetWindowPos in 2.2.1 and the issue is no longer reproducible.