Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: chrome/browser/ui/cocoa/bubble_anchor_helper_views.mm

Issue 2586373003: MacViews: Allow toolkit-views for "Global Error" bubbles. (Closed)
Patch Set: addObserverForName Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/cocoa/bubble_anchor_helper_views.h"
6
7 #import <Cocoa/Cocoa.h>
8
9 #import "base/mac/scoped_nsobject.h"
10 #include "ui/views/bubble/bubble_dialog_delegate.h"
11 #include "ui/views/widget/widget_observer.h"
12
13 namespace {
14
15 // Self-deleting object that hosts Objective-C observers watching for parent
16 // window resizes to reposition a bubble Widget. Deletes itself when the bubble
17 // Widget closes.
18 class BubbleAnchorHelper : public views::WidgetObserver {
19 public:
20 explicit BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble);
21
22 private:
23 // Observe |name| on the bubble parent window with a block to call ReAnchor().
24 void Observe(NSString* name);
25
26 // Whether offset from the left of the parent window is fixed.
27 bool IsMinXFixed() const {
28 return views::BubbleBorder::is_arrow_on_left(bubble_->arrow());
29 }
30
31 // Re-positions |bubble_| so that the offset to the parent window at
32 // construction time is preserved.
33 void ReAnchor();
34
35 // WidgetObserver:
36 void OnWidgetDestroying(views::Widget* widget) override;
37
38 base::scoped_nsobject<NSMutableArray> observer_tokens_;
39 views::BubbleDialogDelegateView* bubble_;
40 CGFloat horizontal_offset_; // Offset from the left or right.
41 CGFloat vertical_offset_; // Offset from the top.
42
43 DISALLOW_COPY_AND_ASSIGN(BubbleAnchorHelper);
44 };
45
46 } // namespace
47
48 void KeepBubbleAnchored(views::BubbleDialogDelegateView* bubble) {
49 new BubbleAnchorHelper(bubble);
50 }
51
52 BubbleAnchorHelper::BubbleAnchorHelper(views::BubbleDialogDelegateView* bubble)
53 : observer_tokens_([[NSMutableArray alloc] init]), bubble_(bubble) {
54 DCHECK(bubble->GetWidget());
55 DCHECK(bubble->parent_window());
56 bubble->GetWidget()->AddObserver(this);
57
58 NSRect parent_frame = [[bubble->parent_window() window] frame];
59 NSRect bubble_frame = [bubble->GetWidget()->GetNativeWindow() frame];
60
61 // Note: when anchored on the right, this doesn't support changes to the
62 // bubble size, just the parent size.
63 horizontal_offset_ =
64 (IsMinXFixed() ? NSMinX(parent_frame) : NSMaxX(parent_frame)) -
65 NSMinX(bubble_frame);
66 vertical_offset_ = NSMaxY(parent_frame) - NSMinY(bubble_frame);
67
68 Observe(NSWindowDidEnterFullScreenNotification);
69 Observe(NSWindowDidExitFullScreenNotification);
70 Observe(NSWindowDidResizeNotification);
71
72 // Also monitor move. Note that for user-initiated window moves this is not
73 // necessary: the bubble's child window status keeps the position pinned to
74 // the parent during the move (which is handy since AppKit doesn't send out
75 // notifications until the move completes). Programmatic -[NSWindow
76 // setFrame:..] calls, however, do not update child window positions for us.
77 Observe(NSWindowDidMoveNotification);
78 }
79
80 void BubbleAnchorHelper::Observe(NSString* name) {
81 NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
82 id token = [center addObserverForName:name
83 object:[bubble_->parent_window() window]
84 queue:nil
85 usingBlock:^(NSNotification* notification) {
86 ReAnchor();
87 }];
88 [observer_tokens_ addObject:token];
89 }
90
91 void BubbleAnchorHelper::ReAnchor() {
92 NSRect bubble_frame = [bubble_->GetWidget()->GetNativeWindow() frame];
93 NSRect parent_frame = [[bubble_->parent_window() window] frame];
94 if (IsMinXFixed())
95 bubble_frame.origin.x = NSMinX(parent_frame) - horizontal_offset_;
96 else
97 bubble_frame.origin.x = NSMaxX(parent_frame) - horizontal_offset_;
98 bubble_frame.origin.y = NSMaxY(parent_frame) - vertical_offset_;
99 [bubble_->GetWidget()->GetNativeWindow() setFrame:bubble_frame
100 display:YES
101 animate:NO];
102 }
103
104 void BubbleAnchorHelper::OnWidgetDestroying(views::Widget* widget) {
105 widget->RemoveObserver(this);
106 for (id token in observer_tokens_.get())
107 [[NSNotificationCenter defaultCenter] removeObserver:token];
108 delete this;
109 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/cocoa/bubble_anchor_helper_views.h ('k') | chrome/browser/ui/cocoa/bubble_anchor_helper_views_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698