зеркало из https://github.com/mozilla/gecko-dev.git
Bug 868211 - Simplify Mac implementation of -moz-window-button-box. r=smichaud
This commit is contained in:
Родитель
07f9252ffd
Коммит
3bbae4a42e
|
@ -122,20 +122,6 @@ typedef struct _nsCocoaWindowList {
|
|||
|
||||
@end
|
||||
|
||||
// Present since at least OS X 10.5 in NSFrameView or one of its subclasses.
|
||||
@interface NSObject (NSFrameViewMethods)
|
||||
- (NSButton*)closeButton;
|
||||
- (NSButton*)zoomButton;
|
||||
- (NSButton*)minimizeButton;
|
||||
- (NSButton*)fullScreenButton;
|
||||
- (void)initTitleCell:(id)cell;
|
||||
@end
|
||||
|
||||
@interface NSView (MozFrameViewMethods)
|
||||
- (int32_t)buttonBoxDisplayPixelsWidth;
|
||||
- (int32_t)fullScreenButtonDisplayPixelsWidth;
|
||||
@end
|
||||
|
||||
@interface PopupWindow : BaseWindow
|
||||
{
|
||||
@private
|
||||
|
|
|
@ -2475,171 +2475,58 @@ GetDPI(NSWindow* aWindow)
|
|||
return dpi * backingScale;
|
||||
}
|
||||
|
||||
// Methods of our MozTitleCell and MozFrameView classes, created below as
|
||||
// subclasses of the appropriate undocumented superclasses. Since we don't
|
||||
// know beforehand exactly what the superclasses will be, each of these
|
||||
// classes is created dynamically, using low-level Objective-C runtime
|
||||
// methods. So their methods' declarations can't use Objective-C syntax.
|
||||
|
||||
static Class gMozTitleCellClass = nil;
|
||||
|
||||
typedef void (*NSCell_drawWithFrame)(struct objc_super *, SEL, NSRect, NSView *);
|
||||
|
||||
static void MozTitleCell_drawWithFrame(id self, SEL sel, NSRect cellFrame,
|
||||
NSView *controlView)
|
||||
{
|
||||
BaseWindow *window = nil;
|
||||
// The documentation for -[NSCell drawWithFrame:(NSRect)cellFrame
|
||||
// inView:(NSView*)controlView] says "this method draws the cell in the
|
||||
// currently focused view", which is what's returned by [NSView focusView].
|
||||
// So in the very unlikely event that 'controlView' is nil, we fall back
|
||||
// to using [NSView focusView].
|
||||
if (controlView) {
|
||||
window = (BaseWindow *) [controlView window];
|
||||
} else {
|
||||
window = (BaseWindow *) [[NSView focusView] window];
|
||||
}
|
||||
if ([window isKindOfClass:[BaseWindow class]]) {
|
||||
if ([window drawsContentsIntoWindowFrame]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
struct objc_super target;
|
||||
target.receiver = self;
|
||||
target.super_class = [self superclass];
|
||||
NSCell_drawWithFrame super = (NSCell_drawWithFrame) objc_msgSendSuper;
|
||||
super(&target, sel, cellFrame, controlView);
|
||||
}
|
||||
|
||||
static NSMutableDictionary *gFrameViewClassesByStyleMask = nil;
|
||||
|
||||
typedef void (*NSFrameView_initTitleCell)(struct objc_super *, SEL, id);
|
||||
|
||||
static void MozFrameView_initTitleCell(id self, SEL sel, id cell)
|
||||
{
|
||||
struct objc_super target;
|
||||
target.receiver = self;
|
||||
target.super_class = [self superclass];
|
||||
NSFrameView_initTitleCell super = (NSFrameView_initTitleCell) objc_msgSendSuper;
|
||||
super(&target, sel, cell);
|
||||
if (cell) {
|
||||
Class cellClass = [cell class];
|
||||
if (!gMozTitleCellClass) {
|
||||
Class newClass = objc_allocateClassPair(cellClass,
|
||||
"MozTitleCell", 0);
|
||||
if (newClass) {
|
||||
if ([cellClass instancesRespondToSelector:@selector(drawWithFrame:inView:)]) {
|
||||
class_addMethod(newClass, @selector(drawWithFrame:inView:),
|
||||
(IMP)MozTitleCell_drawWithFrame,
|
||||
"v@:{_NSRect={_NSPoint=ff}{_NSSize=ff}}@");
|
||||
}
|
||||
objc_registerClassPair(newClass);
|
||||
gMozTitleCellClass = newClass;
|
||||
}
|
||||
}
|
||||
if (gMozTitleCellClass &&
|
||||
cellClass == class_getSuperclass(gMozTitleCellClass)) {
|
||||
object_setClass(cell, gMozTitleCellClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t MozFrameView_buttonBoxDisplayPixelsWidth(id self, SEL sel)
|
||||
{
|
||||
NSRect buttonBox = NSZeroRect;
|
||||
NSButton *closeButton = nil;
|
||||
if ([self respondsToSelector:@selector(closeButton)]) {
|
||||
closeButton = [self closeButton];
|
||||
}
|
||||
if (closeButton) {
|
||||
NSRect closeButtonBox = [self convertRect:[closeButton bounds]
|
||||
fromView:closeButton];
|
||||
buttonBox = NSUnionRect(buttonBox, closeButtonBox);
|
||||
}
|
||||
NSButton *minimizeButton = nil;
|
||||
if ([self respondsToSelector:@selector(minimizeButton)]) {
|
||||
minimizeButton = [self minimizeButton];
|
||||
}
|
||||
if (minimizeButton) {
|
||||
NSRect minimizeButtonBox = [self convertRect:[minimizeButton bounds]
|
||||
fromView:minimizeButton];
|
||||
buttonBox = NSUnionRect(buttonBox, minimizeButtonBox);
|
||||
}
|
||||
NSButton *zoomButton = nil;
|
||||
if ([self respondsToSelector:@selector(zoomButton)]) {
|
||||
zoomButton = [self zoomButton];
|
||||
}
|
||||
if (zoomButton) {
|
||||
NSRect zoomButtonBox = [self convertRect:[zoomButton bounds]
|
||||
fromView:zoomButton];
|
||||
buttonBox = NSUnionRect(buttonBox, zoomButtonBox);
|
||||
}
|
||||
return rint(buttonBox.size.width);
|
||||
}
|
||||
|
||||
static int32_t MozFrameView_fullScreenButtonDisplayPixelsWidth(id self, SEL sel)
|
||||
{
|
||||
CGFloat floatWidth = 0;
|
||||
NSButton *fullScreenButton = nil;
|
||||
if ([self respondsToSelector:@selector(fullScreenButton)]) {
|
||||
fullScreenButton = [self fullScreenButton];
|
||||
}
|
||||
if (fullScreenButton) {
|
||||
floatWidth += [self convertSize:[fullScreenButton bounds].size
|
||||
fromView:fullScreenButton].width;
|
||||
}
|
||||
return rint(floatWidth);
|
||||
}
|
||||
|
||||
@interface BaseWindow(Private)
|
||||
- (void)removeTrackingArea;
|
||||
- (void)cursorUpdated:(NSEvent*)aEvent;
|
||||
@end
|
||||
|
||||
@interface NSView(FrameViewMethodSwizzling)
|
||||
- (void)FrameViewClass__drawTitleBar:(NSRect)aRect;
|
||||
@end
|
||||
|
||||
@implementation NSView(FrameViewMethodSwizzling)
|
||||
|
||||
- (void)FrameViewClass__drawTitleBar:(NSRect)aRect
|
||||
{
|
||||
NSWindow* window = [self window];
|
||||
if ([window isKindOfClass:[BaseWindow class]] &&
|
||||
[(BaseWindow*)window drawsContentsIntoWindowFrame]) {
|
||||
// Do not draw the title.
|
||||
return;
|
||||
}
|
||||
[self FrameViewClass__drawTitleBar:aRect];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
static NSMutableSet *gSwizzledFrameViewClasses = nil;
|
||||
|
||||
@implementation BaseWindow
|
||||
|
||||
// The frame of a window is implemented using undocumented NSView subclasses.
|
||||
// We disable window title drawing by overriding the _drawTitleBar: method on
|
||||
// these frame view classes. The class which is used for a window is
|
||||
// determined in the window's frameViewClassForStyleMask: method, so this is
|
||||
// where we make sure that we have swizzled the method on all encountered
|
||||
// classes.
|
||||
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask
|
||||
{
|
||||
Class retval = [super frameViewClassForStyleMask:styleMask];
|
||||
Class frameViewClass = [super frameViewClassForStyleMask:styleMask];
|
||||
|
||||
if (!gFrameViewClassesByStyleMask) {
|
||||
gFrameViewClassesByStyleMask =
|
||||
[[NSMutableDictionary dictionaryWithCapacity:3] retain];
|
||||
}
|
||||
if (!gFrameViewClassesByStyleMask) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
NSString *styleMaskString =
|
||||
[NSString stringWithFormat:@"%p", (void *) styleMask];
|
||||
Class existingClass = (Class)
|
||||
[gFrameViewClassesByStyleMask valueForKey:styleMaskString];
|
||||
if (existingClass) {
|
||||
retval = existingClass;
|
||||
} else if (retval) {
|
||||
char newClassName[32];
|
||||
snprintf(newClassName, sizeof(newClassName) - 1, "MozFrameView%s",
|
||||
[styleMaskString UTF8String]);
|
||||
Class newClass = objc_allocateClassPair(retval, newClassName, 0);
|
||||
if (newClass) {
|
||||
if ([retval instancesRespondToSelector:@selector(initTitleCell:)]) {
|
||||
class_addMethod(newClass, @selector(initTitleCell:),
|
||||
(IMP)MozFrameView_initTitleCell,
|
||||
"v@:@");
|
||||
}
|
||||
class_addMethod(newClass, @selector(buttonBoxDisplayPixelsWidth),
|
||||
(IMP)MozFrameView_buttonBoxDisplayPixelsWidth,
|
||||
"l@:");
|
||||
class_addMethod(newClass, @selector(fullScreenButtonDisplayPixelsWidth),
|
||||
(IMP)MozFrameView_fullScreenButtonDisplayPixelsWidth,
|
||||
"l@:");
|
||||
objc_registerClassPair(newClass);
|
||||
[gFrameViewClassesByStyleMask setValue:newClass forKey:styleMaskString];
|
||||
retval = newClass;
|
||||
if (!gSwizzledFrameViewClasses) {
|
||||
gSwizzledFrameViewClasses = [[NSMutableSet setWithCapacity:3] retain];
|
||||
if (!gSwizzledFrameViewClasses) {
|
||||
return frameViewClass;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
if (![gSwizzledFrameViewClasses containsObject:frameViewClass]) {
|
||||
nsToolkit::SwizzleMethods(frameViewClass, @selector(_drawTitleBar:),
|
||||
@selector(FrameViewClass__drawTitleBar:));
|
||||
[gSwizzledFrameViewClasses addObject:frameViewClass];
|
||||
}
|
||||
|
||||
return frameViewClass;
|
||||
}
|
||||
|
||||
- (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)aFlag
|
||||
|
|
|
@ -358,36 +358,27 @@ static NSWindow* NativeWindowForFrame(nsIFrame* aFrame,
|
|||
return (NSWindow*)topLevelWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
}
|
||||
|
||||
static NSView* FrameViewForFrame(nsIFrame* aFrame)
|
||||
static int32_t WindowButtonsReservedWidth(nsIFrame* aFrame)
|
||||
{
|
||||
NSWindow* window = NativeWindowForFrame(aFrame);
|
||||
return [[window contentView] superview];
|
||||
}
|
||||
|
||||
static int32_t ButtonBoxDisplayPixelsWidth(nsIFrame* aFrame)
|
||||
{
|
||||
int32_t retval = 60; // Default value;
|
||||
NSView *frameView = FrameViewForFrame(aFrame);
|
||||
if ([frameView respondsToSelector:@selector(buttonBoxDisplayPixelsWidth)]) {
|
||||
int32_t measuredWidth = [frameView buttonBoxDisplayPixelsWidth];
|
||||
if (measuredWidth) {
|
||||
retval = measuredWidth;
|
||||
}
|
||||
if (!window) {
|
||||
return 61; // fallback value
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int32_t FullScreenButtonDisplayPixelsWidth(nsIFrame* aFrame)
|
||||
{
|
||||
int32_t retval = 20; // Default value;
|
||||
NSView *frameView = FrameViewForFrame(aFrame);
|
||||
if ([frameView respondsToSelector:@selector(fullScreenButtonDisplayPixelsWidth)]) {
|
||||
int32_t measuredWidth = [frameView fullScreenButtonDisplayPixelsWidth];
|
||||
if (measuredWidth) {
|
||||
retval = measuredWidth;
|
||||
}
|
||||
NSRect buttonBox = NSZeroRect;
|
||||
NSButton* closeButton = [window standardWindowButton:NSWindowCloseButton];
|
||||
if (closeButton) {
|
||||
buttonBox = NSUnionRect(buttonBox, [closeButton frame]);
|
||||
}
|
||||
return retval;
|
||||
NSButton* minimizeButton = [window standardWindowButton:NSWindowMiniaturizeButton];
|
||||
if (minimizeButton) {
|
||||
buttonBox = NSUnionRect(buttonBox, [minimizeButton frame]);
|
||||
}
|
||||
NSButton* zoomButton = [window standardWindowButton:NSWindowZoomButton];
|
||||
if (zoomButton) {
|
||||
buttonBox = NSUnionRect(buttonBox, [zoomButton frame]);
|
||||
}
|
||||
return int32_t(NSMaxX(buttonBox));
|
||||
}
|
||||
|
||||
static BOOL FrameIsInActiveWindow(nsIFrame* aFrame)
|
||||
|
@ -2768,12 +2759,14 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext,
|
|||
}
|
||||
|
||||
case NS_THEME_WINDOW_BUTTON_BOX: {
|
||||
aResult->SizeTo(ButtonBoxDisplayPixelsWidth(aFrame), 0);
|
||||
aResult->SizeTo(WindowButtonsReservedWidth(aFrame), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NS_THEME_MOZ_MAC_FULLSCREEN_BUTTON: {
|
||||
aResult->SizeTo(FullScreenButtonDisplayPixelsWidth(aFrame), 0);
|
||||
// This value is hardcoded because it's needed before we can measure the
|
||||
// position and size of the fullscreen button.
|
||||
aResult->SizeTo(20, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче