Skip to content

Commit

Permalink
Merge pull request AvaloniaUI#10265 from AvaloniaUI/fixes/macos-nores…
Browse files Browse the repository at this point in the history
…ize-fullscreen

Various macOS and win32 fixes
  • Loading branch information
grokys committed Feb 16, 2023
1 parent ac49092 commit 8d0f449
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 82 deletions.
17 changes: 13 additions & 4 deletions native/Avalonia.Native/src/OSX/AvnWindow.mm
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,19 @@ - (void)windowWillClose:(NSNotification *_Nonnull)notification
}
}

// From chromium:
//
// > The delegate or the window class should implement this method so that
// > -[NSWindow isZoomed] can be then determined by whether or not the current
// > window frame is equal to the zoomed frame.
//
// If we don't implement this, then isZoomed always returns true for a non-
// resizable window ¯\_(ツ)_/¯
- (NSRect)windowWillUseStandardFrame:(NSWindow*)window
defaultFrame:(NSRect)newFrame {
return newFrame;
}

-(BOOL)canBecomeKeyWindow
{
if(_canBecomeKeyWindow)
Expand Down Expand Up @@ -260,10 +273,6 @@ -(bool)shouldTryToHandleEvents
-(void) setEnabled:(bool)enable
{
_isEnabled = enable;

[[self standardWindowButton:NSWindowCloseButton] setEnabled:enable];
[[self standardWindowButton:NSWindowMiniaturizeButton] setEnabled:enable];
[[self standardWindowButton:NSWindowZoomButton] setEnabled:enable];
}

-(void)becomeKeyWindow
Expand Down
2 changes: 1 addition & 1 deletion native/Avalonia.Native/src/OSX/PopupImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
[Window setLevel:NSPopUpMenuWindowLevel];
}
protected:
virtual NSWindowStyleMask GetStyle() override
virtual NSWindowStyleMask CalculateStyleMask() override
{
return NSWindowStyleMaskBorderless;
}
Expand Down
5 changes: 2 additions & 3 deletions native/Avalonia.Native/src/OSX/WindowBaseImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,8 @@ BEGIN_INTERFACE_MAP()
virtual void BringToFront ();

protected:
virtual NSWindowStyleMask GetStyle();

void UpdateStyle();
virtual NSWindowStyleMask CalculateStyleMask() = 0;
virtual void UpdateStyle();

private:
void CreateNSWindow (bool isDialog);
Expand Down
29 changes: 6 additions & 23 deletions native/Avalonia.Native/src/OSX/WindowBaseImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,14 @@
lastSize = NSSize { 100, 100 };
lastMaxSize = NSSize { CGFLOAT_MAX, CGFLOAT_MAX};
lastMinSize = NSSize { 0, 0 };

lastMenu = nullptr;

CreateNSWindow(usePanel);

[Window setContentView:StandardContainer];
[Window setStyleMask:NSWindowStyleMaskBorderless];
[Window setBackingType:NSBackingStoreBuffered];

[Window setContentMinSize:lastMinSize];
[Window setContentMaxSize:lastMaxSize];

[Window setOpaque:false];
}

Expand Down Expand Up @@ -545,12 +541,8 @@
return false;
}

NSWindowStyleMask WindowBaseImpl::GetStyle() {
return NSWindowStyleMaskBorderless;
}

void WindowBaseImpl::UpdateStyle() {
[Window setStyleMask:GetStyle()];
[Window setStyleMask:CalculateStyleMask()];
}

void WindowBaseImpl::CleanNSWindow() {
Expand All @@ -561,21 +553,12 @@
}
}

void WindowBaseImpl::CreateNSWindow(bool isDialog) {
if (isDialog) {
if (![Window isKindOfClass:[AvnPanel class]]) {
CleanNSWindow();

Window = [[AvnPanel alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()];

[Window setHidesOnDeactivate:false];
}
void WindowBaseImpl::CreateNSWindow(bool usePanel) {
if (usePanel) {
Window = [[AvnPanel alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:NSWindowStyleMaskBorderless];
[Window setHidesOnDeactivate:false];
} else {
if (![Window isKindOfClass:[AvnWindow class]]) {
CleanNSWindow();

Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()];
}
Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:NSWindowStyleMaskBorderless];
}
}

Expand Down
6 changes: 3 additions & 3 deletions native/Avalonia.Native/src/OSX/WindowImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ BEGIN_INTERFACE_MAP()

WindowImpl(IAvnWindowEvents* events, IAvnGlContext* gl);

void HideOrShowTrafficLights ();

virtual HRESULT Show (bool activate, bool isDialog) override;

virtual HRESULT SetEnabled (bool enable) override;
Expand Down Expand Up @@ -100,9 +98,11 @@ BEGIN_INTERFACE_MAP()
bool CanBecomeKeyWindow ();

protected:
virtual NSWindowStyleMask GetStyle() override;
virtual NSWindowStyleMask CalculateStyleMask() override;
void UpdateStyle () override;

private:
void ZOrderChildWindows();
void OnInitialiseNSWindow();
NSString *_lastTitle;
};
Expand Down
101 changes: 54 additions & 47 deletions native/Avalonia.Native/src/OSX/WindowImpl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,6 @@
OnInitialiseNSWindow();
}

void WindowImpl::HideOrShowTrafficLights() {
if (Window == nil) {
return;
}

bool wantsChrome = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
bool hasTrafficLights = _isClientAreaExtended ? wantsChrome : _decorations == SystemDecorationsFull;

[[Window standardWindowButton:NSWindowCloseButton] setHidden:!hasTrafficLights];
[[Window standardWindowButton:NSWindowMiniaturizeButton] setHidden:!hasTrafficLights];
[[Window standardWindowButton:NSWindowZoomButton] setHidden:!hasTrafficLights];
}

void WindowImpl::OnInitialiseNSWindow(){
[GetWindowProtocol() setCanBecomeKeyWindow:true];

Expand All @@ -66,8 +53,6 @@

WindowBaseImpl::Show(activate, isDialog);
GetWindowState(&_actualWindowState);
HideOrShowTrafficLights();

return SetWindowState(_lastWindowState);
}
}
Expand Down Expand Up @@ -133,14 +118,19 @@
}

[Window invalidateShadow];
ZOrderChildWindows();
}
}

void WindowImpl::ZOrderChildWindows()
{
for(auto iterator = _children.begin(); iterator != _children.end(); iterator++)
{
auto window = (*iterator)->Window;

for(auto iterator = _children.begin(); iterator != _children.end(); iterator++)
{
auto window = (*iterator)->Window;

// #9565: Only bring window to front if it's on the currently active space
if ([window isOnActiveSpace])
(*iterator)->BringToFront();
// #9565: Only bring window to front if it's on the currently active space
if ([window isOnActiveSpace]) {
(*iterator)->BringToFront();
}
}
}
Expand All @@ -160,13 +150,15 @@

void WindowImpl::StartStateTransition() {
_transitioningWindowState = true;
UpdateStyle();
}

void WindowImpl::EndStateTransition() {
_transitioningWindowState = false;

UpdateStyle();

// Ensure correct order of child windows after fullscreen transition.
BringToFront();
ZOrderChildWindows();
}

SystemDecorations WindowImpl::Decorations() {
Expand Down Expand Up @@ -224,16 +216,12 @@
}

void WindowImpl::DoZoom() {
switch (_decorations) {
case SystemDecorationsNone:
case SystemDecorationsBorderOnly:
[Window setFrame:[Window screen].visibleFrame display:true];
break;


case SystemDecorationsFull:
[Window performZoom:Window];
break;
if (_decorations == SystemDecorationsNone ||
_decorations == SystemDecorationsBorderOnly ||
_canResize == false) {
[Window setFrame:[Window screen].visibleFrame display:true];
} else {
[Window performZoom:Window];
}
}

Expand All @@ -260,8 +248,6 @@

UpdateStyle();

HideOrShowTrafficLights();

switch (_decorations) {
case SystemDecorationsNone:
[Window setHasShadow:NO];
Expand Down Expand Up @@ -418,9 +404,6 @@
}

[GetWindowProtocol() setIsExtended:enable];

HideOrShowTrafficLights();

UpdateStyle();
}

Expand Down Expand Up @@ -576,14 +559,16 @@
return _parent != nullptr;
}

NSWindowStyleMask WindowImpl::GetStyle() {
unsigned long s = NSWindowStyleMaskBorderless;
NSWindowStyleMask WindowImpl::CalculateStyleMask() {
// Use the current style mask and only clear the flags we're going to be modifying.
unsigned long s = [Window styleMask] &
~(NSWindowStyleMaskFullSizeContentView |
NSWindowStyleMaskTitled |
NSWindowStyleMaskClosable |
NSWindowStyleMaskResizable |
NSWindowStyleMaskMiniaturizable |
NSWindowStyleMaskTexturedBackground);

if(_actualWindowState == FullScreen)
{
s |= NSWindowStyleMaskFullScreen;
}

switch (_decorations) {
case SystemDecorationsNone:
s = s | NSWindowStyleMaskFullSizeContentView;
Expand All @@ -596,7 +581,7 @@
case SystemDecorationsFull:
s = s | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable;

if (_canResize && _isEnabled) {
if ((_canResize && _isEnabled) || _transitioningWindowState) {
s = s | NSWindowStyleMaskResizable;
}
break;
Expand All @@ -611,3 +596,25 @@
}
return s;
}

void WindowImpl::UpdateStyle() {
WindowBaseImpl::UpdateStyle();

if (Window == nil) {
return;
}

bool wantsChrome = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
bool hasTrafficLights = _isClientAreaExtended ? wantsChrome : _decorations == SystemDecorationsFull;

NSButton* closeButton = [Window standardWindowButton:NSWindowCloseButton];
NSButton* miniaturizeButton = [Window standardWindowButton:NSWindowMiniaturizeButton];
NSButton* zoomButton = [Window standardWindowButton:NSWindowZoomButton];

[closeButton setHidden:!hasTrafficLights];
[closeButton setEnabled:_isEnabled];
[miniaturizeButton setHidden:!hasTrafficLights];
[miniaturizeButton setEnabled:_isEnabled];
[zoomButton setHidden:!hasTrafficLights];
[zoomButton setEnabled:_isEnabled && _canResize];
}
1 change: 1 addition & 0 deletions samples/IntegrationTestApp/MainWindow.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
<ComboBoxItem Name="ShowWindowStateMaximized">Maximized</ComboBoxItem>
<ComboBoxItem Name="ShowWindowStateFullScreen">FullScreen</ComboBoxItem>
</ComboBox>
<CheckBox Name="ShowWindowCanResize" IsChecked="True">Can Resize</CheckBox>
<Button Name="ShowWindow">Show Window</Button>
<Button Name="SendToBack">Send to Back</Button>
<Button Name="EnterFullscreen">Enter Fullscreen</Button>
Expand Down
2 changes: 2 additions & 0 deletions samples/IntegrationTestApp/MainWindow.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ private void ShowWindow()
var locationComboBox = this.GetControl<ComboBox>("ShowWindowLocation");
var stateComboBox = this.GetControl<ComboBox>("ShowWindowState");
var size = !string.IsNullOrWhiteSpace(sizeTextBox.Text) ? Size.Parse(sizeTextBox.Text) : (Size?)null;
var canResizeCheckBox = this.GetControl<CheckBox>("ShowWindowCanResize");
var owner = (Window)this.GetVisualRoot()!;

var window = new ShowWindowTest
{
WindowStartupLocation = (WindowStartupLocation)locationComboBox.SelectedIndex,
CanResize = canResizeCheckBox.IsChecked.Value,
};

if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime)
Expand Down
15 changes: 14 additions & 1 deletion src/Windows/Avalonia.Win32/WindowImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1089,8 +1089,21 @@ private void MaximizeWithoutCoveringTaskbar()
var y = monitorInfo.rcWork.top;
var cx = Math.Abs(monitorInfo.rcWork.right - x);
var cy = Math.Abs(monitorInfo.rcWork.bottom - y);
var style = (WindowStyles)GetWindowLong(_hwnd, (int)WindowLongParam.GWL_STYLE);

SetWindowPos(_hwnd, WindowPosZOrder.HWND_NOTOPMOST, x, y, cx, cy, SetWindowPosFlags.SWP_SHOWWINDOW);
if (!style.HasFlag(WindowStyles.WS_SIZEFRAME))
{
// When calling SetWindowPos on a maximized window it automatically adjusts
// for "hidden" borders which are placed offscreen, EVEN IF THE WINDOW HAS
// NO BORDERS, meaning that the window is placed wrong when we have CanResize
// == false. Account for this here.
var borderThickness = BorderThickness;
x -= (int)borderThickness.Left;
cx += (int)borderThickness.Left + (int)borderThickness.Right;
cy += (int)borderThickness.Bottom;
}

SetWindowPos(_hwnd, WindowPosZOrder.HWND_NOTOPMOST, x, y, cx, cy, SetWindowPosFlags.SWP_SHOWWINDOW | SetWindowPosFlags.SWP_FRAMECHANGED);
}
}
}
Expand Down

0 comments on commit 8d0f449

Please sign in to comment.