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

Side by Side Diff: ui/views/cocoa/bridged_native_widget.mm

Issue 927233003: MacViews: Fix positioning of top-level Widgets with parents (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@20150129-MacViews-Bringup5
Patch Set: Added comment to BridgedNativeWidget Created 5 years, 9 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
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
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
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
OLDNEW
« no previous file with comments | « ui/views/cocoa/bridged_native_widget.h ('k') | ui/views/cocoa/bridged_native_widget_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698