Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ui / base / cocoa / nsview_additions.mm
blob250965cce12376e7ee4e5c4609090c92467a3451
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/mac/sdk_forward_declarations.h"
6 #import "ui/base/cocoa/nsview_additions.h"
7 #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
9 #include "base/logging.h"
11 @implementation NSView (ChromeAdditions)
13 - (CGFloat)cr_lineWidth {
14   // All shipping retina macs run at least 10.7.
15   if (![self respondsToSelector:@selector(convertSizeFromBacking:)])
16     return 1;
17   return [self convertSizeFromBacking:NSMakeSize(1, 1)].width;
20 - (BOOL)cr_isMouseInView {
21   NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream];
22   mouseLoc = [[self superview] convertPoint:mouseLoc fromView:nil];
23   return [self hitTest:mouseLoc] == self;
26 - (BOOL)cr_isBelowView:(NSView*)otherView {
27   NSArray* subviews = [[self superview] subviews];
29   NSUInteger selfIndex = [subviews indexOfObject:self];
30   DCHECK(NSNotFound != selfIndex);
32   NSUInteger otherIndex = [subviews indexOfObject:otherView];
33   DCHECK(NSNotFound != otherIndex);
35   return selfIndex < otherIndex;
38 - (BOOL)cr_isAboveView:(NSView*)otherView {
39   return ![self cr_isBelowView:otherView];
42 - (void)cr_ensureSubview:(NSView*)subview
43             isPositioned:(NSWindowOrderingMode)place
44               relativeTo:(NSView *)otherView {
45   DCHECK(place == NSWindowAbove || place == NSWindowBelow);
46   BOOL isAbove = place == NSWindowAbove;
47   if ([[subview superview] isEqual:self] &&
48       [subview cr_isAboveView:otherView] == isAbove) {
49     return;
50   }
52   [subview removeFromSuperview];
53   [self addSubview:subview
54         positioned:place
55         relativeTo:otherView];
58 - (NSColor*)cr_keyboardFocusIndicatorColor {
59   return [[NSColor keyboardFocusIndicatorColor]
60       colorWithAlphaComponent:0.5 / [self cr_lineWidth]];
63 - (void)cr_recursivelyInvokeBlock:(void (^)(id view))block {
64   block(self);
65   for (NSView* subview in [self subviews])
66     [subview cr_recursivelyInvokeBlock:block];
69 - (void)cr_recursivelySetNeedsDisplay:(BOOL)flag {
70   [self setNeedsDisplay:YES];
71   for (NSView* child in [self subviews])
72     [child cr_recursivelySetNeedsDisplay:flag];
75 static NSView* g_ancestorBeingDrawnFrom = nil;
76 static NSView* g_childBeingDrawnTo = nil;
78 - (void)cr_drawUsingAncestor:(NSView*)ancestorView inRect:(NSRect)dirtyRect
79      clippedToAncestorBounds:(BOOL)clipToAncestorBounds {
80   gfx::ScopedNSGraphicsContextSaveGState scopedGSState;
81   NSRect frame = [self convertRect:[self bounds] toView:ancestorView];
82   NSAffineTransform* transform = [NSAffineTransform transform];
83   if ([self isFlipped] == [ancestorView isFlipped]) {
84     [transform translateXBy:-NSMinX(frame) yBy:-NSMinY(frame)];
85   } else {
86     [transform translateXBy:-NSMinX(frame) yBy:NSMaxY(frame)];
87     [transform scaleXBy:1.0 yBy:-1.0];
88   }
89   [transform concat];
91   // This can be made robust to recursive calls, but is as of yet unneeded.
92   DCHECK(!g_ancestorBeingDrawnFrom && !g_childBeingDrawnTo);
93   g_ancestorBeingDrawnFrom = ancestorView;
94   g_childBeingDrawnTo = self;
95   NSRect drawRect = [self convertRect:dirtyRect toView:ancestorView];
96   if (clipToAncestorBounds) {
97     drawRect = NSIntersectionRect([ancestorView bounds], drawRect);
98   }
99   [ancestorView drawRect:drawRect];
100   g_childBeingDrawnTo = nil;
101   g_ancestorBeingDrawnFrom = nil;
104 - (void)cr_drawUsingAncestor:(NSView*)ancestorView inRect:(NSRect)dirtyRect {
105   [self cr_drawUsingAncestor:ancestorView
106                       inRect:dirtyRect
107      clippedToAncestorBounds:YES];
110 - (NSView*)cr_viewBeingDrawnTo {
111   if (!g_ancestorBeingDrawnFrom)
112     return self;
113   DCHECK(g_ancestorBeingDrawnFrom == self);
114   return g_childBeingDrawnTo;
117 @end