Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
80 changes: 71 additions & 9 deletions src/Controls/src/Core/TitleBar/TitleBar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,40 @@ public partial class TitleBar : TemplatedView, ITitleBar, ISafeAreaView
#if MACCATALYST
static int GetMacCatalystLeadingMargin() =>
OperatingSystem.IsMacCatalystVersionAtLeast(26) ? MacCatalystMarginLiquidGlass : MacCatalystMargin;

bool IsMacCatalystFullScreen()
{
if (OperatingSystem.IsMacCatalystVersionAtLeast(16)
&& Window?.Handler?.PlatformView is UIKit.UIWindow uiwindow)
{
return uiwindow.WindowScene?.FullScreen ?? false;
}

return false;
}

void ApplyMacCatalystMargin()
{
if (!_isDefaultControlTemplate)
{
return;
}

if (_templateRoot is not Grid contentGrid)
{
return;
}

if (IsMacCatalystFullScreen())
{
contentGrid.Margin = new Thickness(0);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[moderate] Native Defaults Preservation - ApplyMacCatalystMargin() now writes directly to the template root Grid.Margin, including resetting it to zero in fullscreen. For a custom TitleBar.ControlTemplate whose PART_Root is a Grid with its own margin, applying the template or resizing the window will overwrite the app's template-defined margin even though the template did not opt into the default TitleBar spacing behavior. Please preserve the existing template margin and apply/remove only the Mac traffic-light inset, or scope this mutation to the default template root.

return;
}

contentGrid.Margin = FlowDirection == FlowDirection.RightToLeft
? new Thickness(0, 0, GetMacCatalystLeadingMargin(), 0)
: new Thickness(GetMacCatalystLeadingMargin(), 0, 0, 0);
}
#endif

// Margin space (150px) required for Windows title bar system buttons
Expand Down Expand Up @@ -313,21 +347,40 @@ public Color ForegroundColor

static ControlTemplate? _defaultTemplate;
View? _templateRoot;
#if MACCATALYST
bool _isDefaultControlTemplate;
#endif

public TitleBar()
{
PassthroughElements = new List<IView>();
PropertyChanged += TitleBar_PropertyChanged;

#if MACCATALYST
Comment thread
devanathan-vaithiyanathan marked this conversation as resolved.
SizeChanged += OnSizeChanged;
#endif

if (ControlTemplate is null)
{
ControlTemplate = DefaultTemplate;
}
}

#if MACCATALYST
void OnSizeChanged(object? sender, EventArgs e)
{
ApplyMacCatalystMargin();
}
#endif

internal void Cleanup()
{
PropertyChanged -= TitleBar_PropertyChanged;

#if MACCATALYST
SizeChanged -= OnSizeChanged;
#endif

if (Window is not null)
{
Window.Activated -= Window_Activated;
Expand Down Expand Up @@ -358,6 +411,11 @@ void UpdateFlowDirectionState()
: TitleBarLTRState;

ApplyVisibleState(flowDirectionState);

#if MACCATALYST
ApplyMacCatalystMargin();
#endif

}

internal void ApplyVisibleState(string stateGroup)
Expand Down Expand Up @@ -391,6 +449,10 @@ protected override void OnApplyTemplate()

_templateRoot = controlTemplate?.TemplateRoot as View;

#if MACCATALYST
_isDefaultControlTemplate = ReferenceEquals(ControlTemplate, DefaultTemplate);
#endif

if (controlTemplate?.GetTemplateChild(TitleBarLeading) is IView leadingContent)
{
PassthroughElements.Add(leadingContent);
Expand Down Expand Up @@ -428,7 +490,7 @@ static View BuildDefaultTemplate()
var contentGrid = new Grid()
{
#if MACCATALYST
Margin = new Thickness(GetMacCatalystLeadingMargin(), 0, 0, 0),
Margin = new Thickness(0),
#endif
HorizontalOptions = LayoutOptions.Fill,
ColumnDefinitions =
Expand Down Expand Up @@ -630,30 +692,30 @@ static View BuildDefaultTemplate()

// Left-to-Right state (default)
var ltrState = new VisualState() { Name = TitleBarLTRState };

#if !MACCATALYST
ltrState.Setters.Add(new Setter()
{
Property = MarginProperty,
TargetName = TemplateRootName,
#if MACCATALYST
Value = new Thickness(GetMacCatalystLeadingMargin(), 0, 0, 0) // System buttons on left in macOS
#else
Value = new Thickness(0, 0, WindowsMargin, 0) // System buttons on right in Windows
#endif
});
#endif

flowDirectionGroup.States.Add(ltrState);

// Right-to-Left state
var rtlState = new VisualState() { Name = TitleBarRTLState };

#if !MACCATALYST
rtlState.Setters.Add(new Setter()
{
Property = MarginProperty,
TargetName = TemplateRootName,
#if MACCATALYST
Value = new Thickness(0, 0, GetMacCatalystLeadingMargin(), 0) // System buttons on right in macOS RTL
#else
Value = new Thickness(WindowsMargin, 0, 0, 0) // System buttons on left in Windows RTL
#endif
});
#endif

flowDirectionGroup.States.Add(rtlState);

visualStateGroups.Add(flowDirectionGroup);
Expand Down
56 changes: 56 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue30248.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
namespace Maui.Controls.Sample.Issues;

[Issue(IssueTracker.Github, 30248, "TitleBar, MacCatalyst - content is not aligned to left on fullscreen", PlatformAffected.macOS)]

public class Issue30248 : ContentPage
{
public Issue30248()
{
Title = "Issue 30248";

// Create TitleBar
var titleBar = new TitleBar
{
Title = "Maui App",
Subtitle = "Hello, World!",
ForegroundColor = Colors.Red,
HeightRequest = 48
};

titleBar.LeadingContent = new Image {Source = "dotnet_bot.png", HeightRequest = 24};

// Set the TitleBar on the current Window when this page appears
this.Loaded += (sender, e) =>
{
if (Window != null)
{
Window.TitleBar = titleBar;
}
};

// Create the page content with a Label
Content = new VerticalStackLayout
{
Spacing = 25,
Padding = new Thickness(30),
VerticalOptions = LayoutOptions.Center,
Children =
{
new Label
{
Text = "TitleBar should be aligned to the left in fullscreen mode",
AutomationId = "TitleBarAlignmentLabel",
FontSize = 32,
HorizontalOptions = LayoutOptions.Center
},
new Button
{
Text = "Empty Button",
AutomationId = "EmptyButton",
HorizontalOptions = LayoutOptions.Center
}
}
};
}
}

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#if MACCATALYST //This is the Mac Specific issue, so restricting other platforms
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue30248 : _IssuesUITest
{
public override string Issue => "TitleBar, MacCatalyst - content is not aligned to left on fullscreen";

public Issue30248(TestDevice device)
: base(device)
{ }

[Test]
[Category(UITestCategories.Window)]
public void VerifyTitleBarContentinFullScreenmode()
Comment thread
devanathan-vaithiyanathan marked this conversation as resolved.
{
App.WaitForElement("TitleBarAlignmentLabel");
try
{
App.EnterFullScreen();
App.WaitForElement("TitleBarAlignmentLabel");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] Regression Prevention and Test Coverage — This wait does not prove the app has entered fullscreen because TitleBarAlignmentLabel was already found before EnterFullScreen() on line 20. If the fullscreen command is slow or no-ops, the test proceeds to VerifyScreenshot(includeTitleBar: true) against a non-fullscreen window; the provided gate evidence shows exactly this reliability problem with a 1920x1080 baseline versus a 1280x800 actual capture even with the fix. Please wait for a fullscreen-specific condition or otherwise assert the window/screenshot state before verifying the snapshot.

App.Tap("EmptyButton");
VerifyScreenshot(includeTitleBar: true);
}
finally
{
App.ExitFullScreen();
}
}
Comment thread
devanathan-vaithiyanathan marked this conversation as resolved.
}
#endif
Loading