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

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

Issue 2393843002: MacViews: Implement CloseNow() as just -[NSWindow close]. (Closed)
Patch Set: Selfnits Created 4 years, 2 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 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 in_fullscreen_transition_(false), 346 in_fullscreen_transition_(false),
347 window_visible_(false), 347 window_visible_(false),
348 wants_to_be_visible_(false) { 348 wants_to_be_visible_(false) {
349 SetupDragEventMonitor(); 349 SetupDragEventMonitor();
350 DCHECK(parent); 350 DCHECK(parent);
351 window_delegate_.reset( 351 window_delegate_.reset(
352 [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]); 352 [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]);
353 } 353 }
354 354
355 BridgedNativeWidget::~BridgedNativeWidget() { 355 BridgedNativeWidget::~BridgedNativeWidget() {
356 bool close_window = false; 356 // The delegate should be cleared already. Note this enforces the precondition
357 if ([window_ delegate]) { 357 // that the hosted NSWindow is closed before the destructor is called.
karandeepb 2016/10/18 10:00:29 Technically, the window hasn't closed yet right? W
tapted 2016/10/19 06:20:25 Done.
358 // If the delegate is still set on a modal dialog, it means it was not 358 DCHECK(![window_ delegate]);
359 // closed via [NSApplication endSheet:]. This is probably OK if the widget
360 // was never shown. But Cocoa ignores close() calls on open sheets. Calling
361 // endSheet: here would work, but it messes up assumptions elsewhere. E.g.
362 // DialogClientView assumes its delegate is alive when closing, which isn't
363 // true after endSheet: synchronously calls OnNativeWidgetDestroyed().
364 // So ban it. Modal dialogs should be closed via Widget::Close().
365 DCHECK(!native_widget_mac_->IsWindowModalSheet());
366
367 // If the delegate is still set, it means OnWindowWillClose() has not been
368 // called and the window is still open. Usually, -[NSWindow close] would
369 // synchronously call OnWindowWillClose() which removes the delegate and
370 // notifies NativeWidgetMac, which then calls this with a nil delegate.
371 // For other teardown flows (e.g. Widget::WIDGET_OWNS_NATIVE_WIDGET or
372 // Widget::CloseNow()) the delegate must first be cleared to avoid AppKit
373 // calling back into the bridge. This means OnWindowWillClose() needs to be
374 // invoked manually, which is done below.
375 // Note that if the window has children it can't be closed until the
376 // children are gone, but removing child windows calls into AppKit for the
377 // parent window, so the delegate must be cleared first.
378 [window_ setDelegate:nil];
379 close_window = true;
380 }
381 359
382 RemoveOrDestroyChildren(); 360 RemoveOrDestroyChildren();
383 DCHECK(child_windows_.empty()); 361 DCHECK(child_windows_.empty());
384 SetFocusManager(nullptr); 362 SetFocusManager(nullptr);
385 SetRootView(nullptr); 363 SetRootView(nullptr);
386 DestroyCompositor(); 364 DestroyCompositor();
387
388 if (close_window) {
389 OnWindowWillClose();
390 [window_ close];
391 }
392 } 365 }
393 366
394 void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window, 367 void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window,
395 const Widget::InitParams& params) { 368 const Widget::InitParams& params) {
396 widget_type_ = params.type; 369 widget_type_ = params.type;
397 370
398 DCHECK(!window_); 371 DCHECK(!window_);
399 window_.swap(window); 372 window_.swap(window);
400 [window_ setDelegate:window_delegate_]; 373 [window_ setDelegate:window_delegate_];
401 374
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 void* BridgedNativeWidget::GetNativeWindowProperty(const char* name) const { 672 void* BridgedNativeWidget::GetNativeWindowProperty(const char* name) const {
700 NSString* key = [NSString stringWithUTF8String:name]; 673 NSString* key = [NSString stringWithUTF8String:name];
701 return [[GetWindowProperties() objectForKey:key] pointerValue]; 674 return [[GetWindowProperties() objectForKey:key] pointerValue];
702 } 675 }
703 676
704 void BridgedNativeWidget::SetCursor(NSCursor* cursor) { 677 void BridgedNativeWidget::SetCursor(NSCursor* cursor) {
705 [window_delegate_ setCursor:cursor]; 678 [window_delegate_ setCursor:cursor];
706 } 679 }
707 680
708 void BridgedNativeWidget::OnWindowWillClose() { 681 void BridgedNativeWidget::OnWindowWillClose() {
682 native_widget_mac_->GetWidget()->OnNativeWidgetDestroying();
683
709 // Ensure BridgedNativeWidget does not have capture, otherwise 684 // Ensure BridgedNativeWidget does not have capture, otherwise
710 // OnMouseCaptureLost() may reference a deleted |native_widget_mac_| when 685 // OnMouseCaptureLost() may reference a deleted |native_widget_mac_| when
711 // called via ~CocoaMouseCapture() upon the destruction of |mouse_capture_|. 686 // called via ~CocoaMouseCapture() upon the destruction of |mouse_capture_|.
712 // See crbug.com/622201. Also we do this before setting the delegate to nil, 687 // See crbug.com/622201. Also we do this before setting the delegate to nil,
713 // because this may lead to callbacks to bridge which rely on a valid 688 // because this may lead to callbacks to bridge which rely on a valid
714 // delegate. 689 // delegate.
715 ReleaseCapture(); 690 ReleaseCapture();
716 691
717 if (parent_) { 692 if (parent_) {
718 parent_->RemoveChildWindow(this); 693 parent_->RemoveChildWindow(this);
719 parent_ = nullptr; 694 parent_ = nullptr;
720 } 695 }
721 [[NSNotificationCenter defaultCenter] removeObserver:window_delegate_]; 696 [[NSNotificationCenter defaultCenter] removeObserver:window_delegate_];
722 // Note this also clears the NSWindow delegate, after informing Widget 697 [window_ setDelegate:nil];
723 // delegates about the closure. NativeWidgetMac then deletes |this| before 698 native_widget_mac_->OnWindowDestroyed();
724 // returning. 699 // Note: |this| is deleted here.
725 native_widget_mac_->OnWindowWillClose();
726 } 700 }
727 701
728 void BridgedNativeWidget::OnFullscreenTransitionStart( 702 void BridgedNativeWidget::OnFullscreenTransitionStart(
729 bool target_fullscreen_state) { 703 bool target_fullscreen_state) {
730 // Note: This can fail for fullscreen changes started externally, but a user 704 // Note: This can fail for fullscreen changes started externally, but a user
731 // shouldn't be able to do that if the window is invisible to begin with. 705 // shouldn't be able to do that if the window is invisible to begin with.
732 DCHECK(window_visible_); 706 DCHECK(window_visible_);
733 707
734 DCHECK_NE(target_fullscreen_state, target_fullscreen_state_); 708 DCHECK_NE(target_fullscreen_state, target_fullscreen_state_);
735 target_fullscreen_state_ = target_fullscreen_state; 709 target_fullscreen_state_ = target_fullscreen_state;
(...skipping 666 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 [bridged_view_ setMouseDownCanMoveWindow:draggable]; 1376 [bridged_view_ setMouseDownCanMoveWindow:draggable];
1403 // AppKit will not update its cache of mouseDownCanMoveWindow unless something 1377 // AppKit will not update its cache of mouseDownCanMoveWindow unless something
1404 // changes. Previously we tried adding an NSView and removing it, but for some 1378 // changes. Previously we tried adding an NSView and removing it, but for some
1405 // reason it required reposting the mouse-down event, and didn't always work. 1379 // reason it required reposting the mouse-down event, and didn't always work.
1406 // Calling the below seems to be an effective solution. 1380 // Calling the below seems to be an effective solution.
1407 [window_ setMovableByWindowBackground:NO]; 1381 [window_ setMovableByWindowBackground:NO];
1408 [window_ setMovableByWindowBackground:YES]; 1382 [window_ setMovableByWindowBackground:YES];
1409 } 1383 }
1410 1384
1411 } // namespace views 1385 } // namespace views
OLDNEW
« no previous file with comments | « no previous file | ui/views/cocoa/bridged_native_widget_unittest.mm » ('j') | ui/views/cocoa/bridged_native_widget_unittest.mm » ('J')

Powered by Google App Engine
This is Rietveld 408576698