зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1673055 - Simplify VibrancyManager.mm. r=haik
This removes some code which was creating new Objective C classes at runtime. I originally wrote this code because NSVisualEffectView was a new class that was added in 10.10, and we were building with a pre-10.10 SDK. These days we build with the 10.11 SDK, which has NSVisualEffectView, and we only run on 10.12+. Differential Revision: https://phabricator.services.mozilla.com/D94622
This commit is contained in:
Родитель
af68ac4a30
Коммит
a15e11c85e
|
@ -12,6 +12,121 @@
|
|||
|
||||
using namespace mozilla;
|
||||
|
||||
#if !defined(MAC_OS_X_VERSION_10_12) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
|
||||
enum { NSVisualEffectMaterialSelection = 4 };
|
||||
|
||||
@interface NSVisualEffectView (NSVisualEffectViewMethods)
|
||||
- (void)setEmphasized:(BOOL)emphasized;
|
||||
@end
|
||||
#endif
|
||||
|
||||
@interface MOZVibrantView : NSVisualEffectView {
|
||||
VibrancyType mType;
|
||||
}
|
||||
- (instancetype)initWithFrame:(NSRect)aRect vibrancyType:(VibrancyType)aVibrancyType;
|
||||
@end
|
||||
|
||||
@interface MOZVibrantLeafView : MOZVibrantView
|
||||
@end
|
||||
|
||||
static NSAppearance* AppearanceForVibrancyType(VibrancyType aType) {
|
||||
switch (aType) {
|
||||
case VibrancyType::LIGHT:
|
||||
case VibrancyType::TOOLTIP:
|
||||
case VibrancyType::MENU:
|
||||
case VibrancyType::HIGHLIGHTED_MENUITEM:
|
||||
case VibrancyType::SHEET:
|
||||
case VibrancyType::SOURCE_LIST:
|
||||
case VibrancyType::SOURCE_LIST_SELECTION:
|
||||
case VibrancyType::ACTIVE_SOURCE_LIST_SELECTION:
|
||||
return [NSAppearance appearanceNamed:@"NSAppearanceNameVibrantLight"];
|
||||
case VibrancyType::DARK:
|
||||
return [NSAppearance appearanceNamed:@"NSAppearanceNameVibrantDark"];
|
||||
}
|
||||
}
|
||||
|
||||
static NSVisualEffectState VisualEffectStateForVibrancyType(VibrancyType aType) {
|
||||
switch (aType) {
|
||||
case VibrancyType::TOOLTIP:
|
||||
case VibrancyType::MENU:
|
||||
case VibrancyType::HIGHLIGHTED_MENUITEM:
|
||||
case VibrancyType::SHEET:
|
||||
// Tooltip and menu windows are never "key" and sheets always looks
|
||||
// active, so we need to tell the vibrancy effect to look active
|
||||
// regardless of window state.
|
||||
return NSVisualEffectStateActive;
|
||||
default:
|
||||
return NSVisualEffectStateFollowsWindowActiveState;
|
||||
}
|
||||
}
|
||||
|
||||
static NSVisualEffectMaterial VisualEffectMaterialForVibrancyType(VibrancyType aType,
|
||||
BOOL* aOutIsEmphasized) {
|
||||
switch (aType) {
|
||||
case VibrancyType::MENU:
|
||||
return NSVisualEffectMaterialMenu;
|
||||
case VibrancyType::SOURCE_LIST:
|
||||
return NSVisualEffectMaterialSidebar;
|
||||
case VibrancyType::SOURCE_LIST_SELECTION:
|
||||
return (NSVisualEffectMaterial)NSVisualEffectMaterialSelection;
|
||||
case VibrancyType::HIGHLIGHTED_MENUITEM:
|
||||
case VibrancyType::ACTIVE_SOURCE_LIST_SELECTION:
|
||||
*aOutIsEmphasized = YES;
|
||||
return (NSVisualEffectMaterial)NSVisualEffectMaterialSelection;
|
||||
default:
|
||||
return NSVisualEffectMaterialAppearanceBased;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL HasVibrantForeground(VibrancyType aType) {
|
||||
switch (aType) {
|
||||
case VibrancyType::MENU:
|
||||
return YES;
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
@implementation MOZVibrantView
|
||||
|
||||
- (instancetype)initWithFrame:(NSRect)aRect vibrancyType:(VibrancyType)aType {
|
||||
self = [super initWithFrame:aRect];
|
||||
mType = aType;
|
||||
|
||||
self.appearance = AppearanceForVibrancyType(mType);
|
||||
self.state = VisualEffectStateForVibrancyType(mType);
|
||||
|
||||
BOOL isEmphasized = NO;
|
||||
self.material = VisualEffectMaterialForVibrancyType(mType, &isEmphasized);
|
||||
|
||||
if (isEmphasized && [self respondsToSelector:@selector(setEmphasized:)]) {
|
||||
[self setEmphasized:YES];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// Don't override allowsVibrancy here, because this view may have subviews, and
|
||||
// returning YES from allowsVibrancy forces on foreground vibrancy for all
|
||||
// descendant views, which can have unintended effects.
|
||||
|
||||
@end
|
||||
|
||||
@implementation MOZVibrantLeafView
|
||||
|
||||
- (NSView*)hitTest:(NSPoint)aPoint {
|
||||
// This view must be transparent to mouse events.
|
||||
return nil;
|
||||
}
|
||||
|
||||
// MOZVibrantLeafView does not have subviews, so we can return YES here without
|
||||
// having unintended effects on other contents of the window.
|
||||
- (BOOL)allowsVibrancy {
|
||||
return HasVibrantForeground(mType);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
bool VibrancyManager::UpdateVibrantRegion(VibrancyType aType,
|
||||
const LayoutDeviceIntRegion& aRegion) {
|
||||
if (aRegion.IsEmpty()) {
|
||||
|
@ -31,147 +146,9 @@ LayoutDeviceIntRegion VibrancyManager::GetUnionOfVibrantRegions() const {
|
|||
return result;
|
||||
}
|
||||
|
||||
static NSView* HitTestNil(id self, SEL _cmd, NSPoint aPoint) {
|
||||
// This view must be transparent to mouse events.
|
||||
return nil;
|
||||
}
|
||||
|
||||
static BOOL AllowsVibrancyYes(id self, SEL _cmd) {
|
||||
// Means that the foreground is blended using a vibrant blend mode.
|
||||
return YES;
|
||||
}
|
||||
|
||||
static Class CreateEffectViewClass(BOOL aForegroundVibrancy, BOOL aIsContainer) {
|
||||
// Create a class that inherits from NSVisualEffectView and overrides the
|
||||
// methods -[NSView hitTest:] and -[NSVisualEffectView allowsVibrancy].
|
||||
Class NSVisualEffectViewClass = NSClassFromString(@"NSVisualEffectView");
|
||||
const char* className = aForegroundVibrancy ? "EffectViewWithForegroundVibrancy"
|
||||
: "EffectViewWithoutForegroundVibrancy";
|
||||
Class EffectViewClass = objc_allocateClassPair(NSVisualEffectViewClass, className, 0);
|
||||
if (!aIsContainer) {
|
||||
// Make this view transparent to mouse events.
|
||||
class_addMethod(EffectViewClass, @selector(hitTest:), (IMP)HitTestNil, "@@:{CGPoint=dd}");
|
||||
}
|
||||
if (aForegroundVibrancy) {
|
||||
// Override the -[NSView allowsVibrancy] method to return YES.
|
||||
class_addMethod(EffectViewClass, @selector(allowsVibrancy), (IMP)AllowsVibrancyYes, "I@:");
|
||||
}
|
||||
return EffectViewClass;
|
||||
}
|
||||
|
||||
static id AppearanceForVibrancyType(VibrancyType aType) {
|
||||
Class NSAppearanceClass = NSClassFromString(@"NSAppearance");
|
||||
switch (aType) {
|
||||
case VibrancyType::LIGHT:
|
||||
case VibrancyType::TOOLTIP:
|
||||
case VibrancyType::MENU:
|
||||
case VibrancyType::HIGHLIGHTED_MENUITEM:
|
||||
case VibrancyType::SHEET:
|
||||
case VibrancyType::SOURCE_LIST:
|
||||
case VibrancyType::SOURCE_LIST_SELECTION:
|
||||
case VibrancyType::ACTIVE_SOURCE_LIST_SELECTION:
|
||||
return [NSAppearanceClass performSelector:@selector(appearanceNamed:)
|
||||
withObject:@"NSAppearanceNameVibrantLight"];
|
||||
case VibrancyType::DARK:
|
||||
return [NSAppearanceClass performSelector:@selector(appearanceNamed:)
|
||||
withObject:@"NSAppearanceNameVibrantDark"];
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(MAC_OS_X_VERSION_10_10) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10
|
||||
enum {
|
||||
NSVisualEffectStateFollowsWindowActiveState,
|
||||
NSVisualEffectStateActive,
|
||||
NSVisualEffectStateInactive
|
||||
};
|
||||
|
||||
enum { NSVisualEffectMaterialTitlebar = 3 };
|
||||
#endif
|
||||
|
||||
#if !defined(MAC_OS_X_VERSION_10_11) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_11
|
||||
enum { NSVisualEffectMaterialMenu = 5, NSVisualEffectMaterialSidebar = 7 };
|
||||
#endif
|
||||
|
||||
static NSUInteger VisualEffectStateForVibrancyType(VibrancyType aType) {
|
||||
switch (aType) {
|
||||
case VibrancyType::TOOLTIP:
|
||||
case VibrancyType::MENU:
|
||||
case VibrancyType::HIGHLIGHTED_MENUITEM:
|
||||
case VibrancyType::SHEET:
|
||||
// Tooltip and menu windows are never "key" and sheets always looks
|
||||
// active, so we need to tell the vibrancy effect to look active
|
||||
// regardless of window state.
|
||||
return NSVisualEffectStateActive;
|
||||
default:
|
||||
return NSVisualEffectStateFollowsWindowActiveState;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL HasVibrantForeground(VibrancyType aType) {
|
||||
switch (aType) {
|
||||
case VibrancyType::MENU:
|
||||
return YES;
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(MAC_OS_X_VERSION_10_12) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
|
||||
enum { NSVisualEffectMaterialSelection = 4 };
|
||||
#endif
|
||||
|
||||
@interface NSView (NSVisualEffectViewMethods)
|
||||
- (void)setState:(NSUInteger)state;
|
||||
- (void)setMaterial:(NSUInteger)material;
|
||||
- (void)setEmphasized:(BOOL)emphasized;
|
||||
@end
|
||||
|
||||
/* static */ NSView* VibrancyManager::CreateEffectView(VibrancyType aType, BOOL aIsContainer) {
|
||||
static Class EffectViewWithoutForegroundVibrancy = CreateEffectViewClass(NO, NO);
|
||||
static Class EffectViewWithForegroundVibrancy = CreateEffectViewClass(YES, NO);
|
||||
static Class EffectViewContainer = CreateEffectViewClass(NO, YES);
|
||||
|
||||
// Pick the right NSVisualEffectView subclass for the desired vibrancy mode.
|
||||
// For "container" views, never use foreground vibrancy, because returning
|
||||
// YES from allowsVibrancy forces on foreground vibrancy for all descendant
|
||||
// views which can have unintended effects.
|
||||
Class EffectViewClass = aIsContainer
|
||||
? EffectViewContainer
|
||||
: (HasVibrantForeground(aType) ? EffectViewWithForegroundVibrancy
|
||||
: EffectViewWithoutForegroundVibrancy);
|
||||
|
||||
NSView* effectView = [[EffectViewClass alloc] initWithFrame:NSZeroRect];
|
||||
[effectView performSelector:@selector(setAppearance:)
|
||||
withObject:AppearanceForVibrancyType(aType)];
|
||||
[effectView setState:VisualEffectStateForVibrancyType(aType)];
|
||||
|
||||
BOOL canUseElCapitanMaterials = nsCocoaFeatures::OnElCapitanOrLater();
|
||||
if (aType == VibrancyType::MENU) {
|
||||
// Before 10.11 there is no material that perfectly matches the menu
|
||||
// look. Of all available material types, NSVisualEffectMaterialTitlebar
|
||||
// is the one that comes closest.
|
||||
[effectView setMaterial:canUseElCapitanMaterials ? NSVisualEffectMaterialMenu
|
||||
: NSVisualEffectMaterialTitlebar];
|
||||
} else if (aType == VibrancyType::SOURCE_LIST && canUseElCapitanMaterials) {
|
||||
[effectView setMaterial:NSVisualEffectMaterialSidebar];
|
||||
} else if (aType == VibrancyType::HIGHLIGHTED_MENUITEM ||
|
||||
aType == VibrancyType::SOURCE_LIST_SELECTION ||
|
||||
aType == VibrancyType::ACTIVE_SOURCE_LIST_SELECTION) {
|
||||
[effectView setMaterial:NSVisualEffectMaterialSelection];
|
||||
if ([effectView respondsToSelector:@selector(setEmphasized:)] &&
|
||||
aType != VibrancyType::SOURCE_LIST_SELECTION) {
|
||||
[effectView setEmphasized:YES];
|
||||
}
|
||||
}
|
||||
|
||||
return effectView;
|
||||
return aIsContainer ? [[MOZVibrantView alloc] initWithFrame:NSZeroRect vibrancyType:aType]
|
||||
: [[MOZVibrantLeafView alloc] initWithFrame:NSZeroRect vibrancyType:aType];
|
||||
}
|
||||
|
||||
static bool ComputeSystemSupportsVibrancy() {
|
||||
return NSClassFromString(@"NSAppearance") && NSClassFromString(@"NSVisualEffectView");
|
||||
}
|
||||
|
||||
/* static */ bool VibrancyManager::SystemSupportsVibrancy() {
|
||||
static bool supportsVibrancy = ComputeSystemSupportsVibrancy();
|
||||
return supportsVibrancy;
|
||||
}
|
||||
/* static */ bool VibrancyManager::SystemSupportsVibrancy() { return true; }
|
||||
|
|
Загрузка…
Ссылка в новой задаче