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

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

Issue 2629593005: MacViews: Support -[NSWindow close] on sheets. (Closed)
Patch Set: Fix lifetime Created 3 years, 11 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/views_nswindow_delegate.h" 5 #import "ui/views/cocoa/views_nswindow_delegate.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #import "base/mac/bind_objc_block.h"
9 #include "base/threading/thread_task_runner_handle.h"
8 #import "ui/views/cocoa/bridged_content_view.h" 10 #import "ui/views/cocoa/bridged_content_view.h"
9 #import "ui/views/cocoa/bridged_native_widget.h" 11 #import "ui/views/cocoa/bridged_native_widget.h"
10 #include "ui/views/widget/native_widget_mac.h" 12 #include "ui/views/widget/native_widget_mac.h"
11 13
12 @implementation ViewsNSWindowDelegate 14 @implementation ViewsNSWindowDelegate
13 15
14 - (id)initWithBridgedNativeWidget:(views::BridgedNativeWidget*)parent { 16 - (id)initWithBridgedNativeWidget:(views::BridgedNativeWidget*)parent {
15 DCHECK(parent); 17 DCHECK(parent);
16 if ((self = [super init])) { 18 if ((self = [super init])) {
17 parent_ = parent; 19 parent_ = parent;
(...skipping 21 matching lines...) Expand all
39 parent_->OnVisibilityChanged(); 41 parent_->OnVisibilityChanged();
40 } 42 }
41 43
42 - (void)onSystemControlTintChanged:(NSNotification*)notification { 44 - (void)onSystemControlTintChanged:(NSNotification*)notification {
43 parent_->OnSystemControlTintChanged(); 45 parent_->OnSystemControlTintChanged();
44 } 46 }
45 47
46 - (void)sheetDidEnd:(NSWindow*)sheet 48 - (void)sheetDidEnd:(NSWindow*)sheet
47 returnCode:(NSInteger)returnCode 49 returnCode:(NSInteger)returnCode
48 contextInfo:(void*)contextInfo { 50 contextInfo:(void*)contextInfo {
51 // |parent_| will be null when triggered from the block in -windowWillClose:.
52 if (!parent_)
53 return;
54
49 [sheet orderOut:nil]; 55 [sheet orderOut:nil];
50 parent_->OnWindowWillClose(); 56 parent_->OnWindowWillClose();
51 } 57 }
52 58
53 // NSWindowDelegate implementation. 59 // NSWindowDelegate implementation.
54 60
55 - (void)windowDidFailToEnterFullScreen:(NSWindow*)window { 61 - (void)windowDidFailToEnterFullScreen:(NSWindow*)window {
56 // Cocoa should already have sent an (unexpected) windowDidExitFullScreen: 62 // Cocoa should already have sent an (unexpected) windowDidExitFullScreen:
57 // notification, and the attempt to get back into fullscreen should fail. 63 // notification, and the attempt to get back into fullscreen should fail.
58 // Nothing to do except verify |parent_| is no longer trying to fullscreen. 64 // Nothing to do except verify |parent_| is no longer trying to fullscreen.
(...skipping 20 matching lines...) Expand all
79 } 85 }
80 86
81 - (void)windowDidBecomeKey:(NSNotification*)notification { 87 - (void)windowDidBecomeKey:(NSNotification*)notification {
82 parent_->OnWindowKeyStatusChangedTo(true); 88 parent_->OnWindowKeyStatusChangedTo(true);
83 } 89 }
84 90
85 - (void)windowDidResignKey:(NSNotification*)notification { 91 - (void)windowDidResignKey:(NSNotification*)notification {
86 parent_->OnWindowKeyStatusChangedTo(false); 92 parent_->OnWindowKeyStatusChangedTo(false);
87 } 93 }
88 94
95 // Does nothing: Used to force |self| to be retained in a block.
Robert Sesek 2017/01/13 20:02:47 Could you instead just put another keepAlive in th
tapted 2017/01/13 20:52:51 That would take (and release) an additional refere
Robert Sesek 2017/01/13 21:46:00 Hm, I see your point. Maybe rather than doNothing,
tapted 2017/01/13 22:32:45 Done!
96 - (void)doNothing {}
97
89 - (void)windowWillClose:(NSNotification*)notification { 98 - (void)windowWillClose:(NSNotification*)notification {
90 DCHECK([parent_->ns_window() isEqual:[notification object]]); 99 // Retain |self|. |parent_| should be cleared. OnWindowWillClose() may delete
100 // |parent_|, but it may also dealloc |self| before returning. However, the
101 // observers it notifies before that need a valid |parent_| on the delegate,
102 // so it can only be cleared after OnWindowWillClose() returns.
103 base::scoped_nsobject<NSObject> keepAlive(self, base::scoped_policy::RETAIN);
104 NSWindow* window = parent_->ns_window();
105 if (NSWindow* sheetParent = [window sheetParent]) {
106 // On no! Something called -[NSWindow close] on a sheet rather than calling
107 // -[NSWindow endSheet:] on its parent. If the modal session is not ended
108 // then the parent will never be able to show another sheet. But calling
109 // -endSheet: here will block the thread with an animation, so post a task.
110 // Use a block: The argument to -endSheet: must be retained, since it's the
111 // window that is closing and -performSelector: won't retain the argument.
112 // The NSWindowDelegate (i.e. |self|) must also be explicitly retained. Even
113 // though the call to OnWindowWillClose() below will remove |self| as the
114 // NSWindow delegate, the call to -[NSApp beginSheet:] also took a weak
115 // reference to the delegate, which will be destroyed when the sheet's
116 // BridgedNativeWidget is destroyed.
117 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindBlock(^{
118 [sheetParent endSheet:window];
119 [self doNothing];
120 }));
121 }
122 DCHECK([window isEqual:[notification object]]);
91 parent_->OnWindowWillClose(); 123 parent_->OnWindowWillClose();
124 parent_ = nullptr;
92 } 125 }
93 126
94 - (void)windowDidMiniaturize:(NSNotification*)notification { 127 - (void)windowDidMiniaturize:(NSNotification*)notification {
95 parent_->OnVisibilityChanged(); 128 parent_->OnVisibilityChanged();
96 } 129 }
97 130
98 - (void)windowDidDeminiaturize:(NSNotification*)notification { 131 - (void)windowDidDeminiaturize:(NSNotification*)notification {
99 parent_->OnVisibilityChanged(); 132 parent_->OnVisibilityChanged();
100 } 133 }
101 134
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 usingRect:(NSRect)defaultSheetLocation { 168 usingRect:(NSRect)defaultSheetLocation {
136 // As per NSWindowDelegate documentation, the origin indicates the top left 169 // As per NSWindowDelegate documentation, the origin indicates the top left
137 // point of the host frame in window coordinates. The width changes the 170 // point of the host frame in window coordinates. The width changes the
138 // animation from vertical to trapezoid if it is smaller than the width of the 171 // animation from vertical to trapezoid if it is smaller than the width of the
139 // dialog. The height is ignored but should be set to zero. 172 // dialog. The height is ignored but should be set to zero.
140 return NSMakeRect(0, [self nativeWidgetMac]->SheetPositionY(), 173 return NSMakeRect(0, [self nativeWidgetMac]->SheetPositionY(),
141 NSWidth(defaultSheetLocation), 0); 174 NSWidth(defaultSheetLocation), 0);
142 } 175 }
143 176
144 @end 177 @end
OLDNEW
« no previous file with comments | « no previous file | ui/views/cocoa/widget_owner_nswindow_adapter.mm » ('j') | ui/views/widget/native_widget_mac.mm » ('J')

Powered by Google App Engine
This is Rietveld 408576698