-
Notifications
You must be signed in to change notification settings - Fork 745
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #18793 from unoplatform/dev/spouliot/macos-desktop…
…-native-embedding feat(macOS): add native elements support for macOS/Skia
- Loading branch information
Showing
11 changed files
with
514 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
157 changes: 157 additions & 0 deletions
157
src/Uno.UI.Runtime.Skia.MacOS/MacOSNativeElementHostingExtension.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
#nullable enable | ||
|
||
using Windows.Foundation; | ||
using Windows.UI.Core; | ||
using Microsoft.UI.Xaml.Controls; | ||
|
||
using Uno.Foundation.Extensibility; | ||
using Uno.Foundation.Logging; | ||
|
||
namespace Uno.UI.Runtime.Skia.MacOS; | ||
|
||
internal class MacOSNativeElement : Microsoft.UI.Xaml.FrameworkElement | ||
{ | ||
public nint NativeHandle { get; internal set; } | ||
|
||
internal bool Detached { get; set; } | ||
} | ||
|
||
internal class MacOSNativeElementHostingExtension : ContentPresenter.INativeElementHostingExtension | ||
{ | ||
private readonly ContentPresenter _presenter; | ||
private readonly MacOSWindowNative? _window; | ||
|
||
private MacOSNativeElementHostingExtension(ContentPresenter contentPresenter) | ||
{ | ||
_presenter = contentPresenter; | ||
_window = _presenter.XamlRoot?.HostWindow?.NativeWindow as MacOSWindowNative; | ||
} | ||
|
||
public static void Register() => ApiExtensibility.Register<ContentPresenter>(typeof(ContentPresenter.INativeElementHostingExtension), o => new MacOSNativeElementHostingExtension(o)); | ||
|
||
public void ArrangeNativeElement(object content, Rect arrangeRect, Rect clipRect) | ||
{ | ||
if (content is MacOSNativeElement element) | ||
{ | ||
if (element.Detached) | ||
{ | ||
this.Log().Debug($"Cannot arrange element `{nameof(content)}` of type {content.GetType().FullName} since it was detached."); | ||
} | ||
else | ||
{ | ||
NativeUno.uno_native_arrange(element.NativeHandle, arrangeRect.Left, arrangeRect.Top, arrangeRect.Width, arrangeRect.Height, clipRect.Left, clipRect.Top, clipRect.Width, clipRect.Height); | ||
} | ||
} | ||
else if (this.Log().IsEnabled(LogLevel.Debug)) | ||
{ | ||
this.Log().Debug($"Object `{nameof(content)}` is a {content.GetType().FullName} and not a MacOSNativeElement subclass."); | ||
} | ||
} | ||
|
||
public void AttachNativeElement(object content) | ||
{ | ||
if (content is MacOSNativeElement element) | ||
{ | ||
NativeUno.uno_native_attach(element.NativeHandle); | ||
} | ||
else if (this.Log().IsEnabled(LogLevel.Debug)) | ||
{ | ||
this.Log().Debug($"Object `{nameof(content)}` is a {content.GetType().FullName} and not a MacOSNativeElement subclass."); | ||
} | ||
} | ||
|
||
public void ChangeNativeElementOpacity(object content, double opacity) | ||
{ | ||
if (content is MacOSNativeElement element) | ||
{ | ||
// https://developer.apple.com/documentation/appkit/nsview/1483560-alphavalue?language=objc | ||
// note: no marshaling needed as CGFloat is double for 64bits apps | ||
NativeUno.uno_native_set_opacity(element.NativeHandle, opacity); | ||
} | ||
else if (this.Log().IsEnabled(LogLevel.Debug)) | ||
{ | ||
this.Log().Debug($"Object `{nameof(content)}` is a {content.GetType().FullName} and not a MacOSNativeElement subclass."); | ||
} | ||
} | ||
|
||
public void ChangeNativeElementVisibility(object content, bool visible) | ||
{ | ||
if (content is MacOSNativeElement element) | ||
{ | ||
// https://developer.apple.com/documentation/appkit/nsview/1483369-hidden?language=objc | ||
NativeUno.uno_native_set_visibility(element.NativeHandle, visible); | ||
} | ||
else if (this.Log().IsEnabled(LogLevel.Debug)) | ||
{ | ||
this.Log().Debug($"Object `{nameof(content)}` is a {content.GetType().FullName} and not a MacOSNativeElement subclass."); | ||
} | ||
} | ||
|
||
public object? CreateSampleComponent(string text) | ||
{ | ||
if (_window is null) | ||
{ | ||
if (this.Log().IsEnabled(LogLevel.Debug)) | ||
{ | ||
this.Log().Debug($"CreateSampleComponent failed as no MacOSWindowNative instance could be found."); | ||
} | ||
return null; | ||
} | ||
|
||
var handle = NativeUno.uno_native_create_sample(_window.Handle, text); | ||
return new MacOSNativeElement() | ||
{ | ||
NativeHandle = handle, | ||
AccessKey = text // FIXME: debug helper, to be removed | ||
}; | ||
} | ||
|
||
public void DetachNativeElement(object content) | ||
{ | ||
if (content is MacOSNativeElement element) | ||
{ | ||
if (element.Detached) | ||
{ | ||
this.Log().Debug($"Object `{nameof(content)}` of type {content.GetType().FullName} was already detached."); | ||
} | ||
else | ||
{ | ||
NativeUno.uno_native_detach(element.NativeHandle); | ||
element.Detached = true; | ||
} | ||
} | ||
else if (this.Log().IsEnabled(LogLevel.Debug)) | ||
{ | ||
this.Log().Debug($"Object `{nameof(content)}` is a {content.GetType().FullName} and not a MacOSNativeElement subclass."); | ||
} | ||
} | ||
|
||
public bool IsNativeElement(object content) => content is MacOSNativeElement; | ||
|
||
public bool IsNativeElementAttached(object owner, object nativeElement) | ||
{ | ||
if (nativeElement is MacOSNativeElement element) | ||
{ | ||
return NativeUno.uno_native_is_attached(element.NativeHandle); | ||
} | ||
else if (this.Log().IsEnabled(LogLevel.Debug)) | ||
{ | ||
this.Log().Debug($"Object `{nameof(owner)}` is a {owner.GetType().FullName} and not a MacOSNativeElement subclass."); | ||
} | ||
return false; | ||
} | ||
|
||
public Size MeasureNativeElement(object content, Size childMeasuredSize, Size availableSize) | ||
{ | ||
if (content is MacOSNativeElement element) | ||
{ | ||
NativeUno.uno_native_measure(element.NativeHandle, childMeasuredSize.Width, childMeasuredSize.Height, availableSize.Width, availableSize.Height, out var width, out var height); | ||
return new Size(width, height); | ||
} | ||
else if (this.Log().IsEnabled(LogLevel.Debug)) | ||
{ | ||
this.Log().Debug($"Object `{nameof(content)}` is a {content.GetType().FullName} and not a MacOSNativeElement subclass."); | ||
} | ||
return Size.Empty; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
src/Uno.UI.Runtime.Skia.MacOS/UnoNativeMac/UnoNativeMac/UNONative.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// | ||
// UNONative.h | ||
// | ||
|
||
#pragma once | ||
|
||
#import "UnoNativeMac.h" | ||
#import "UNOWindow.h" | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@protocol UNONativeElement | ||
|
||
@property (nonatomic) bool visible; | ||
|
||
-(void) detach; | ||
|
||
@end | ||
|
||
@interface UNORedView : NSView<UNONativeElement> | ||
|
||
@end | ||
|
||
NSView* uno_native_create_sample(NSWindow *window, const char* _Nullable text); | ||
|
||
void uno_native_arrange(NSView *element, double arrangeLeft, double arrangeTop, double arrangeWidth, double arrangeHeight, double clipLeft, double clipTop, double clipWidth, double clipHeight); | ||
|
||
void uno_native_attach(NSView* element); | ||
|
||
void uno_native_detach(NSView* element); | ||
|
||
bool uno_native_is_attached(NSView* element); | ||
|
||
void uno_native_measure(NSView* element, double childWidth, double childHeight, double availableWidth, double availableHeight, double* width, double* height); | ||
|
||
void uno_native_set_opacity(NSView* element, double opacity); | ||
|
||
void uno_native_set_visibility(NSView* element, bool visible); | ||
|
||
NS_ASSUME_NONNULL_END |
Oops, something went wrong.