Skip to content

Commit 9134c47

Browse files
committed
[OSX] update autofill popup view code
Fix nwjs#2653
1 parent a3c2eb0 commit 9134c47

File tree

7 files changed

+382
-195
lines changed

7 files changed

+382
-195
lines changed

nw.gypi

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@
201201
'src/api/window/window.h',
202202
'src/browser/app_controller_mac.h',
203203
'src/browser/app_controller_mac.mm',
204+
'src/browser/autofill_popup_base_view_cocoa.h',
205+
'src/browser/autofill_popup_base_view_cocoa.mm',
204206
'src/browser/autofill_popup_view_cocoa.h',
205207
'src/browser/autofill_popup_view_cocoa.mm',
206208
'src/browser/autofill_popup_view_bridge.h',
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2014 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+
#ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POPUP_BASE_VIEW_COCOA_H_
6+
#define CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POPUP_BASE_VIEW_COCOA_H_
7+
8+
#import <Cocoa/Cocoa.h>
9+
10+
#import "ui/base/cocoa/base_view.h"
11+
12+
namespace autofill {
13+
class AutofillPopupViewDelegate;
14+
}
15+
16+
@interface AutofillPopupBaseViewCocoa : BaseView {
17+
@private
18+
__weak autofill::AutofillPopupViewDelegate* delegate_;
19+
}
20+
21+
- (NSColor*)backgroundColor;
22+
- (NSColor*)borderColor;
23+
- (NSColor*)highlightColor;
24+
- (NSColor*)nameColor;
25+
- (NSColor*)separatorColor;
26+
- (NSColor*)subtextColor;
27+
- (NSColor*)warningColor;
28+
29+
- (id)initWithDelegate:(autofill::AutofillPopupViewDelegate*)delegate
30+
frame:(NSRect)frame;
31+
32+
// Informs the view that its delegate has been (or will imminently be)
33+
// destroyed.
34+
- (void)delegateDestroyed;
35+
36+
// Draw the popup's background and border.
37+
- (void)drawBackgroundAndBorder;
38+
39+
// Draws a thin separator in the popup UI.
40+
- (void)drawSeparatorWithBounds:(NSRect)bounds;
41+
42+
// Messages from AutofillPopupViewBridge:
43+
- (void)updateBoundsAndRedrawPopup;
44+
- (void)showPopup;
45+
- (void)hidePopup;
46+
@end
47+
48+
#endif // CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POPUP_BASE_VIEW_COCOA_H_
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// Copyright 2014 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+
#import "content/nw/src/browser/autofill_popup_base_view_cocoa.h"
6+
7+
#include "chrome/browser/ui/autofill/autofill_popup_view_delegate.h"
8+
#include "chrome/browser/ui/autofill/popup_constants.h"
9+
#include "ui/base/cocoa/window_size_constants.h"
10+
11+
@implementation AutofillPopupBaseViewCocoa
12+
13+
#pragma mark -
14+
#pragma mark Colors
15+
16+
- (NSColor*)backgroundColor {
17+
return [NSColor whiteColor];
18+
}
19+
20+
- (NSColor*)borderColor {
21+
return [NSColor colorForControlTint:[NSColor currentControlTint]];
22+
}
23+
24+
- (NSColor*)highlightColor {
25+
return [NSColor selectedControlColor];
26+
}
27+
28+
- (NSColor*)nameColor {
29+
return [NSColor blackColor];
30+
}
31+
32+
- (NSColor*)separatorColor {
33+
return [NSColor colorWithCalibratedWhite:220 / 255.0 alpha:1];
34+
}
35+
36+
- (NSColor*)subtextColor {
37+
return [NSColor grayColor];
38+
}
39+
40+
- (NSColor*)warningColor {
41+
return [NSColor grayColor];
42+
}
43+
44+
#pragma mark -
45+
#pragma mark Public methods
46+
47+
- (id)initWithDelegate:(autofill::AutofillPopupViewDelegate*)delegate
48+
frame:(NSRect)frame {
49+
self = [super initWithFrame:frame];
50+
if (self)
51+
delegate_ = delegate;
52+
53+
return self;
54+
}
55+
56+
- (void)delegateDestroyed {
57+
delegate_ = NULL;
58+
}
59+
60+
- (void)drawSeparatorWithBounds:(NSRect)bounds {
61+
[[self separatorColor] set];
62+
[NSBezierPath fillRect:bounds];
63+
}
64+
65+
// A slight optimization for drawing:
66+
// https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaViewsGuide/Optimizing/Optimizing.html
67+
- (BOOL)isOpaque {
68+
return YES;
69+
}
70+
71+
- (BOOL)isFlipped {
72+
// Flipped so that it's easier to share controller logic with other OSes.
73+
return YES;
74+
}
75+
76+
- (void)drawBackgroundAndBorder {
77+
// The inset is needed since the border is centered on the |path|.
78+
// TODO(isherman): We should consider using asset-based drawing for the
79+
// border, creating simple bitmaps for the view's border and background, and
80+
// drawing them using NSDrawNinePartImage().
81+
CGFloat inset = autofill::kPopupBorderThickness / 2.0;
82+
NSRect borderRect = NSInsetRect([self bounds], inset, inset);
83+
NSBezierPath* path = [NSBezierPath bezierPathWithRect:borderRect];
84+
[[self backgroundColor] setFill];
85+
[path fill];
86+
[path setLineWidth:autofill::kPopupBorderThickness];
87+
[[self borderColor] setStroke];
88+
[path stroke];
89+
}
90+
91+
- (void)mouseUp:(NSEvent*)theEvent {
92+
// If the view is in the process of being destroyed, abort.
93+
if (!delegate_)
94+
return;
95+
96+
// Only accept single-click.
97+
if ([theEvent clickCount] > 1)
98+
return;
99+
100+
NSPoint location = [self convertPoint:[theEvent locationInWindow]
101+
fromView:nil];
102+
103+
if (NSPointInRect(location, [self bounds])) {
104+
delegate_->SetSelectionAtPoint(gfx::Point(NSPointToCGPoint(location)));
105+
delegate_->AcceptSelectedLine();
106+
}
107+
}
108+
109+
- (void)mouseMoved:(NSEvent*)theEvent {
110+
// If the view is in the process of being destroyed, abort.
111+
if (!delegate_)
112+
return;
113+
114+
NSPoint location = [self convertPoint:[theEvent locationInWindow]
115+
fromView:nil];
116+
117+
delegate_->SetSelectionAtPoint(gfx::Point(NSPointToCGPoint(location)));
118+
}
119+
120+
- (void)mouseDragged:(NSEvent*)theEvent {
121+
[self mouseMoved:theEvent];
122+
}
123+
124+
- (void)mouseExited:(NSEvent*)theEvent {
125+
// If the view is in the process of being destroyed, abort.
126+
if (!delegate_)
127+
return;
128+
129+
delegate_->SelectionCleared();
130+
}
131+
132+
#pragma mark -
133+
#pragma mark Messages from AutofillPopupViewBridge:
134+
135+
- (void)updateBoundsAndRedrawPopup {
136+
NSRect frame = NSRectFromCGRect(delegate_->popup_bounds().ToCGRect());
137+
138+
// Flip coordinates back into Cocoa-land. The controller's platform-neutral
139+
// coordinate space places the origin at the top-left of the first screen,
140+
// whereas Cocoa's coordinate space expects the origin to be at the
141+
// bottom-left of this same screen.
142+
NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
143+
frame.origin.y = NSMaxY([screen frame]) - NSMaxY(frame);
144+
145+
// TODO(isherman): The view should support scrolling if the popup gets too
146+
// big to fit on the screen.
147+
[[self window] setFrame:frame display:YES];
148+
[self setNeedsDisplay:YES];
149+
}
150+
151+
- (void)showPopup {
152+
NSWindow* window =
153+
[[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater
154+
styleMask:NSBorderlessWindowMask
155+
backing:NSBackingStoreBuffered
156+
defer:YES];
157+
[window setContentView:self];
158+
159+
// Telling Cocoa that the window is opaque enables some drawing optimizations.
160+
[window setOpaque:YES];
161+
162+
[self updateBoundsAndRedrawPopup];
163+
[[delegate_->container_view() window] addChildWindow:window
164+
ordered:NSWindowAbove];
165+
}
166+
167+
- (void)hidePopup {
168+
// Remove the child window before closing, otherwise it can mess up
169+
// display ordering.
170+
NSWindow* window = [self window];
171+
[[window parentWindow] removeChildWindow:window];
172+
[window close];
173+
}
174+
175+
@end

src/browser/autofill_popup_view_bridge.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,20 @@
99

1010
#include "base/basictypes.h"
1111
#include "base/compiler_specific.h"
12+
#include "base/mac/scoped_nsobject.h"
1213
#include "chrome/browser/ui/autofill/autofill_popup_view.h"
14+
#include "content/nw/src/browser/autofill_popup_view_cocoa.h"
1315

1416
@class AutofillPopupViewCocoa;
1517
@class NSWindow;
1618

1719
namespace autofill {
1820

19-
class AutofillPopupController;
21+
class AutofillPopupViewDelegate;
2022

21-
// Mac implementation for AutofillPopupView interface.
22-
// Serves as a bridge to the Objective-C class AutofillPopupViewCocoa which
23-
// actually implements the view.
23+
// Mac implementation of the AutofillPopupView interface.
24+
// Serves as a bridge to an instance of the Objective-C class which actually
25+
// implements the view.
2426
class AutofillPopupViewBridge : public AutofillPopupView {
2527
public:
2628
explicit AutofillPopupViewBridge(AutofillPopupController* controller);
@@ -34,16 +36,13 @@ class AutofillPopupViewBridge : public AutofillPopupView {
3436
virtual void InvalidateRow(size_t row) OVERRIDE;
3537
virtual void UpdateBoundsAndRedrawPopup() OVERRIDE;
3638

37-
// Set the initial bounds of the popup to show, including the placement
38-
// of it.
39+
// Set the initial bounds of the popup, including its placement.
3940
void SetInitialBounds();
4041

41-
// The controller for this view.
42-
AutofillPopupController* controller_; // Weak reference.
42+
// The native Cocoa view.
43+
base::scoped_nsobject<AutofillPopupViewCocoa> view_;
4344

44-
// The native Cocoa window and view.
45-
NSWindow* window_; // Weak reference, owns itself.
46-
AutofillPopupViewCocoa* view_; // Weak reference, owned by the |window_|.
45+
AutofillPopupController* controller_; // Weak.
4746

4847
DISALLOW_COPY_AND_ASSIGN(AutofillPopupViewBridge);
4948
};

src/browser/autofill_popup_view_bridge.mm

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,70 +7,40 @@
77
#include "content/nw/src/browser/autofill_popup_view_bridge.h"
88

99
#include "base/logging.h"
10-
#include "content/nw/src/browser/autofill_popup_controller.h"
10+
#include "chrome/browser/ui/autofill/autofill_popup_controller.h"
11+
#include "chrome/browser/ui/autofill/autofill_popup_view_delegate.h"
1112
#import "content/nw/src/browser/autofill_popup_view_cocoa.h"
12-
#include "ui/base/cocoa/window_size_constants.h"
1313
#include "ui/gfx/rect.h"
1414

1515
namespace autofill {
1616

1717
AutofillPopupViewBridge::AutofillPopupViewBridge(
1818
AutofillPopupController* controller)
1919
: controller_(controller) {
20-
window_ =
21-
[[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater
22-
styleMask:NSBorderlessWindowMask
23-
backing:NSBackingStoreBuffered
24-
defer:YES];
25-
// Telling Cocoa that the window is opaque enables some drawing optimizations.
26-
[window_ setOpaque:YES];
27-
28-
view_ = [[[AutofillPopupViewCocoa alloc]
29-
initWithController:controller_
30-
frame:NSZeroRect] autorelease];
31-
[window_ setContentView:view_];
20+
view_.reset(
21+
[[AutofillPopupViewCocoa alloc] initWithController:controller
22+
frame:NSZeroRect]);
3223
}
3324

3425
AutofillPopupViewBridge::~AutofillPopupViewBridge() {
3526
[view_ controllerDestroyed];
36-
37-
// Remove the child window before closing, otherwise it can mess up
38-
// display ordering.
39-
[[window_ parentWindow] removeChildWindow:window_];
40-
41-
[window_ close];
27+
[view_ hidePopup];
4228
}
4329

4430
void AutofillPopupViewBridge::Hide() {
4531
delete this;
4632
}
4733

4834
void AutofillPopupViewBridge::Show() {
49-
UpdateBoundsAndRedrawPopup();
50-
[[controller_->container_view() window] addChildWindow:window_
51-
ordered:NSWindowAbove];
35+
[view_ showPopup];
5236
}
5337

5438
void AutofillPopupViewBridge::InvalidateRow(size_t row) {
55-
NSRect dirty_rect =
56-
NSRectFromCGRect(controller_->GetRowBounds(row).ToCGRect());
57-
[view_ setNeedsDisplayInRect:dirty_rect];
39+
[view_ invalidateRow:row];
5840
}
5941

6042
void AutofillPopupViewBridge::UpdateBoundsAndRedrawPopup() {
61-
NSRect frame = NSRectFromCGRect(controller_->popup_bounds().ToCGRect());
62-
63-
// Flip coordinates back into Cocoa-land. The controller's platform-neutral
64-
// coordinate space places the origin at the top-left of the first screen,
65-
// whereas Cocoa's coordinate space expects the origin to be at the
66-
// bottom-left of this same screen.
67-
NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
68-
frame.origin.y = NSMaxY([screen frame]) - NSMaxY(frame);
69-
70-
// TODO(isherman): The view should support scrolling if the popup gets too
71-
// big to fit on the screen.
72-
[window_ setFrame:frame display:YES];
73-
[view_ setNeedsDisplay:YES];
43+
[view_ updateBoundsAndRedrawPopup];
7444
}
7545

7646
AutofillPopupView* AutofillPopupView::Create(

src/browser/autofill_popup_view_cocoa.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
#ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POPUP_CONTENT_VIEW_H_
6-
#define CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POPUP_CONTENT_VIEW_H_
5+
#ifndef CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POPUP_VIEW_COCOA_H_
6+
#define CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POPUP_VIEW_COCOA_H_
77

88
#import <Cocoa/Cocoa.h>
99

10-
#import "ui/base/cocoa/base_view.h"
10+
#import "content/nw/src/browser/autofill_popup_base_view_cocoa.h"
1111

1212
namespace autofill {
1313
class AutofillPopupController;
1414
} // namespace autofill
1515

1616
// Draws the native Autofill popup view on Mac.
17-
@interface AutofillPopupViewCocoa : BaseView {
17+
@interface AutofillPopupViewCocoa : AutofillPopupBaseViewCocoa {
1818
@private
1919
// The cross-platform controller for this view.
2020
__weak autofill::AutofillPopupController* controller_;
@@ -28,6 +28,8 @@ class AutofillPopupController;
2828
// destroyed.
2929
- (void)controllerDestroyed;
3030

31+
- (void)invalidateRow:(size_t)row;
32+
3133
@end
3234

33-
#endif // CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POPUP_CONTENT_VIEW_H_
35+
#endif // CHROME_BROWSER_UI_COCOA_AUTOFILL_AUTOFILL_POPUP_VIEW_COCOA_H_

0 commit comments

Comments
 (0)