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