• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4
5#include "base/command_line.h"
6#include "base/mac/mac_util.h"
7#include "base/mac/sdk_forward_declarations.h"
8#import "chrome/browser/ui/cocoa/nsview_additions.h"
9#include "chrome/common/chrome_switches.h"
10#include "ui/base/ui_base_switches.h"
11#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
12
13#include "base/logging.h"
14
15@implementation NSView (ChromeAdditions)
16
17- (CGFloat)cr_lineWidth {
18  // All shipping retina macs run at least 10.7.
19  if (![self respondsToSelector:@selector(convertSizeFromBacking:)])
20    return 1;
21  return [self convertSizeFromBacking:NSMakeSize(1, 1)].width;
22}
23
24- (BOOL)cr_isMouseInView {
25  NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream];
26  mouseLoc = [[self superview] convertPoint:mouseLoc fromView:nil];
27  return [self hitTest:mouseLoc] == self;
28}
29
30- (BOOL)cr_isBelowView:(NSView*)otherView {
31  NSArray* subviews = [[self superview] subviews];
32
33  NSUInteger selfIndex = [subviews indexOfObject:self];
34  DCHECK_NE(NSNotFound, selfIndex);
35
36  NSUInteger otherIndex = [subviews indexOfObject:otherView];
37  DCHECK_NE(NSNotFound, otherIndex);
38
39  return selfIndex < otherIndex;
40}
41
42- (BOOL)cr_isAboveView:(NSView*)otherView {
43  return ![self cr_isBelowView:otherView];
44}
45
46- (void)cr_ensureSubview:(NSView*)subview
47            isPositioned:(NSWindowOrderingMode)place
48              relativeTo:(NSView *)otherView {
49  DCHECK(place == NSWindowAbove || place == NSWindowBelow);
50  BOOL isAbove = place == NSWindowAbove;
51  if ([[subview superview] isEqual:self] &&
52      [subview cr_isAboveView:otherView] == isAbove) {
53    return;
54  }
55
56  [subview removeFromSuperview];
57  [self addSubview:subview
58        positioned:place
59        relativeTo:otherView];
60}
61
62- (NSColor*)cr_keyboardFocusIndicatorColor {
63  return [[NSColor keyboardFocusIndicatorColor]
64      colorWithAlphaComponent:0.5 / [self cr_lineWidth]];
65}
66
67- (void)cr_recursivelySetNeedsDisplay:(BOOL)flag {
68  [self setNeedsDisplay:YES];
69  for (NSView* child in [self subviews])
70    [child cr_recursivelySetNeedsDisplay:flag];
71}
72
73- (void)cr_setWantsLayer:(BOOL)wantsLayer {
74  if (CommandLine::ForCurrentProcess()->HasSwitch(
75          switches::kDisableCoreAnimation))
76    return;
77
78  // Dynamically removing layers on SnowLeopard will sometimes result in
79  // crashes. Once a view has a layer on SnowLeopard, it is stuck with it.
80  // http://crbug.com/348328
81  if (!wantsLayer && base::mac::IsOSSnowLeopard())
82    return;
83
84  [self setWantsLayer:wantsLayer];
85}
86
87static NSView* g_ancestorBeingDrawnFrom = nil;
88static NSView* g_childBeingDrawnTo = nil;
89
90- (void)cr_drawUsingAncestor:(NSView*)ancestorView inRect:(NSRect)rect {
91  gfx::ScopedNSGraphicsContextSaveGState scopedGSState;
92  NSRect frame = [self convertRect:[self bounds] toView:ancestorView];
93  NSAffineTransform* transform = [NSAffineTransform transform];
94  if ([self isFlipped] == [ancestorView isFlipped]) {
95    [transform translateXBy:-NSMinX(frame) yBy:-NSMinY(frame)];
96  } else {
97    [transform translateXBy:-NSMinX(frame) yBy:NSMaxY(frame)];
98    [transform scaleXBy:1.0 yBy:-1.0];
99  }
100  [transform concat];
101
102  // This can be made robust to recursive calls, but is as of yet unneeded.
103  DCHECK(!g_ancestorBeingDrawnFrom && !g_childBeingDrawnTo);
104  g_ancestorBeingDrawnFrom = ancestorView;
105  g_childBeingDrawnTo = self;
106  [ancestorView drawRect:[ancestorView bounds]];
107  g_childBeingDrawnTo = nil;
108  g_ancestorBeingDrawnFrom = nil;
109}
110
111- (NSView*)cr_viewBeingDrawnTo {
112  if (!g_ancestorBeingDrawnFrom)
113    return self;
114  DCHECK(g_ancestorBeingDrawnFrom == self);
115  return g_childBeingDrawnTo;
116}
117
118@end
119