committed by
GitHub
549 changed files with 12142 additions and 9792 deletions
@ -0,0 +1,113 @@ |
|||
#include "common.h" |
|||
|
|||
@interface CocoaThemeObserver : NSObject |
|||
-(id)initWithCallback:(IAvnActionCallback *)callback; |
|||
@end |
|||
|
|||
class PlatformSettings : public ComSingleObject<IAvnPlatformSettings, &IID_IAvnPlatformSettings> |
|||
{ |
|||
CocoaThemeObserver* observer; |
|||
|
|||
public: |
|||
FORWARD_IUNKNOWN() |
|||
virtual AvnPlatformThemeVariant GetPlatformTheme() override |
|||
{ |
|||
@autoreleasepool |
|||
{ |
|||
if (@available(macOS 10.14, *)) |
|||
{ |
|||
if (NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameAqua |
|||
|| NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameVibrantLight) { |
|||
return AvnPlatformThemeVariant::Light; |
|||
} else if (NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameDarkAqua |
|||
|| NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameVibrantDark) { |
|||
return AvnPlatformThemeVariant::Dark; |
|||
} else if (NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameAccessibilityHighContrastAqua |
|||
|| NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameAccessibilityHighContrastVibrantLight) { |
|||
return AvnPlatformThemeVariant::HighContrastLight; |
|||
} else if (NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameAccessibilityHighContrastDarkAqua |
|||
|| NSApplication.sharedApplication.effectiveAppearance.name == NSAppearanceNameAccessibilityHighContrastVibrantDark) { |
|||
return AvnPlatformThemeVariant::HighContrastDark; |
|||
} |
|||
} |
|||
return AvnPlatformThemeVariant::Light; |
|||
} |
|||
} |
|||
|
|||
virtual unsigned int GetAccentColor() override |
|||
{ |
|||
@autoreleasepool |
|||
{ |
|||
if (@available(macOS 10.14, *)) |
|||
{ |
|||
auto color = [NSColor controlAccentColor]; |
|||
return to_argb(color); |
|||
} |
|||
else |
|||
{ |
|||
return 0; |
|||
} |
|||
} |
|||
} |
|||
|
|||
virtual void RegisterColorsChange(IAvnActionCallback *callback) override |
|||
{ |
|||
if (@available(macOS 10.14, *)) |
|||
{ |
|||
observer = [[CocoaThemeObserver alloc] initWithCallback: callback]; |
|||
[[NSApplication sharedApplication] addObserver:observer forKeyPath:@"effectiveAppearance" options:NSKeyValueObservingOptionNew context:nil]; |
|||
} |
|||
} |
|||
|
|||
private: |
|||
unsigned int to_argb(NSColor* color) |
|||
{ |
|||
const CGFloat* components = CGColorGetComponents(color.CGColor); |
|||
unsigned int alpha = static_cast<unsigned int>(CGColorGetAlpha(color.CGColor) * 0xFF); |
|||
unsigned int red = static_cast<unsigned int>(components[0] * 0xFF); |
|||
unsigned int green = static_cast<unsigned int>(components[1] * 0xFF); |
|||
unsigned int blue = static_cast<unsigned int>(components[2] * 0xFF); |
|||
return (alpha << 24) + (red << 16) + (green << 8) + blue; |
|||
} |
|||
}; |
|||
|
|||
@implementation CocoaThemeObserver |
|||
{ |
|||
ComPtr<IAvnActionCallback> _callback; |
|||
} |
|||
- (id) initWithCallback:(IAvnActionCallback *)callback{ |
|||
self = [super init]; |
|||
if (self) { |
|||
_callback = callback; |
|||
} |
|||
return self; |
|||
} |
|||
|
|||
/*- (void)didChangeValueForKey:(NSString *)key { |
|||
if([key isEqualToString:@"effectiveAppearance"]) { |
|||
_callback->Run(); |
|||
} |
|||
else { |
|||
[super didChangeValueForKey:key]; |
|||
} |
|||
}*/ |
|||
|
|||
- (void)observeValueForKeyPath:(NSString *)keyPath |
|||
ofObject:(id)object |
|||
change:(NSDictionary *)change |
|||
context:(void *)context { |
|||
if([keyPath isEqualToString:@"effectiveAppearance"]) { |
|||
_callback->Run(); |
|||
} else { |
|||
[super observeValueForKeyPath:keyPath |
|||
ofObject:object |
|||
change:change |
|||
context:context]; |
|||
} |
|||
} |
|||
@end |
|||
|
|||
extern IAvnPlatformSettings* CreatePlatformSettings() |
|||
{ |
|||
return new PlatformSettings(); |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Android |
|||
{ |
|||
public interface IActivityNavigationService |
|||
{ |
|||
event EventHandler<AndroidBackRequestedEventArgs> BackRequested; |
|||
} |
|||
|
|||
public class AndroidBackRequestedEventArgs : EventArgs |
|||
{ |
|||
public bool Handled { get; set; } |
|||
} |
|||
} |
|||
@ -0,0 +1,94 @@ |
|||
using System; |
|||
using Android; |
|||
using Android.Content; |
|||
using Android.Content.Res; |
|||
using Android.Graphics; |
|||
using Android.Provider; |
|||
using Android.Views.Accessibility; |
|||
using AndroidX.Core.Content.Resources; |
|||
using Avalonia.Media; |
|||
using Avalonia.Platform; |
|||
using Color = Avalonia.Media.Color; |
|||
|
|||
namespace Avalonia.Android.Platform; |
|||
|
|||
// TODO: ideally should be created per view/activity.
|
|||
internal class AndroidPlatformSettings : DefaultPlatformSettings |
|||
{ |
|||
private PlatformColorValues _latestValues; |
|||
|
|||
public AndroidPlatformSettings() |
|||
{ |
|||
_latestValues = base.GetColorValues(); |
|||
} |
|||
|
|||
public override PlatformColorValues GetColorValues() |
|||
{ |
|||
return _latestValues; |
|||
} |
|||
|
|||
internal void OnViewConfigurationChanged(Context context) |
|||
{ |
|||
if (context.Resources?.Configuration is null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var systemTheme = (context.Resources.Configuration.UiMode & UiMode.NightMask) switch |
|||
{ |
|||
UiMode.NightYes => PlatformThemeVariant.Dark, |
|||
UiMode.NightNo => PlatformThemeVariant.Light, |
|||
_ => throw new ArgumentOutOfRangeException() |
|||
}; |
|||
|
|||
if (OperatingSystem.IsAndroidVersionAtLeast(31)) |
|||
{ |
|||
// See https://developer.android.com/reference/android/R.color
|
|||
var accent1 = context.Resources.GetColor(17170494, context.Theme); // Resource.Color.SystemAccent1500
|
|||
var accent2 = context.Resources.GetColor(17170507, context.Theme); // Resource.Color.SystemAccent2500
|
|||
var accent3 = context.Resources.GetColor(17170520, context.Theme); // Resource.Color.SystemAccent3500
|
|||
|
|||
_latestValues = new PlatformColorValues |
|||
{ |
|||
ThemeVariant = systemTheme, |
|||
ContrastPreference = IsHighContrast(context), |
|||
AccentColor1 = new Color(accent1.A, accent1.R, accent1.G, accent1.B), |
|||
AccentColor2 = new Color(accent2.A, accent2.R, accent2.G, accent2.B), |
|||
AccentColor3 = new Color(accent3.A, accent3.R, accent3.G, accent3.B), |
|||
}; |
|||
} |
|||
else if (OperatingSystem.IsAndroidVersionAtLeast(23)) |
|||
{ |
|||
// See https://developer.android.com/reference/android/R.attr
|
|||
var array = context.Theme.ObtainStyledAttributes(new[] { 16843829 }); // Resource.Attribute.ColorAccent
|
|||
var accent = array.GetColor(0, 0); |
|||
|
|||
_latestValues = new PlatformColorValues |
|||
{ |
|||
ThemeVariant = systemTheme, |
|||
ContrastPreference = IsHighContrast(context), |
|||
AccentColor1 = new Color(accent.A, accent.R, accent.G, accent.B) |
|||
}; |
|||
array.Recycle(); |
|||
} |
|||
else |
|||
{ |
|||
_latestValues = _latestValues with { ThemeVariant = systemTheme }; |
|||
} |
|||
|
|||
OnColorValuesChanged(_latestValues); |
|||
} |
|||
|
|||
private static ColorContrastPreference IsHighContrast(Context context) |
|||
{ |
|||
try |
|||
{ |
|||
return Settings.Secure.GetInt(context.ContentResolver, "high_text_contrast_enabled", 0) == 1 |
|||
? ColorContrastPreference.High : ColorContrastPreference.NoPreference; |
|||
} |
|||
catch |
|||
{ |
|||
return ColorContrastPreference.NoPreference; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
using System; |
|||
using Avalonia.Interactivity; |
|||
using Avalonia.Platform; |
|||
|
|||
namespace Avalonia.Android.Platform |
|||
{ |
|||
internal class AndroidSystemNavigationManager : ISystemNavigationManager |
|||
{ |
|||
public event EventHandler<RoutedEventArgs> BackRequested; |
|||
|
|||
public AndroidSystemNavigationManager(IActivityNavigationService? navigationService) |
|||
{ |
|||
if(navigationService != null) |
|||
{ |
|||
navigationService.BackRequested += OnBackRequested; |
|||
} |
|||
} |
|||
|
|||
private void OnBackRequested(object sender, AndroidBackRequestedEventArgs e) |
|||
{ |
|||
var routedEventArgs = new RoutedEventArgs(); |
|||
|
|||
BackRequested?.Invoke(this, routedEventArgs); |
|||
|
|||
e.Handled = routedEventArgs.Handled; |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue