OLD | NEW |
---|---|
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/cocoa/bubble_anchor_helper_views.h" | 5 #include "chrome/browser/ui/cocoa/bubble_anchor_helper_views.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 | 8 |
9 #import "base/mac/scoped_nsobject.h" | 9 #import "base/mac/scoped_nsobject.h" |
10 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | |
11 #import "chrome/browser/ui/cocoa/location_bar/location_bar_decoration.h" | |
12 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" | |
13 #import "chrome/browser/ui/cocoa/location_bar/manage_passwords_decoration.h" | |
14 #import "chrome/browser/ui/cocoa/location_bar/star_decoration.h" | |
10 #include "ui/views/bubble/bubble_dialog_delegate.h" | 15 #include "ui/views/bubble/bubble_dialog_delegate.h" |
11 #include "ui/views/widget/widget_observer.h" | 16 #include "ui/views/widget/widget_observer.h" |
12 | 17 |
13 namespace { | 18 namespace { |
14 | 19 |
15 // Self-deleting object that hosts Objective-C observers watching for parent | 20 // Self-deleting object that hosts Objective-C observers watching for parent |
16 // window resizes to reposition a bubble Widget. Deletes itself when the bubble | 21 // window resizes to reposition a bubble Widget. Deletes itself when the bubble |
17 // Widget closes. | 22 // Widget closes. |
18 class BubbleAnchorHelper : public views::WidgetObserver { | 23 class BubbleAnchorHelper : public views::WidgetObserver { |
19 public: | 24 public: |
20 explicit BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble); | 25 explicit BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble, |
tapted
2017/05/16 07:39:37
nit: explicit not required
spqchan
2017/05/17 01:39:39
Done.
| |
26 LocationBarDecoration* decoration); | |
21 | 27 |
22 private: | 28 private: |
23 // Observe |name| on the bubble parent window with a block to call ReAnchor(). | 29 // Observe |name| on the bubble parent window with a block to call ReAnchor(). |
24 void Observe(NSString* name); | 30 void Observe(NSString* name); |
25 | 31 |
26 // Whether offset from the left of the parent window is fixed. | 32 // Whether offset from the left of the parent window is fixed. |
27 bool IsMinXFixed() const { | 33 bool IsMinXFixed() const { |
28 return views::BubbleBorder::is_arrow_on_left(bubble_->arrow()); | 34 return views::BubbleBorder::is_arrow_on_left(bubble_->arrow()); |
29 } | 35 } |
30 | 36 |
31 // Re-positions |bubble_| so that the offset to the parent window at | 37 // Re-positions |bubble_| so that the offset to the parent window at |
32 // construction time is preserved. | 38 // construction time is preserved. |
33 void ReAnchor(); | 39 void ReAnchor(); |
34 | 40 |
35 // WidgetObserver: | 41 // WidgetObserver: |
36 void OnWidgetDestroying(views::Widget* widget) override; | 42 void OnWidgetDestroying(views::Widget* widget) override; |
37 | 43 |
38 base::scoped_nsobject<NSMutableArray> observer_tokens_; | 44 base::scoped_nsobject<NSMutableArray> observer_tokens_; |
39 views::BubbleDialogDelegateView* bubble_; | 45 views::BubbleDialogDelegateView* bubble_; |
40 CGFloat horizontal_offset_; // Offset from the left or right. | 46 CGFloat horizontal_offset_; // Offset from the left or right. |
41 CGFloat vertical_offset_; // Offset from the top. | 47 CGFloat vertical_offset_; // Offset from the top. |
42 | 48 |
49 // The omnibox decoration that |bubble_| is anchored to. | |
50 LocationBarDecoration* decoration_; | |
51 | |
43 DISALLOW_COPY_AND_ASSIGN(BubbleAnchorHelper); | 52 DISALLOW_COPY_AND_ASSIGN(BubbleAnchorHelper); |
44 }; | 53 }; |
45 | 54 |
46 } // namespace | 55 } // namespace |
47 | 56 |
48 void KeepBubbleAnchored(views::BubbleDialogDelegateView* bubble) { | 57 LocationBarDecoration* GetManagePasswordDecoration( |
49 new BubbleAnchorHelper(bubble); | 58 views::BubbleDialogDelegateView* bubble) { |
59 LocationBarViewMac* locationBarBridge = | |
tapted
2017/05/16 07:39:37
nit: locationBarBridge -> location_bar (camel cas
spqchan
2017/05/17 01:39:39
Done.
| |
60 [[[bubble->parent_window() window] windowController] locationBarBridge]; | |
tapted
2017/05/16 07:39:37
I don't think this will compile in the 10.11 or 10
spqchan
2017/05/17 01:39:39
Done.
| |
61 return locationBarBridge ? locationBarBridge->manage_passwords_decoration() | |
62 : nullptr; | |
50 } | 63 } |
51 | 64 |
52 BubbleAnchorHelper::BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble) | 65 LocationBarDecoration* GetStarDecoration( |
53 : observer_tokens_([[NSMutableArray alloc] init]), bubble_(bubble) { | 66 views::BubbleDialogDelegateView* bubble) { |
67 LocationBarViewMac* locationBarBridge = | |
68 [[[bubble->parent_window() window] windowController] locationBarBridge]; | |
69 return locationBarBridge ? locationBarBridge->star_decoration() : nullptr; | |
70 } | |
71 | |
72 LocationBarDecoration* GetPageInfoDecoration( | |
73 views::BubbleDialogDelegateView* bubble) { | |
74 LocationBarViewMac* locationBarBridge = | |
75 [[[bubble->parent_window() window] windowController] locationBarBridge]; | |
76 return locationBarBridge ? locationBarBridge->GetPageInfoDecoration() | |
77 : nullptr; | |
78 } | |
79 | |
80 void KeepBubbleAnchored(views::BubbleDialogDelegateView* bubble, | |
81 LocationBarDecoration* decoration) { | |
82 new BubbleAnchorHelper(bubble, decoration); | |
83 } | |
84 | |
85 BubbleAnchorHelper::BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble, | |
86 LocationBarDecoration* decoration) | |
87 : observer_tokens_([[NSMutableArray alloc] init]), | |
88 bubble_(bubble), | |
89 decoration_(decoration) { | |
54 DCHECK(bubble->GetWidget()); | 90 DCHECK(bubble->GetWidget()); |
55 DCHECK(bubble->parent_window()); | 91 DCHECK(bubble->parent_window()); |
56 bubble->GetWidget()->AddObserver(this); | 92 bubble->GetWidget()->AddObserver(this); |
57 | 93 |
94 if (decoration_) | |
95 decoration_->SetActive(true); | |
96 | |
58 NSRect parent_frame = [[bubble->parent_window() window] frame]; | 97 NSRect parent_frame = [[bubble->parent_window() window] frame]; |
59 NSRect bubble_frame = [bubble->GetWidget()->GetNativeWindow() frame]; | 98 NSRect bubble_frame = [bubble->GetWidget()->GetNativeWindow() frame]; |
60 | 99 |
61 // Note: when anchored on the right, this doesn't support changes to the | 100 // Note: when anchored on the right, this doesn't support changes to the |
62 // bubble size, just the parent size. | 101 // bubble size, just the parent size. |
63 horizontal_offset_ = | 102 horizontal_offset_ = |
64 (IsMinXFixed() ? NSMinX(parent_frame) : NSMaxX(parent_frame)) - | 103 (IsMinXFixed() ? NSMinX(parent_frame) : NSMaxX(parent_frame)) - |
65 NSMinX(bubble_frame); | 104 NSMinX(bubble_frame); |
66 vertical_offset_ = NSMaxY(parent_frame) - NSMinY(bubble_frame); | 105 vertical_offset_ = NSMaxY(parent_frame) - NSMinY(bubble_frame); |
67 | 106 |
(...skipping 27 matching lines...) Expand all Loading... | |
95 bubble_frame.origin.x = NSMinX(parent_frame) - horizontal_offset_; | 134 bubble_frame.origin.x = NSMinX(parent_frame) - horizontal_offset_; |
96 else | 135 else |
97 bubble_frame.origin.x = NSMaxX(parent_frame) - horizontal_offset_; | 136 bubble_frame.origin.x = NSMaxX(parent_frame) - horizontal_offset_; |
98 bubble_frame.origin.y = NSMaxY(parent_frame) - vertical_offset_; | 137 bubble_frame.origin.y = NSMaxY(parent_frame) - vertical_offset_; |
99 [bubble_->GetWidget()->GetNativeWindow() setFrame:bubble_frame | 138 [bubble_->GetWidget()->GetNativeWindow() setFrame:bubble_frame |
100 display:YES | 139 display:YES |
101 animate:NO]; | 140 animate:NO]; |
102 } | 141 } |
103 | 142 |
104 void BubbleAnchorHelper::OnWidgetDestroying(views::Widget* widget) { | 143 void BubbleAnchorHelper::OnWidgetDestroying(views::Widget* widget) { |
144 if (decoration_) | |
tapted
2017/05/16 07:39:37
This raises a new lifetime issue that didn't previ
spqchan
2017/05/17 01:39:39
Done. Are there any other steps that we could perh
| |
145 decoration_->SetActive(false); | |
105 widget->RemoveObserver(this); | 146 widget->RemoveObserver(this); |
106 for (id token in observer_tokens_.get()) | 147 for (id token in observer_tokens_.get()) |
107 [[NSNotificationCenter defaultCenter] removeObserver:token]; | 148 [[NSNotificationCenter defaultCenter] removeObserver:token]; |
108 delete this; | 149 delete this; |
109 } | 150 } |
OLD | NEW |