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 #include <stddef.h> | 8 #include <stddef.h> |
9 #include <stdint.h> | 9 #include <stdint.h> |
10 | 10 |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 in_fullscreen_transition_(false), | 286 in_fullscreen_transition_(false), |
287 window_visible_(false), | 287 window_visible_(false), |
288 wants_to_be_visible_(false) { | 288 wants_to_be_visible_(false) { |
289 SetupDragEventMonitor(); | 289 SetupDragEventMonitor(); |
290 DCHECK(parent); | 290 DCHECK(parent); |
291 window_delegate_.reset( | 291 window_delegate_.reset( |
292 [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]); | 292 [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]); |
293 } | 293 } |
294 | 294 |
295 BridgedNativeWidget::~BridgedNativeWidget() { | 295 BridgedNativeWidget::~BridgedNativeWidget() { |
296 RemoveOrDestroyChildren(); | 296 bool close_window = false; |
297 DCHECK(child_windows_.empty()); | |
298 SetFocusManager(NULL); | |
299 SetRootView(NULL); | |
300 DestroyCompositor(); | |
301 if ([window_ delegate]) { | 297 if ([window_ delegate]) { |
302 // If the delegate is still set on a modal dialog, it means it was not | 298 // If the delegate is still set on a modal dialog, it means it was not |
303 // closed via [NSApplication endSheet:]. This is probably OK if the widget | 299 // closed via [NSApplication endSheet:]. This is probably OK if the widget |
304 // was never shown. But Cocoa ignores close() calls on open sheets. Calling | 300 // was never shown. But Cocoa ignores close() calls on open sheets. Calling |
305 // endSheet: here would work, but it messes up assumptions elsewhere. E.g. | 301 // endSheet: here would work, but it messes up assumptions elsewhere. E.g. |
306 // DialogClientView assumes its delegate is alive when closing, which isn't | 302 // DialogClientView assumes its delegate is alive when closing, which isn't |
307 // true after endSheet: synchronously calls OnNativeWidgetDestroyed(). | 303 // true after endSheet: synchronously calls OnNativeWidgetDestroyed(). |
308 // So ban it. Modal dialogs should be closed via Widget::Close(). | 304 // So ban it. Modal dialogs should be closed via Widget::Close(). |
309 DCHECK(!native_widget_mac_->IsWindowModalSheet()); | 305 DCHECK(!native_widget_mac_->IsWindowModalSheet()); |
310 | 306 |
311 // If the delegate is still set, it means OnWindowWillClose has not been | 307 // If the delegate is still set, it means OnWindowWillClose() has not been |
312 // called and the window is still open. Calling -[NSWindow close] will | 308 // called and the window is still open. Usually, -[NSWindow close] would |
313 // synchronously call OnWindowWillClose and notify NativeWidgetMac. | 309 // synchronously call OnWindowWillClose() which removes the delegate and |
| 310 // notifies NativeWidgetMac, which then calls this with a nil delegate. |
| 311 // For other teardown flows (e.g. Widget::WIDGET_OWNS_NATIVE_WIDGET or |
| 312 // Widget::CloseNow()) the delegate must first be cleared to avoid AppKit |
| 313 // calling back into the bridge. This means OnWindowWillClose() needs to be |
| 314 // invoked manually, which is done below. |
| 315 // Note that if the window has children it can't be closed until the |
| 316 // children are gone, but removing child windows calls into AppKit for the |
| 317 // parent window, so the delegate must be cleared first. |
| 318 [window_ setDelegate:nil]; |
| 319 close_window = true; |
| 320 } |
| 321 |
| 322 RemoveOrDestroyChildren(); |
| 323 DCHECK(child_windows_.empty()); |
| 324 SetFocusManager(nullptr); |
| 325 SetRootView(nullptr); |
| 326 DestroyCompositor(); |
| 327 |
| 328 if (close_window) { |
| 329 OnWindowWillClose(); |
314 [window_ close]; | 330 [window_ close]; |
315 } | 331 } |
316 DCHECK(![window_ delegate]); | |
317 } | 332 } |
318 | 333 |
319 void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window, | 334 void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window, |
320 const Widget::InitParams& params) { | 335 const Widget::InitParams& params) { |
321 widget_type_ = params.type; | 336 widget_type_ = params.type; |
322 | 337 |
323 DCHECK(!window_); | 338 DCHECK(!window_); |
324 window_.swap(window); | 339 window_.swap(window); |
325 [window_ setDelegate:window_delegate_]; | 340 [window_ setDelegate:window_delegate_]; |
326 | 341 |
(...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1211 [bridged_view_ setMouseDownCanMoveWindow:draggable]; | 1226 [bridged_view_ setMouseDownCanMoveWindow:draggable]; |
1212 // AppKit will not update its cache of mouseDownCanMoveWindow unless something | 1227 // AppKit will not update its cache of mouseDownCanMoveWindow unless something |
1213 // changes. Previously we tried adding an NSView and removing it, but for some | 1228 // changes. Previously we tried adding an NSView and removing it, but for some |
1214 // reason it required reposting the mouse-down event, and didn't always work. | 1229 // reason it required reposting the mouse-down event, and didn't always work. |
1215 // Calling the below seems to be an effective solution. | 1230 // Calling the below seems to be an effective solution. |
1216 [window_ setMovableByWindowBackground:NO]; | 1231 [window_ setMovableByWindowBackground:NO]; |
1217 [window_ setMovableByWindowBackground:YES]; | 1232 [window_ setMovableByWindowBackground:YES]; |
1218 } | 1233 } |
1219 | 1234 |
1220 } // namespace views | 1235 } // namespace views |
OLD | NEW |