| 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" |
| 15 #include "ui/gfx/mac/coordinate_conversion.h" |
| 10 #include "ui/views/bubble/bubble_dialog_delegate.h" | 16 #include "ui/views/bubble/bubble_dialog_delegate.h" |
| 11 #include "ui/views/widget/widget_observer.h" | 17 #include "ui/views/widget/widget_observer.h" |
| 12 | 18 |
| 13 namespace { | 19 namespace { |
| 14 | 20 |
| 15 // Self-deleting object that hosts Objective-C observers watching for parent | 21 // Self-deleting object that hosts Objective-C observers watching for parent |
| 16 // window resizes to reposition a bubble Widget. Deletes itself when the bubble | 22 // window resizes to reposition a bubble Widget. Deletes itself when the bubble |
| 17 // Widget closes. | 23 // Widget closes. |
| 18 class BubbleAnchorHelper : public views::WidgetObserver { | 24 class BubbleAnchorHelper : public views::WidgetObserver { |
| 19 public: | 25 public: |
| 20 explicit BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble); | 26 BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble, |
| 27 LocationBarDecoration* decoration); |
| 21 | 28 |
| 22 private: | 29 private: |
| 23 // Observe |name| on the bubble parent window with a block to call ReAnchor(). | 30 // Observe |name| on the bubble parent window with a block to call ReAnchor(). |
| 24 void Observe(NSString* name); | 31 void Observe(NSString* name); |
| 25 | 32 |
| 26 // Whether offset from the left of the parent window is fixed. | 33 // Whether offset from the left of the parent window is fixed. |
| 27 bool IsMinXFixed() const { | 34 bool IsMinXFixed() const { |
| 28 return views::BubbleBorder::is_arrow_on_left(bubble_->arrow()); | 35 return views::BubbleBorder::is_arrow_on_left(bubble_->arrow()); |
| 29 } | 36 } |
| 30 | 37 |
| 31 // Re-positions |bubble_| so that the offset to the parent window at | 38 // Re-positions |bubble_| so that the offset to the parent window at |
| 32 // construction time is preserved. | 39 // construction time is preserved. |
| 33 void ReAnchor(); | 40 void ReAnchor(); |
| 34 | 41 |
| 35 // WidgetObserver: | 42 // WidgetObserver: |
| 36 void OnWidgetDestroying(views::Widget* widget) override; | 43 void OnWidgetDestroying(views::Widget* widget) override; |
| 37 | 44 |
| 38 base::scoped_nsobject<NSMutableArray> observer_tokens_; | 45 base::scoped_nsobject<NSMutableArray> observer_tokens_; |
| 39 views::BubbleDialogDelegateView* bubble_; | 46 views::BubbleDialogDelegateView* bubble_; |
| 40 CGFloat horizontal_offset_; // Offset from the left or right. | 47 CGFloat horizontal_offset_; // Offset from the left or right. |
| 41 CGFloat vertical_offset_; // Offset from the top. | 48 CGFloat vertical_offset_; // Offset from the top. |
| 42 | 49 |
| 50 // The omnibox decoration that |bubble_| is anchored to. |
| 51 // Weak. The lifetime is tied to the controller of the bubble's parent |
| 52 // window, which owns a LocationBarViewMac that directly owns |decoration_|. |
| 53 LocationBarDecoration* decoration_; |
| 54 |
| 43 DISALLOW_COPY_AND_ASSIGN(BubbleAnchorHelper); | 55 DISALLOW_COPY_AND_ASSIGN(BubbleAnchorHelper); |
| 44 }; | 56 }; |
| 45 | 57 |
| 58 LocationBarViewMac* GetLocationBarView( |
| 59 views::BubbleDialogDelegateView* bubble) { |
| 60 BrowserWindowController* window_controller = [BrowserWindowController |
| 61 browserWindowControllerForWindow:[bubble->parent_window() window]]; |
| 62 return window_controller ? [window_controller locationBarBridge] : nullptr; |
| 63 } |
| 64 |
| 46 } // namespace | 65 } // namespace |
| 47 | 66 |
| 48 void KeepBubbleAnchored(views::BubbleDialogDelegateView* bubble) { | 67 LocationBarDecoration* GetManagePasswordDecoration( |
| 49 new BubbleAnchorHelper(bubble); | 68 views::BubbleDialogDelegateView* bubble) { |
| 69 LocationBarViewMac* location_bar = GetLocationBarView(bubble); |
| 70 return location_bar ? location_bar->manage_passwords_decoration() : nullptr; |
| 50 } | 71 } |
| 51 | 72 |
| 52 BubbleAnchorHelper::BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble) | 73 LocationBarDecoration* GetStarDecoration( |
| 53 : observer_tokens_([[NSMutableArray alloc] init]), bubble_(bubble) { | 74 views::BubbleDialogDelegateView* bubble) { |
| 75 LocationBarViewMac* location_bar = GetLocationBarView(bubble); |
| 76 return location_bar ? location_bar->star_decoration() : nullptr; |
| 77 } |
| 78 |
| 79 LocationBarDecoration* GetPageInfoDecoration( |
| 80 views::BubbleDialogDelegateView* bubble) { |
| 81 LocationBarViewMac* location_bar = GetLocationBarView(bubble); |
| 82 return location_bar ? location_bar->GetPageInfoDecoration() : nullptr; |
| 83 } |
| 84 |
| 85 LocationBarDecoration* GetContentSettingDecoration( |
| 86 views::BubbleDialogDelegateView* bubble, |
| 87 const gfx::Point& anchor) { |
| 88 LocationBarViewMac* location_bar = GetLocationBarView(bubble); |
| 89 NSPoint point = ScreenPointToNSPoint(anchor); |
| 90 return location_bar ? location_bar->GetContentSettingDecoration(point) |
| 91 : nullptr; |
| 92 } |
| 93 |
| 94 void KeepBubbleAnchored(views::BubbleDialogDelegateView* bubble, |
| 95 LocationBarDecoration* decoration) { |
| 96 new BubbleAnchorHelper(bubble, decoration); |
| 97 } |
| 98 |
| 99 BubbleAnchorHelper::BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble, |
| 100 LocationBarDecoration* decoration) |
| 101 : observer_tokens_([[NSMutableArray alloc] init]), |
| 102 bubble_(bubble), |
| 103 decoration_(decoration) { |
| 54 DCHECK(bubble->GetWidget()); | 104 DCHECK(bubble->GetWidget()); |
| 55 DCHECK(bubble->parent_window()); | 105 DCHECK(bubble->parent_window()); |
| 56 bubble->GetWidget()->AddObserver(this); | 106 bubble->GetWidget()->AddObserver(this); |
| 57 | 107 |
| 108 if (decoration_) |
| 109 decoration_->SetActive(true); |
| 110 |
| 58 NSRect parent_frame = [[bubble->parent_window() window] frame]; | 111 NSRect parent_frame = [[bubble->parent_window() window] frame]; |
| 59 NSRect bubble_frame = [bubble->GetWidget()->GetNativeWindow() frame]; | 112 NSRect bubble_frame = [bubble->GetWidget()->GetNativeWindow() frame]; |
| 60 | 113 |
| 61 // Note: when anchored on the right, this doesn't support changes to the | 114 // Note: when anchored on the right, this doesn't support changes to the |
| 62 // bubble size, just the parent size. | 115 // bubble size, just the parent size. |
| 63 horizontal_offset_ = | 116 horizontal_offset_ = |
| 64 (IsMinXFixed() ? NSMinX(parent_frame) : NSMaxX(parent_frame)) - | 117 (IsMinXFixed() ? NSMinX(parent_frame) : NSMaxX(parent_frame)) - |
| 65 NSMinX(bubble_frame); | 118 NSMinX(bubble_frame); |
| 66 vertical_offset_ = NSMaxY(parent_frame) - NSMinY(bubble_frame); | 119 vertical_offset_ = NSMaxY(parent_frame) - NSMinY(bubble_frame); |
| 67 | 120 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 95 bubble_frame.origin.x = NSMinX(parent_frame) - horizontal_offset_; | 148 bubble_frame.origin.x = NSMinX(parent_frame) - horizontal_offset_; |
| 96 else | 149 else |
| 97 bubble_frame.origin.x = NSMaxX(parent_frame) - horizontal_offset_; | 150 bubble_frame.origin.x = NSMaxX(parent_frame) - horizontal_offset_; |
| 98 bubble_frame.origin.y = NSMaxY(parent_frame) - vertical_offset_; | 151 bubble_frame.origin.y = NSMaxY(parent_frame) - vertical_offset_; |
| 99 [bubble_->GetWidget()->GetNativeWindow() setFrame:bubble_frame | 152 [bubble_->GetWidget()->GetNativeWindow() setFrame:bubble_frame |
| 100 display:YES | 153 display:YES |
| 101 animate:NO]; | 154 animate:NO]; |
| 102 } | 155 } |
| 103 | 156 |
| 104 void BubbleAnchorHelper::OnWidgetDestroying(views::Widget* widget) { | 157 void BubbleAnchorHelper::OnWidgetDestroying(views::Widget* widget) { |
| 158 // NativeWidgetMac guarantees that a child's OnWidgetDestroying() is invoked |
| 159 // before the parent NSWindow has closed. |
| 160 if (decoration_) |
| 161 decoration_->SetActive(false); |
| 105 widget->RemoveObserver(this); | 162 widget->RemoveObserver(this); |
| 106 for (id token in observer_tokens_.get()) | 163 for (id token in observer_tokens_.get()) |
| 107 [[NSNotificationCenter defaultCenter] removeObserver:token]; | 164 [[NSNotificationCenter defaultCenter] removeObserver:token]; |
| 108 delete this; | 165 delete this; |
| 109 } | 166 } |
| OLD | NEW |