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

Side by Side Diff: ui/views/widget/native_widget_mac.mm

Issue 2061693003: MacViews: Suppress visibility changes during an asynchronous close. Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Neater, but Linux, Windows disagree on WidgetTest.DesktopNativeWidgetVisibilityAfterCloseTest Created 4 years, 4 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
« no previous file with comments | « ui/views/widget/native_widget_mac.h ('k') | ui/views/widget/widget_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 #include "ui/views/widget/native_widget_mac.h" 5 #include "ui/views/widget/native_widget_mac.h"
6 6
7 #import <Cocoa/Cocoa.h> 7 #import <Cocoa/Cocoa.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
11 #import "base/mac/bind_objc_block.h"
12 #include "base/mac/foundation_util.h" 11 #include "base/mac/foundation_util.h"
13 #include "base/mac/scoped_nsobject.h" 12 #include "base/mac/scoped_nsobject.h"
14 #include "base/strings/sys_string_conversions.h" 13 #include "base/strings/sys_string_conversions.h"
15 #include "base/threading/thread_task_runner_handle.h"
16 #import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
17 #import "ui/base/cocoa/window_size_constants.h" 14 #import "ui/base/cocoa/window_size_constants.h"
18 #include "ui/gfx/font_list.h" 15 #include "ui/gfx/font_list.h"
19 #import "ui/gfx/mac/coordinate_conversion.h" 16 #import "ui/gfx/mac/coordinate_conversion.h"
20 #import "ui/gfx/mac/nswindow_frame_controls.h" 17 #import "ui/gfx/mac/nswindow_frame_controls.h"
21 #include "ui/native_theme/native_theme.h" 18 #include "ui/native_theme/native_theme.h"
22 #include "ui/native_theme/native_theme_mac.h" 19 #include "ui/native_theme/native_theme_mac.h"
23 #import "ui/views/cocoa/bridged_content_view.h" 20 #import "ui/views/cocoa/bridged_content_view.h"
24 #import "ui/views/cocoa/bridged_native_widget.h" 21 #import "ui/views/cocoa/bridged_native_widget.h"
25 #include "ui/views/cocoa/cocoa_mouse_capture.h" 22 #include "ui/views/cocoa/cocoa_mouse_capture.h"
26 #import "ui/views/cocoa/drag_drop_client_mac.h" 23 #import "ui/views/cocoa/drag_drop_client_mac.h"
27 #import "ui/views/cocoa/native_widget_mac_nswindow.h" 24 #import "ui/views/cocoa/native_widget_mac_nswindow.h"
28 #import "ui/views/cocoa/views_nswindow_delegate.h" 25 #import "ui/views/cocoa/views_nswindow_delegate.h"
29 #include "ui/views/widget/drop_helper.h" 26 #include "ui/views/widget/drop_helper.h"
30 #include "ui/views/widget/widget_delegate.h" 27 #include "ui/views/widget/widget_delegate.h"
31 #include "ui/views/window/native_frame_view.h" 28 #include "ui/views/window/native_frame_view.h"
32 29
33 // Self-owning animation delegate that starts a hide animation, then calls
34 // -[NSWindow close] when the animation ends, releasing itself.
35 @interface ViewsNSWindowCloseAnimator : NSObject<NSAnimationDelegate> {
36 @private
37 base::scoped_nsobject<NSWindow> window_;
38 base::scoped_nsobject<NSAnimation> animation_;
39 }
40
41 + (void)closeWindowWithAnimation:(NSWindow*)window;
42
43 @end
44
45 namespace views { 30 namespace views {
46 namespace { 31 namespace {
47 32
48 NSInteger StyleMaskForParams(const Widget::InitParams& params) { 33 NSInteger StyleMaskForParams(const Widget::InitParams& params) {
49 // If the Widget is modal, it will be displayed as a sheet. This works best if 34 // If the Widget is modal, it will be displayed as a sheet. This works best if
50 // it has NSTitledWindowMask. For example, with NSBorderlessWindowMask, the 35 // it has NSTitledWindowMask. For example, with NSBorderlessWindowMask, the
51 // parent window still accepts input. 36 // parent window still accepts input.
52 if (params.delegate && 37 if (params.delegate &&
53 params.delegate->GetModalType() == ui::MODAL_TYPE_WINDOW) 38 params.delegate->GetModalType() == ui::MODAL_TYPE_WINDOW)
54 return NSTitledWindowMask; 39 return NSTitledWindowMask;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 gfx::NativeWindow window) { 73 gfx::NativeWindow window) {
89 id<NSWindowDelegate> window_delegate = [window delegate]; 74 id<NSWindowDelegate> window_delegate = [window delegate];
90 if ([window_delegate respondsToSelector:@selector(nativeWidgetMac)]) { 75 if ([window_delegate respondsToSelector:@selector(nativeWidgetMac)]) {
91 ViewsNSWindowDelegate* delegate = 76 ViewsNSWindowDelegate* delegate =
92 base::mac::ObjCCastStrict<ViewsNSWindowDelegate>(window_delegate); 77 base::mac::ObjCCastStrict<ViewsNSWindowDelegate>(window_delegate);
93 return [delegate nativeWidgetMac]->bridge_.get(); 78 return [delegate nativeWidgetMac]->bridge_.get();
94 } 79 }
95 return nullptr; // Not created by NativeWidgetMac. 80 return nullptr; // Not created by NativeWidgetMac.
96 } 81 }
97 82
98 bool NativeWidgetMac::IsWindowModalSheet() const {
99 return GetWidget()->widget_delegate()->GetModalType() ==
100 ui::MODAL_TYPE_WINDOW;
101 }
102
103 void NativeWidgetMac::OnWindowWillClose() { 83 void NativeWidgetMac::OnWindowWillClose() {
104 // Note: If closed via CloseNow(), |bridge_| will already be reset. If closed 84 // Note: If closed via CloseNow(), |bridge_| will already be reset. If closed
105 // by the user, or via Close() and a RunLoop, notify observers while |bridge_| 85 // by the user, or via Close() and a RunLoop, notify observers while |bridge_|
106 // is still a valid pointer, then reset it. 86 // is still a valid pointer, then reset it.
107 if (bridge_) { 87 if (bridge_) {
108 delegate_->OnNativeWidgetDestroying(); 88 delegate_->OnNativeWidgetDestroying();
109 bridge_.reset(); 89 bridge_.reset();
110 } 90 }
111 delegate_->OnNativeWidgetDestroyed(); 91 delegate_->OnNativeWidgetDestroyed();
112 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) 92 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET)
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 } 317 }
338 318
339 void NativeWidgetMac::SetShape(std::unique_ptr<SkRegion> shape) { 319 void NativeWidgetMac::SetShape(std::unique_ptr<SkRegion> shape) {
340 NOTIMPLEMENTED(); 320 NOTIMPLEMENTED();
341 } 321 }
342 322
343 void NativeWidgetMac::Close() { 323 void NativeWidgetMac::Close() {
344 if (!bridge_) 324 if (!bridge_)
345 return; 325 return;
346 326
347 NSWindow* window = GetNativeWindow(); 327 bridge_->CloseAsynchronously();
348 if (IsWindowModalSheet()) {
349 // Sheets can't be closed normally. This starts the sheet closing. Once the
350 // sheet has finished animating, it will call sheetDidEnd: on the parent
351 // window's delegate. Note it still needs to be asynchronous, since code
352 // calling Widget::Close() doesn't expect things to be deleted upon return.
353 [NSApp performSelector:@selector(endSheet:) withObject:window afterDelay:0];
354 return;
355 }
356
357 // For other modal types, animate the close.
358 if (delegate_->IsModal()) {
359 [ViewsNSWindowCloseAnimator closeWindowWithAnimation:window];
360 return;
361 }
362
363 // Clear the view early to suppress repaints.
364 bridge_->SetRootView(NULL);
365
366 // Widget::Close() ensures [Non]ClientView::CanClose() returns true, so there
367 // is no need to call the NSWindow or its delegate's -windowShouldClose:
368 // implementation in the manner of -[NSWindow performClose:]. But,
369 // like -performClose:, first remove the window from AppKit's display
370 // list to avoid crashes like http://crbug.com/156101.
371 [window orderOut:nil];
372
373 // Many tests assume that base::RunLoop().RunUntilIdle() is always sufficient
374 // to execute a close. However, in rare cases, -performSelector:..afterDelay:0
375 // does not do this. So post a regular task.
376 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindBlock(^{
377 [window close];
378 }));
379 } 328 }
380 329
381 void NativeWidgetMac::CloseNow() { 330 void NativeWidgetMac::CloseNow() {
382 if (!bridge_) 331 if (!bridge_)
383 return; 332 return;
384 333
385 // Notify observers while |bridged_| is still valid. 334 // Notify observers while |bridged_| is still valid.
386 delegate_->OnNativeWidgetDestroying(); 335 delegate_->OnNativeWidgetDestroying();
387 // Reset |bridge_| to NULL before destroying it. 336 // Reset |bridge_| to NULL before destroying it.
388 std::unique_ptr<BridgedNativeWidget> bridge(std::move(bridge_)); 337 std::unique_ptr<BridgedNativeWidget> bridge(std::move(bridge_));
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 } 685 }
737 686
738 // static 687 // static
739 gfx::NativeView NativeWidgetPrivate::GetGlobalCapture( 688 gfx::NativeView NativeWidgetPrivate::GetGlobalCapture(
740 gfx::NativeView native_view) { 689 gfx::NativeView native_view) {
741 return [CocoaMouseCapture::GetGlobalCaptureWindow() contentView]; 690 return [CocoaMouseCapture::GetGlobalCaptureWindow() contentView];
742 } 691 }
743 692
744 } // namespace internal 693 } // namespace internal
745 } // namespace views 694 } // namespace views
746
747 @implementation ViewsNSWindowCloseAnimator
748
749 - (id)initWithWindow:(NSWindow*)window {
750 if ((self = [super init])) {
751 window_.reset([window retain]);
752 animation_.reset(
753 [[ConstrainedWindowAnimationHide alloc] initWithWindow:window]);
754 [animation_ setDelegate:self];
755 [animation_ setAnimationBlockingMode:NSAnimationNonblocking];
756 [animation_ startAnimation];
757 }
758 return self;
759 }
760
761 + (void)closeWindowWithAnimation:(NSWindow*)window {
762 [[ViewsNSWindowCloseAnimator alloc] initWithWindow:window];
763 }
764
765 - (void)animationDidEnd:(NSAnimation*)animation {
766 [window_ close];
767 [animation_ setDelegate:nil];
768 [self release];
769 }
770
771 @end
OLDNEW
« no previous file with comments | « ui/views/widget/native_widget_mac.h ('k') | ui/views/widget/widget_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698