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 #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 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 return [delegate nativeWidgetMac]->bridge_.get(); | 93 return [delegate nativeWidgetMac]->bridge_.get(); |
94 } | 94 } |
95 return nullptr; // Not created by NativeWidgetMac. | 95 return nullptr; // Not created by NativeWidgetMac. |
96 } | 96 } |
97 | 97 |
98 bool NativeWidgetMac::IsWindowModalSheet() const { | 98 bool NativeWidgetMac::IsWindowModalSheet() const { |
99 return GetWidget()->widget_delegate()->GetModalType() == | 99 return GetWidget()->widget_delegate()->GetModalType() == |
100 ui::MODAL_TYPE_WINDOW; | 100 ui::MODAL_TYPE_WINDOW; |
101 } | 101 } |
102 | 102 |
103 void NativeWidgetMac::OnWindowWillClose() { | 103 void NativeWidgetMac::OnWindowDestroyed() { |
104 // Note: If closed via CloseNow(), |bridge_| will already be reset. If closed | 104 DCHECK(bridge_); |
105 // by the user, or via Close() and a RunLoop, notify observers while |bridge_| | 105 bridge_.reset(); |
106 // is still a valid pointer, then reset it. | |
107 if (bridge_) { | |
108 delegate_->OnNativeWidgetDestroying(); | |
109 [GetNativeWindow() setDelegate:nil]; | |
110 bridge_.reset(); | |
111 } | |
112 delegate_->OnNativeWidgetDestroyed(); | 106 delegate_->OnNativeWidgetDestroyed(); |
113 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) | 107 if (ownership_ == Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) |
114 delete this; | 108 delete this; |
115 } | 109 } |
116 | 110 |
117 int NativeWidgetMac::SheetPositionY() { | 111 int NativeWidgetMac::SheetPositionY() { |
118 NSView* view = GetNativeView(); | 112 NSView* view = GetNativeView(); |
119 return | 113 return |
120 [view convertPoint:NSMakePoint(0, NSHeight([view frame])) toView:nil].y; | 114 [view convertPoint:NSMakePoint(0, NSHeight([view frame])) toView:nil].y; |
121 } | 115 } |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 } | 328 } |
335 | 329 |
336 void NativeWidgetMac::SetShape(std::unique_ptr<SkRegion> shape) { | 330 void NativeWidgetMac::SetShape(std::unique_ptr<SkRegion> shape) { |
337 NOTIMPLEMENTED(); | 331 NOTIMPLEMENTED(); |
338 } | 332 } |
339 | 333 |
340 void NativeWidgetMac::Close() { | 334 void NativeWidgetMac::Close() { |
341 if (!bridge_) | 335 if (!bridge_) |
342 return; | 336 return; |
343 | 337 |
| 338 // Keep |window| on the stack so that the ObjectiveC block below can capture |
| 339 // it and properly increment the reference count bound to the posted task. |
344 NSWindow* window = GetNativeWindow(); | 340 NSWindow* window = GetNativeWindow(); |
| 341 |
345 if (IsWindowModalSheet()) { | 342 if (IsWindowModalSheet()) { |
346 // Sheets can't be closed normally. This starts the sheet closing. Once the | 343 // Sheets can't be closed normally. This starts the sheet closing. Once the |
347 // sheet has finished animating, it will call sheetDidEnd: on the parent | 344 // sheet has finished animating, it will call sheetDidEnd: on the parent |
348 // window's delegate. Note it still needs to be asynchronous, since code | 345 // window's delegate. Note it still needs to be asynchronous, since code |
349 // calling Widget::Close() doesn't expect things to be deleted upon return. | 346 // calling Widget::Close() doesn't expect things to be deleted upon return. |
350 [NSApp performSelector:@selector(endSheet:) withObject:window afterDelay:0]; | 347 [NSApp performSelector:@selector(endSheet:) withObject:window afterDelay:0]; |
351 return; | 348 return; |
352 } | 349 } |
353 | 350 |
354 // For other modal types, animate the close. | 351 // For other modal types, animate the close. |
(...skipping 17 matching lines...) Expand all Loading... |
372 // does not do this. So post a regular task. | 369 // does not do this. So post a regular task. |
373 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindBlock(^{ | 370 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindBlock(^{ |
374 [window close]; | 371 [window close]; |
375 })); | 372 })); |
376 } | 373 } |
377 | 374 |
378 void NativeWidgetMac::CloseNow() { | 375 void NativeWidgetMac::CloseNow() { |
379 if (!bridge_) | 376 if (!bridge_) |
380 return; | 377 return; |
381 | 378 |
382 // Notify observers while |bridged_| is still valid. | 379 // Cocoa ignores -close calls on open sheets, so they should be closed |
383 delegate_->OnNativeWidgetDestroying(); | 380 // asynchronously, using Widget::Close(). |
384 // Reset |bridge_| to NULL before destroying it. | 381 DCHECK(!IsWindowModalSheet()); |
385 std::unique_ptr<BridgedNativeWidget> bridge(std::move(bridge_)); | 382 |
| 383 // NSWindows must be retained until -[NSWindow close] returns. |
| 384 base::scoped_nsobject<NSWindow> window(GetNativeWindow(), |
| 385 base::scoped_policy::RETAIN); |
| 386 |
| 387 // If there's a bridge at this point, it means there must be a window as well. |
| 388 DCHECK(window); |
| 389 [window close]; |
| 390 // Note: |this| is deleted here when ownership_ == NATIVE_WIDGET_OWNS_WIDGET. |
386 } | 391 } |
387 | 392 |
388 void NativeWidgetMac::Show() { | 393 void NativeWidgetMac::Show() { |
389 ShowWithWindowState(ui::SHOW_STATE_NORMAL); | 394 ShowWithWindowState(ui::SHOW_STATE_NORMAL); |
390 } | 395 } |
391 | 396 |
392 void NativeWidgetMac::Hide() { | 397 void NativeWidgetMac::Hide() { |
393 if (!bridge_) | 398 if (!bridge_) |
394 return; | 399 return; |
395 | 400 |
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 [[ViewsNSWindowCloseAnimator alloc] initWithWindow:window]; | 764 [[ViewsNSWindowCloseAnimator alloc] initWithWindow:window]; |
760 } | 765 } |
761 | 766 |
762 - (void)animationDidEnd:(NSAnimation*)animation { | 767 - (void)animationDidEnd:(NSAnimation*)animation { |
763 [window_ close]; | 768 [window_ close]; |
764 [animation_ setDelegate:nil]; | 769 [animation_ setDelegate:nil]; |
765 [self release]; | 770 [self release]; |
766 } | 771 } |
767 | 772 |
768 @end | 773 @end |
OLD | NEW |