| 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 |