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

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

Issue 2375903002: Emit OnNativeWidgetDestroying() before clearing the NSWindowDelegate. (Closed)
Patch Set: 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 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698