OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 #import "ui/views/cocoa/bridged_native_widget.h" | 5 #import "ui/views/cocoa/bridged_native_widget.h" |
6 | 6 |
7 #import <objc/runtime.h> | 7 #import <objc/runtime.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/mac/mac_util.h" | 10 #include "base/mac/mac_util.h" |
(...skipping 20 matching lines...) Expand all Loading... | |
31 | 31 |
32 int kWindowPropertiesKey; | 32 int kWindowPropertiesKey; |
33 | 33 |
34 float GetDeviceScaleFactorFromView(NSView* view) { | 34 float GetDeviceScaleFactorFromView(NSView* view) { |
35 gfx::Display display = | 35 gfx::Display display = |
36 gfx::Screen::GetScreenFor(view)->GetDisplayNearestWindow(view); | 36 gfx::Screen::GetScreenFor(view)->GetDisplayNearestWindow(view); |
37 DCHECK(display.is_valid()); | 37 DCHECK(display.is_valid()); |
38 return display.device_scale_factor(); | 38 return display.device_scale_factor(); |
39 } | 39 } |
40 | 40 |
41 // Returns true if bounds passed to window in SetBounds should be treated as | |
42 // though they are in screen coordinates. | |
43 bool PositionWindowInScreenCoordinates(views::Widget* widget, | |
44 views::Widget::InitParams::Type type) { | |
45 // Replicate the logic in desktop_aura/desktop_screen_position_client.cc. | |
46 if (type == views::Widget::InitParams::TYPE_POPUP) | |
Andre
2015/02/23 18:27:08
The aura version of this checks for ui::wm::WINDOW
tapted
2015/02/24 00:14:32
ooh - good catch! Fixed.
used GetAuraWindowTypeFo
| |
47 return true; | |
48 | |
49 return widget && widget->is_top_level(); | |
50 } | |
51 | |
41 } // namespace | 52 } // namespace |
42 | 53 |
43 namespace views { | 54 namespace views { |
44 | 55 |
45 BridgedNativeWidget::BridgedNativeWidget(NativeWidgetMac* parent) | 56 BridgedNativeWidget::BridgedNativeWidget(NativeWidgetMac* parent) |
46 : native_widget_mac_(parent), | 57 : native_widget_mac_(parent), |
47 focus_manager_(NULL), | 58 focus_manager_(nullptr), |
59 widget_type_(Widget::InitParams::TYPE_WINDOW), // Updated in Init(). | |
48 parent_(nullptr), | 60 parent_(nullptr), |
49 target_fullscreen_state_(false), | 61 target_fullscreen_state_(false), |
50 in_fullscreen_transition_(false), | 62 in_fullscreen_transition_(false), |
51 window_visible_(false), | 63 window_visible_(false), |
52 wants_to_be_visible_(false) { | 64 wants_to_be_visible_(false) { |
53 DCHECK(parent); | 65 DCHECK(parent); |
54 window_delegate_.reset( | 66 window_delegate_.reset( |
55 [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]); | 67 [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]); |
56 } | 68 } |
57 | 69 |
58 BridgedNativeWidget::~BridgedNativeWidget() { | 70 BridgedNativeWidget::~BridgedNativeWidget() { |
59 RemoveOrDestroyChildren(); | 71 RemoveOrDestroyChildren(); |
60 DCHECK(child_windows_.empty()); | 72 DCHECK(child_windows_.empty()); |
61 SetFocusManager(NULL); | 73 SetFocusManager(NULL); |
62 SetRootView(NULL); | 74 SetRootView(NULL); |
63 DestroyCompositor(); | 75 DestroyCompositor(); |
64 if ([window_ delegate]) { | 76 if ([window_ delegate]) { |
65 // If the delegate is still set, it means OnWindowWillClose has not been | 77 // If the delegate is still set, it means OnWindowWillClose has not been |
66 // called and the window is still open. Calling -[NSWindow close] will | 78 // called and the window is still open. Calling -[NSWindow close] will |
67 // synchronously call OnWindowWillClose and notify NativeWidgetMac. | 79 // synchronously call OnWindowWillClose and notify NativeWidgetMac. |
68 [window_ close]; | 80 [window_ close]; |
69 } | 81 } |
70 DCHECK(![window_ delegate]); | 82 DCHECK(![window_ delegate]); |
71 } | 83 } |
72 | 84 |
73 void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window, | 85 void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window, |
74 const Widget::InitParams& params) { | 86 const Widget::InitParams& params) { |
87 widget_type_ = params.type; | |
88 | |
75 DCHECK(!window_); | 89 DCHECK(!window_); |
76 window_.swap(window); | 90 window_.swap(window); |
77 [window_ setDelegate:window_delegate_]; | 91 [window_ setDelegate:window_delegate_]; |
78 | 92 |
79 // Register for application hide notifications so that visibility can be | 93 // Register for application hide notifications so that visibility can be |
80 // properly tracked. This is not done in the delegate so that the lifetime is | 94 // properly tracked. This is not done in the delegate so that the lifetime is |
81 // tied to the C++ object, rather than the delegate (which may be reference | 95 // tied to the C++ object, rather than the delegate (which may be reference |
82 // counted). This is required since the application hides do not send an | 96 // counted). This is required since the application hides do not send an |
83 // orderOut: to individual windows. Unhide, however, does send an order | 97 // orderOut: to individual windows. Unhide, however, does send an order |
84 // message. | 98 // message. |
(...skipping 14 matching lines...) Expand all Loading... | |
99 BridgedNativeWidget* parent = | 113 BridgedNativeWidget* parent = |
100 NativeWidgetMac::GetBridgeForNativeWindow([params.parent window]); | 114 NativeWidgetMac::GetBridgeForNativeWindow([params.parent window]); |
101 // The parent could be an NSWindow without an associated Widget. That could | 115 // The parent could be an NSWindow without an associated Widget. That could |
102 // work by observing NSWindowWillCloseNotification, but for now it's not | 116 // work by observing NSWindowWillCloseNotification, but for now it's not |
103 // supported, and there might not be a use-case for that. | 117 // supported, and there might not be a use-case for that. |
104 CHECK(parent); | 118 CHECK(parent); |
105 parent_ = parent; | 119 parent_ = parent; |
106 parent->child_windows_.push_back(this); | 120 parent->child_windows_.push_back(this); |
107 } | 121 } |
108 | 122 |
123 // Set a meaningful initial bounds. Note that except for frameless widgets | |
124 // with no WidgetDelegate, the bounds will be set again by Widget after | |
125 // initializing the non-client view. In the former case, if bounds were not | |
126 // set at all, the creator of the Widget is expected to call SetBounds() | |
127 // before calling Widget::Show() to avoid a kWindowSizeDeterminedLater-sized | |
128 // (i.e. 1x1) window appearing. | |
129 if (!params.bounds.IsEmpty()) { | |
130 SetBounds(params.bounds); | |
131 } else { | |
132 // If a position is set, but no size, complain. Otherwise, a 1x1 window | |
133 // would appear there, which might be unexpected. | |
134 DCHECK(params.bounds.origin().IsOrigin()) | |
135 << "Zero-sized windows not supported on Mac."; | |
136 } | |
137 | |
109 // Widgets for UI controls (usually layered above web contents) start visible. | 138 // Widgets for UI controls (usually layered above web contents) start visible. |
110 if (params.type == Widget::InitParams::TYPE_CONTROL) | 139 if (params.type == Widget::InitParams::TYPE_CONTROL) |
111 SetVisibilityState(SHOW_INACTIVE); | 140 SetVisibilityState(SHOW_INACTIVE); |
112 } | 141 } |
113 | 142 |
114 void BridgedNativeWidget::SetFocusManager(FocusManager* focus_manager) { | 143 void BridgedNativeWidget::SetFocusManager(FocusManager* focus_manager) { |
115 if (focus_manager_ == focus_manager) | 144 if (focus_manager_ == focus_manager) |
116 return; | 145 return; |
117 | 146 |
118 if (focus_manager_) | 147 if (focus_manager_) |
119 focus_manager_->RemoveFocusChangeListener(this); | 148 focus_manager_->RemoveFocusChangeListener(this); |
120 | 149 |
121 if (focus_manager) | 150 if (focus_manager) |
122 focus_manager->AddFocusChangeListener(this); | 151 focus_manager->AddFocusChangeListener(this); |
123 | 152 |
124 focus_manager_ = focus_manager; | 153 focus_manager_ = focus_manager; |
125 } | 154 } |
126 | 155 |
127 void BridgedNativeWidget::SetBounds(const gfx::Rect& new_bounds) { | 156 void BridgedNativeWidget::SetBounds(const gfx::Rect& new_bounds) { |
157 // A contentRect with zero width or height is a banned practice in ChromeMac, | |
158 // due to unpredictable OSX treatment. | |
159 DCHECK(!new_bounds.IsEmpty()) << "Zero-sized windows not supported on Mac"; | |
160 | |
128 gfx::Rect actual_new_bounds(new_bounds); | 161 gfx::Rect actual_new_bounds(new_bounds); |
129 if (parent_) | 162 |
163 if (parent_ && | |
164 !PositionWindowInScreenCoordinates(native_widget_mac_->GetWidget(), | |
165 widget_type_)) | |
130 actual_new_bounds.Offset(parent_->GetRestoredBounds().OffsetFromOrigin()); | 166 actual_new_bounds.Offset(parent_->GetRestoredBounds().OffsetFromOrigin()); |
131 | 167 |
132 [window_ setFrame:gfx::ScreenRectToNSRect(actual_new_bounds) | 168 [window_ setFrame:gfx::ScreenRectToNSRect(actual_new_bounds) |
133 display:YES | 169 display:YES |
134 animate:NO]; | 170 animate:NO]; |
135 } | 171 } |
136 | 172 |
137 void BridgedNativeWidget::SetRootView(views::View* view) { | 173 void BridgedNativeWidget::SetRootView(views::View* view) { |
138 if (view == [bridged_view_ hostedView]) | 174 if (view == [bridged_view_ hostedView]) |
139 return; | 175 return; |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
695 window_, &kWindowPropertiesKey); | 731 window_, &kWindowPropertiesKey); |
696 if (!properties) { | 732 if (!properties) { |
697 properties = [NSMutableDictionary dictionary]; | 733 properties = [NSMutableDictionary dictionary]; |
698 objc_setAssociatedObject(window_, &kWindowPropertiesKey, | 734 objc_setAssociatedObject(window_, &kWindowPropertiesKey, |
699 properties, OBJC_ASSOCIATION_RETAIN); | 735 properties, OBJC_ASSOCIATION_RETAIN); |
700 } | 736 } |
701 return properties; | 737 return properties; |
702 } | 738 } |
703 | 739 |
704 } // namespace views | 740 } // namespace views |
OLD | NEW |