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 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
335 in_fullscreen_transition_(false), | 335 in_fullscreen_transition_(false), |
336 window_visible_(false), | 336 window_visible_(false), |
337 wants_to_be_visible_(false) { | 337 wants_to_be_visible_(false) { |
338 SetupDragEventMonitor(); | 338 SetupDragEventMonitor(); |
339 DCHECK(parent); | 339 DCHECK(parent); |
340 window_delegate_.reset( | 340 window_delegate_.reset( |
341 [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]); | 341 [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]); |
342 } | 342 } |
343 | 343 |
344 BridgedNativeWidget::~BridgedNativeWidget() { | 344 BridgedNativeWidget::~BridgedNativeWidget() { |
345 bool close_window = false; | 345 // If the delegate is still set on a modal dialog, it means it was not |
346 if ([window_ delegate]) { | 346 // closed via [NSApplication endSheet:]. This is probably OK if the widget |
347 // If the delegate is still set on a modal dialog, it means it was not | 347 // was never shown. But Cocoa ignores close() calls on open sheets. Calling |
348 // closed via [NSApplication endSheet:]. This is probably OK if the widget | 348 // endSheet: here would work, but it messes up assumptions elsewhere. E.g. |
349 // was never shown. But Cocoa ignores close() calls on open sheets. Calling | 349 // DialogClientView assumes its delegate is alive when closing, which isn't |
350 // endSheet: here would work, but it messes up assumptions elsewhere. E.g. | 350 // true after endSheet: synchronously calls OnNativeWidgetDestroyed(). |
351 // DialogClientView assumes its delegate is alive when closing, which isn't | 351 // So ban it. Modal dialogs should be closed via Widget::Close(). |
352 // true after endSheet: synchronously calls OnNativeWidgetDestroyed(). | 352 DCHECK(!close_window_ || !native_widget_mac_->IsWindowModalSheet()); |
353 // So ban it. Modal dialogs should be closed via Widget::Close(). | |
354 DCHECK(!native_widget_mac_->IsWindowModalSheet()); | |
355 | 353 |
356 // If the delegate is still set, it means OnWindowWillClose() has not been | 354 [window_ setDelegate:nil]; |
357 // called and the window is still open. Usually, -[NSWindow close] would | |
358 // synchronously call OnWindowWillClose() which removes the delegate and | |
359 // notifies NativeWidgetMac, which then calls this with a nil delegate. | |
360 // For other teardown flows (e.g. Widget::WIDGET_OWNS_NATIVE_WIDGET or | |
361 // Widget::CloseNow()) the delegate must first be cleared to avoid AppKit | |
362 // calling back into the bridge. This means OnWindowWillClose() needs to be | |
363 // invoked manually, which is done below. | |
364 // Note that if the window has children it can't be closed until the | |
365 // children are gone, but removing child windows calls into AppKit for the | |
366 // parent window, so the delegate must be cleared first. | |
367 [window_ setDelegate:nil]; | |
368 close_window = true; | |
369 } | |
370 | |
371 RemoveOrDestroyChildren(); | 355 RemoveOrDestroyChildren(); |
372 DCHECK(child_windows_.empty()); | 356 DCHECK(child_windows_.empty()); |
373 SetFocusManager(nullptr); | 357 SetFocusManager(nullptr); |
374 SetRootView(nullptr); | 358 SetRootView(nullptr); |
375 DestroyCompositor(); | 359 DestroyCompositor(); |
376 | 360 |
377 if (close_window) { | 361 if (close_window_) { |
378 OnWindowWillClose(); | 362 OnWindowWillClose(); |
379 [window_ close]; | 363 [window_ close]; |
380 } | 364 } |
381 } | 365 } |
382 | 366 |
383 void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window, | 367 void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window, |
384 const Widget::InitParams& params) { | 368 const Widget::InitParams& params) { |
385 widget_type_ = params.type; | 369 widget_type_ = params.type; |
386 | 370 |
387 DCHECK(!window_); | 371 DCHECK(!window_); |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
700 // called via ~CocoaMouseCapture() upon the destruction of |mouse_capture_|. | 684 // called via ~CocoaMouseCapture() upon the destruction of |mouse_capture_|. |
701 // See crbug.com/622201. Also we do this before setting the delegate to nil, | 685 // See crbug.com/622201. Also we do this before setting the delegate to nil, |
702 // because this may lead to callbacks to bridge which rely on a valid | 686 // because this may lead to callbacks to bridge which rely on a valid |
703 // delegate. | 687 // delegate. |
704 ReleaseCapture(); | 688 ReleaseCapture(); |
705 | 689 |
706 if (parent_) { | 690 if (parent_) { |
707 parent_->RemoveChildWindow(this); | 691 parent_->RemoveChildWindow(this); |
708 parent_ = nullptr; | 692 parent_ = nullptr; |
709 } | 693 } |
710 [window_ setDelegate:nil]; | 694 close_window_ = false; |
711 [[NSNotificationCenter defaultCenter] removeObserver:window_delegate_]; | 695 [[NSNotificationCenter defaultCenter] removeObserver:window_delegate_]; |
712 native_widget_mac_->OnWindowWillClose(); | 696 native_widget_mac_->OnWindowWillClose(); |
tapted
2016/10/05 08:38:18
Is the problem just that NativeWidgetMac::OnWindow
| |
713 } | 697 } |
714 | 698 |
715 void BridgedNativeWidget::OnFullscreenTransitionStart( | 699 void BridgedNativeWidget::OnFullscreenTransitionStart( |
716 bool target_fullscreen_state) { | 700 bool target_fullscreen_state) { |
717 // Note: This can fail for fullscreen changes started externally, but a user | 701 // Note: This can fail for fullscreen changes started externally, but a user |
718 // shouldn't be able to do that if the window is invisible to begin with. | 702 // shouldn't be able to do that if the window is invisible to begin with. |
719 DCHECK(window_visible_); | 703 DCHECK(window_visible_); |
720 | 704 |
721 DCHECK_NE(target_fullscreen_state, target_fullscreen_state_); | 705 DCHECK_NE(target_fullscreen_state, target_fullscreen_state_); |
722 target_fullscreen_state_ = target_fullscreen_state; | 706 target_fullscreen_state_ = target_fullscreen_state; |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1390 [bridged_view_ setMouseDownCanMoveWindow:draggable]; | 1374 [bridged_view_ setMouseDownCanMoveWindow:draggable]; |
1391 // AppKit will not update its cache of mouseDownCanMoveWindow unless something | 1375 // AppKit will not update its cache of mouseDownCanMoveWindow unless something |
1392 // changes. Previously we tried adding an NSView and removing it, but for some | 1376 // changes. Previously we tried adding an NSView and removing it, but for some |
1393 // reason it required reposting the mouse-down event, and didn't always work. | 1377 // reason it required reposting the mouse-down event, and didn't always work. |
1394 // Calling the below seems to be an effective solution. | 1378 // Calling the below seems to be an effective solution. |
1395 [window_ setMovableByWindowBackground:NO]; | 1379 [window_ setMovableByWindowBackground:NO]; |
1396 [window_ setMovableByWindowBackground:YES]; | 1380 [window_ setMovableByWindowBackground:YES]; |
1397 } | 1381 } |
1398 | 1382 |
1399 } // namespace views | 1383 } // namespace views |
OLD | NEW |