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

Fix windows multi window crash on Full Screen #2256

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4598670
Improve layout and fullscreen handling for MediaElement
ne0rrmatrix Oct 5, 2024
ed6f535
Merge branch 'CommunityToolkit:main' into FixWindowsMultiWindow
ne0rrmatrix Oct 5, 2024
9c87af8
Enable unsafe code, use partial classes, update imports
ne0rrmatrix Oct 5, 2024
3639064
Removed Grid as layouts should only be used if multiple visual elemen…
ne0rrmatrix Oct 15, 2024
851f2af
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Oct 15, 2024
a412a98
Merge branch 'FixWindowsMultiWindow' of https://github.com/ne0rrmatri…
ne0rrmatrix Oct 15, 2024
3425d3a
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Oct 15, 2024
9a61cb7
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Oct 16, 2024
479d2e9
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Oct 20, 2024
6b3371c
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Oct 31, 2024
5a3e171
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Nov 5, 2024
372ce36
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Nov 7, 2024
3ed8820
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Nov 11, 2024
3c02129
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Nov 11, 2024
375254f
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Dec 2, 2024
d8f44da
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Dec 12, 2024
2f9b058
Merge branch 'main' into FixWindowsMultiWindow
brminnick Dec 18, 2024
a403510
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Dec 19, 2024
f3e753d
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Dec 20, 2024
01bc20e
Revert changes to sample pages
ne0rrmatrix Dec 20, 2024
c20d2e5
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Dec 28, 2024
633f420
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Jan 3, 2025
113be81
Merge branch 'main' into FixWindowsMultiWindow
ne0rrmatrix Jan 14, 2025
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 @@ -7,6 +7,7 @@
<SingleProject>true</SingleProject>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsAotCompatible>true</IsAotCompatible>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>

<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ internal static Page GetCurrentPage(this Page currentPage)

internal record struct ParentWindow
{
static Page CurrentPage => GetCurrentPage(Application.Current?.Windows[0].Page ?? throw new InvalidOperationException($"{nameof(Page)} cannot be null."));
static Page CurrentPage => GetCurrentPage(Application.Current?.Windows[^1].Page ?? throw new InvalidOperationException($"{nameof(Page)} cannot be null."));
/// <summary>
/// Checks if the parent window is null.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Runtime.InteropServices;
using CommunityToolkit.Maui.Extensions;
using CommunityToolkit.Maui.Views;
using Microsoft.UI;
Expand All @@ -7,7 +8,6 @@
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Media;
using WinRT.Interop;
using Application = Microsoft.Maui.Controls.Application;
using Button = Microsoft.UI.Xaml.Controls.Button;
using Colors = Microsoft.UI.Colors;
Expand All @@ -23,7 +23,9 @@ namespace CommunityToolkit.Maui.Core.Views;
/// </summary>
public partial class MauiMediaElement : Grid, IDisposable
{
static readonly AppWindow appWindow = GetAppWindowForCurrentWindow();
[LibraryImport("user32.dll")]
internal static partial IntPtr GetForegroundWindow();

readonly Popup popup = new();
readonly Grid fullScreenGrid = new();
readonly Grid buttonContainer;
Expand Down Expand Up @@ -64,8 +66,9 @@ public MauiMediaElement(MediaPlayerElement mediaPlayerElement)
fullScreenButton.Click += OnFullScreenButtonClick;
buttonContainer.Children.Add(fullScreenButton);

Children.Add(this.mediaPlayerElement);
Children.Add(buttonContainer);
fullScreenGrid.Children.Add(this.mediaPlayerElement);
fullScreenGrid.Children.Add(buttonContainer);
Children.Add(fullScreenGrid);

mediaPlayerElement.PointerMoved += OnMediaPlayerElementPointerMoved;
}
Expand All @@ -88,7 +91,7 @@ public void Dispose()
/// Gets the presented page.
/// </summary>
protected static Page CurrentPage =>
PageExtensions.GetCurrentPage(Application.Current?.Windows[0].Page ?? throw new InvalidOperationException($"{nameof(Page)} cannot be null."));
PageExtensions.GetCurrentPage(Application.Current?.Windows[^1]?.Page ?? throw new InvalidOperationException($"{nameof(Page)} cannot be null."));

/// <summary>
/// Releases the managed and unmanaged resources used by the <see cref="MauiMediaElement"/>.
Expand All @@ -111,26 +114,18 @@ protected virtual void Dispose(bool disposing)
isDisposed = true;
}

static AppWindow GetAppWindowForCurrentWindow()
static AppWindow GetAppWindowForWindowHandle(IntPtr hwnd)
{
// let's cache the CurrentPage here, since the user can navigate or background the app
// while this method is running
var currentPage = CurrentPage;

if (currentPage?.GetParentWindow().Handler.PlatformView is not MauiWinUIWindow window)
{
throw new InvalidOperationException($"{nameof(window)} cannot be null.");
}

var handle = WindowNative.GetWindowHandle(window);
var id = Win32Interop.GetWindowIdFromWindow(handle);

return AppWindow.GetFromWindowId(id);
var windowId = Win32Interop.GetWindowIdFromWindow(hwnd);
return AppWindow.GetFromWindowId(windowId);
}

async void OnMediaPlayerElementPointerMoved(object sender, PointerRoutedEventArgs e)
{
e.Handled = true;
if(buttonContainer is null)
{
return;
}
buttonContainer.Visibility = mediaPlayerElement.TransportControls.Visibility;

if (mediaPlayerElement.TransportControls.Visibility == Microsoft.UI.Xaml.Visibility.Collapsed)
Expand All @@ -150,53 +145,57 @@ async void OnMediaPlayerElementPointerMoved(object sender, PointerRoutedEventArg
void OnFullScreenButtonClick(object sender, RoutedEventArgs e)
{
var currentPage = CurrentPage;

var windowHandle = GetForegroundWindow();
var appWindow = GetAppWindowForWindowHandle(windowHandle);
if (appWindow.Presenter.Kind is AppWindowPresenterKind.FullScreen)
{
appWindow.SetPresenter(AppWindowPresenterKind.Default);
Shell.SetNavBarIsVisible(CurrentPage, doesNavigationBarExistBeforeFullScreen);

if (popup.IsOpen)
{
popup.IsOpen = false;
popup.Child = null;
fullScreenGrid.Children.Clear();
}
fullScreenButton.Content = fullScreenIcon;
Children.Add(mediaPlayerElement);
Children.Add(buttonContainer);

var parent = mediaPlayerElement.Parent as FrameworkElement;
mediaPlayerElement.Width = parent?.Width ?? mediaPlayerElement.Width;
mediaPlayerElement.Height = parent?.Height ?? mediaPlayerElement.Height;
SetDefaultScreen(appWindow, currentPage);
}
else
{
appWindow.SetPresenter(AppWindowPresenterKind.FullScreen);
doesNavigationBarExistBeforeFullScreen = Shell.GetNavBarIsVisible(currentPage);
Shell.SetNavBarIsVisible(CurrentPage, false);

var displayInfo = DeviceDisplay.Current.MainDisplayInfo;
mediaPlayerElement.Width = displayInfo.Width / displayInfo.Density;
mediaPlayerElement.Height = displayInfo.Height / displayInfo.Density;

Children.Clear();
fullScreenButton.Content = exitFullScreenIcon;
fullScreenGrid.Children.Add(mediaPlayerElement);
fullScreenGrid.Children.Add(buttonContainer);

popup.XamlRoot = mediaPlayerElement.XamlRoot;
popup.HorizontalOffset = 0;
popup.VerticalOffset = 0;
popup.ShouldConstrainToRootBounds = false;
popup.VerticalAlignment = Microsoft.UI.Xaml.VerticalAlignment.Center;
popup.HorizontalAlignment = Microsoft.UI.Xaml.HorizontalAlignment.Center;
popup.Child = fullScreenGrid;

if (!popup.IsOpen)
{
popup.IsOpen = true;
}
SetFullScreen(appWindow, currentPage);
}
}

void SetFullScreen(AppWindow appWindow, Page currentPage)
{
if (popup.IsOpen)
{
return;
}

doesNavigationBarExistBeforeFullScreen = Shell.GetNavBarIsVisible(currentPage);
Shell.SetNavBarIsVisible(currentPage, false);

Children.Remove(fullScreenGrid);
fullScreenButton.Content = exitFullScreenIcon;

var displayInfo = DeviceDisplay.Current.MainDisplayInfo;
mediaPlayerElement.Height = displayInfo.Height / displayInfo.Density;

appWindow.SetPresenter(AppWindowPresenterKind.FullScreen);
popup.XamlRoot = XamlRoot;
popup.ShouldConstrainToRootBounds = true;
popup.Child = fullScreenGrid;
popup.IsOpen = true;
}

void SetDefaultScreen(AppWindow appWindow, Page currentPage)
{
if(!popup.IsOpen)
{
return;
}

popup.IsOpen = false;
popup.Child = null;

appWindow.SetPresenter(AppWindowPresenterKind.Default);
Shell.SetNavBarIsVisible(currentPage, doesNavigationBarExistBeforeFullScreen);

fullScreenButton.Content = fullScreenIcon;
Children.Add(fullScreenGrid);
mediaPlayerElement.Height = double.NaN;

}
}
Loading