Avalonia icon indicating copy to clipboard operation
Avalonia copied to clipboard

Drag/Dropping Window to Maximized Cuts Taskbar (BorderOnly Deco)

Open ArchLeaders opened this issue 1 year ago • 6 comments

Discussed in https://github.com/AvaloniaUI/Avalonia/discussions/11222

Originally posted by ArchLeaders May 3, 2023 I'm setting up a custom window chrome for my application, but I'm getting some weird behavior with the drag/drop to fullscreen action in Windows 10.

Setting WindowState to WindowState.Maximized works just fine, but when I drag the window to the top of the screen and drop it cuts out the task bar and about 7 pixels off the side of the window.

https://user-images.githubusercontent.com/80713508/236018412-8c7b7983-62ab-4fbd-b272-6aa63c661e9d.mp4

Is there a way to intercept this behavior and call whatever Avalonia does to fullscreen to the correct bounds instead? Or just another way to fix this?

  • Avalonia Version: 11.0.0-preview6 and 11.0.0-r1.1
  • OS: Windows 10

ArchLeaders avatar Jun 07 '23 07:06 ArchLeaders

I should also mention that the other window decoration properties did not work in my case, the main issue being the window drop shadow. The only solution I could find that would remove the system chrome while retaining the shadow (border), was using BorderOnly with a custom resize border and drag region.

ArchLeaders avatar Jun 07 '23 07:06 ArchLeaders

Window has a property called OffScreenMargin. Can you try to apply this to your inner Content?

<Window xmlns="https://github.com/avaloniaui"
        ... other namespaces etc ... >
   <Grid Margin="{Binding $parent[Window].OffScreenMargin}">
     ... Content ...
   </Grid>
</Window>

timunie avatar Jun 07 '23 08:06 timunie

Window has a property called OffScreenMargin. Can you try to apply this to your inner Content?

<Window xmlns="https://github.com/avaloniaui"
        ... other namespaces etc ... >
   <Grid Margin="{Binding $parent[Window].OffScreenMargin}">
     ... Content ...
   </Grid>
</Window>

No luck with that sadly, still cuts the border when drop/dropping to fullscreen (same effect as before)

image

ArchLeaders avatar Jun 08 '23 00:06 ArchLeaders

Apparently my bug report got deleted? It was when it's maximized and no chrome it gets cut by 8 pixels or so in a maximized state.

cyraid avatar Jun 14 '23 20:06 cyraid

I experience the same issue. I think you are right for the pixels. It should be 8px which is the padding applied to the Window when it's maximized.

It's as if this way of maximizing resizes the Window without padding and then internally changes state to maximized.

rprimora-pricer avatar Jun 21 '23 15:06 rprimora-pricer

Margin="{Binding $parent[Window].OffScreenMargin} ,This one really works, thank you!!

ApaulMyLittleAirport avatar Jul 09 '23 03:07 ApaulMyLittleAirport

I have looked closer at the issue today and managed to get a working code.

In your constructor add the following code block:

this.GetPropertyChangedObservable(WindowStateProperty).AddClassHandler<Visual>((t, args) =>
{
    /// I am doing this only for Windows.
    if (OperatingSystem.IsWindows())
    {
        /// If the state is maximised we will enter our code block.
        if (args.GetNewValue<WindowState>() == WindowState.Maximized)
        {
            /// Get the screen from the window.
            var screen = Screens.ScreenFromWindow(this);
            /// This is the part where we check if the actual height is more than the working area cos that would
            /// mean the window has gone over the taskbar.
            if (screen.WorkingArea.Height < ClientSize.Height)
            {
                /// We set the client size of our window to be exactly the size of our working area.
                ClientSize = screen.WorkingArea.Size.ToSize(screen.Scaling);
                /// This is the last piece of the puzzle. If we maximize the Window by setting the state
                /// then this position will be correct. But, if the state is set as a result of dragging the window
                /// to the top then the position will most likely be less then 0 ( it will be (-7,-7) in our case).
                if (Position.X < 0 || Position.Y < 0)
                    Position = screen.WorkingArea.Position; // <-- This is needed because you might have your taskbar in a different position (Left | Right | Top | Bottom).
            }
        }
    }
});

I really hope Avalonia solves this issue.

rprimora-pricer avatar Sep 22 '23 08:09 rprimora-pricer

I have looked closer at the issue today and managed to get a working code.

In your constructor add the following code block:

this.GetPropertyChangedObservable(WindowStateProperty).AddClassHandler<Visual>((t, args) =>
{
    /// I am doing this only for Windows.
    if (OperatingSystem.IsWindows())
    {
        /// If the state is maximised we will enter our code block.
        if (args.GetNewValue<WindowState>() == WindowState.Maximized)
        {
            /// Get the screen from the window.
            var screen = Screens.ScreenFromWindow(this);
            /// This is the part where we check if the actual height is more than the working area cos that would
            /// mean the window has gone over the taskbar.
            if (screen.WorkingArea.Height < ClientSize.Height)
            {
                /// We set the client size of our window to be exactly the size of our working area.
                ClientSize = screen.WorkingArea.Size.ToSize(screen.Scaling);
                /// This is the last piece of the puzzle. If we maximize the Window by setting the state
                /// then this position will be correct. But, if the state is set as a result of dragging the window
                /// to the top then the position will most likely be less then 0 ( it will be (-7,-7) in our case).
                if (Position.X < 0 || Position.Y < 0)
                    Position = screen.WorkingArea.Position; // <-- This is needed because you might have your taskbar in a different position (Left | Right | Top | Bottom).
            }
        }
    }
});

I really hope Avalonia solves this issue.

Hey, thanks for this! I just tested it and it almost works perfectly.

One thing I noticed; when you check the height it should be multiplied by the screen scale. It didn't work on a 4K monitor because the check failed.

if (screen.WorkingArea.Height < ClientSize.Height * screen.Scaling) {
  // . . .
}

Visual it looks fine, but it seems to restrict actually using the taskbar. I'll mess around with it and see if I can fix that issue.

Thanks again for the research on this!

ArchLeaders avatar Oct 04 '23 18:10 ArchLeaders

Visual it looks fine, but it seems to restrict actually using the taskbar. I'll mess around with it and see if I can fix that issue.

The taskbar seems to work fine if the window position is anything greater than 0, 0. I.e. if the taskbar is not docked to the bottom, or the position is hardcoded to 0, 1 or something.

I don't know enough about how windows work to say why this happens, but maybe it will be insightful to someone else.

ArchLeaders avatar Oct 04 '23 18:10 ArchLeaders

@ArchLeaders good catch on scaling. I'll check it out.

I am not sure about the usage of taskbar. What do you mean by this?

rprimora-pricer avatar Oct 05 '23 05:10 rprimora-pricer

I am not sure about the usage of taskbar. What do you mean by this?

Might be a condition of my setup, but when the window position (this.Position) is set to PixelPoint(0, 0) I can't click on the taskbar (as if there is a clear panel covering it). There is also a small 1px-wide white line lining the left side of the taskbar:

image

*Edit*

For some reason I thought it worked if I set SystemDecorations="None", but it doesn't. Only the white line disappears.

ArchLeaders avatar Oct 05 '23 18:10 ArchLeaders

@ArchLeaders how does latest nightly look for you?

Also probably check what FluentAvalonia does to get AppWindow working on Windows. They did a heavy lifting to get it somewhat work.

timunie avatar Oct 05 '23 18:10 timunie

@ArchLeaders how does latest nightly look for you?

~~Can't seem to connect to https://nuget-feed-nightly.avaloniaui.net/api/download/symbols.~~

*Edit*

Nevermind, just needed to deleted and re-add the source instead of updating.

ArchLeaders avatar Oct 05 '23 19:10 ArchLeaders

Latest nightly has the same issue as >11.0.1, there's a weird white border around the window and sizing isn't applied.

image

With this hack, sizing is weirdly off when dragging to fullscreen.

image

Clicking the maximize button (with and without the hack) results in it having about 7-8px of padding on the inside of the border.

image

Dragging to fullscreen without the hack seals it to the edge of the screen (without the 7-8px cutoff that it had previously)

(My other monitor is in the screenshot as a reference to the taskbar)

image

ArchLeaders avatar Oct 05 '23 19:10 ArchLeaders

is there any minimal sample I can check on my computer?

timunie avatar Oct 05 '23 19:10 timunie

Not currently, but I can put one together pretty quick.

ArchLeaders avatar Oct 06 '23 02:10 ArchLeaders

@timunie I created a minimal reproduction using the latest nightly, hope this helps:

https://github.com/ArchLeaders/AvaloniaBorderOnlyWindow

Thanks for looking into this :D

ArchLeaders avatar Oct 06 '23 18:10 ArchLeaders

Latest nightly has the same issue as >11.0.1, there's a weird white border around the window and sizing isn't applied.

image

If you are refering to the white border on top part of the Window, isn't this the ExtendClientAreaTitleBarHeightHint set to something above 0?

rprimora-pricer avatar Oct 09 '23 06:10 rprimora-pricer

If zou are refering to the white border on top part of the Window, isn't this the ExtendClientAreaTitleBarHeightHint set to something above 0?

Yes I am refering to that, I don't think that's the case though. Setting it to 0 has the same effect.

image

ArchLeaders avatar Oct 09 '23 07:10 ArchLeaders

@ArchLeaders Can you try and set it to -1?

rprimora-pricer avatar Oct 09 '23 07:10 rprimora-pricer

<Window x:Class="AvaloniaBorderOnlyWindow.ShellView"
        xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="ShellView"
        Width="400"
        Height="400"
        d:DesignHeight="450"
        d:DesignWidth="800"
+       ExtendClientAreaChromeHints="SystemChrome"
+       ExtendClientAreaToDecorationsHint="True"
        SystemDecorations="BorderOnly"
        mc:Ignorable="d">

That works for me at least

timunie avatar Oct 09 '23 07:10 timunie

@ArchLeaders Can you try and set it to -1?

@rprimora-pricer Same effect with ExtendClientAreaTitleBarHeightHint="-1".

ArchLeaders avatar Oct 09 '23 07:10 ArchLeaders

<Window x:Class="AvaloniaBorderOnlyWindow.ShellView"
        xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        Title="ShellView"
        Width="400"
        Height="400"
        d:DesignHeight="450"
        d:DesignWidth="800"
+       ExtendClientAreaChromeHints="SystemChrome"
+       ExtendClientAreaToDecorationsHint="True"
        SystemDecorations="BorderOnly"
        mc:Ignorable="d">

That works for me at least

Oh yeah that does work. I wonder why I never tried that before.

ArchLeaders avatar Oct 09 '23 07:10 ArchLeaders

Still has an issue with resizing, but at least BorderOnly works.

ArchLeaders avatar Oct 09 '23 07:10 ArchLeaders

What issues you have with resizing?

rprimora-pricer avatar Oct 09 '23 07:10 rprimora-pricer

Same as here: https://github.com/AvaloniaUI/Avalonia/issues/11685#issuecomment-1747436905

(Taskbar is not clickable when dragging to fullscreen)

ArchLeaders avatar Oct 09 '23 07:10 ArchLeaders

then please update your minimal sample to reproduce the mentioned issue.

timunie avatar Oct 09 '23 07:10 timunie

Changes should be synced on github.

Now the main button changes the window state from the code behind (which works as expected)

But dragging with window to the fullscreen (or Win + ArrowUp) disallows the use of the taskbar.

ArchLeaders avatar Oct 09 '23 07:10 ArchLeaders

Same as here: #11685 (comment)

(Taskbar is not clickable when dragging to fullscreen)

Oh, I just saw what you meant by it. The hack does indeed fix the sizing but for some reason the Taskbar is not functioning. It is curious behavior.

Feels like a fullscreen gone wrong. I say this because normally in Windows to go fullscreen all you have to do is maximize the screen and set its bounds to be the same as the screen size. Windows will then hide the taskbar automatically. In our case, without the hack, when you drag a window for maximize same will happen.

rprimora-pricer avatar Oct 10 '23 06:10 rprimora-pricer

can't reproduce using Windows 11 and your Button, but see the issue using [Win]+[Arrow Up]. Strange issue.

timunie avatar Oct 10 '23 10:10 timunie