| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h" | 5 #import "chrome/browser/ui/cocoa/extensions/extension_popup_controller.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "chrome/browser/debugger/devtools_window.h" | 9 #include "chrome/browser/debugger/devtools_window.h" |
| 10 #include "chrome/browser/extensions/extension_host.h" | 10 #include "chrome/browser/extensions/extension_host.h" |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 ExtensionPopupController* controller_; | 112 ExtensionPopupController* controller_; |
| 113 }; | 113 }; |
| 114 | 114 |
| 115 @implementation ExtensionPopupController | 115 @implementation ExtensionPopupController |
| 116 | 116 |
| 117 - (id)initWithHost:(ExtensionHost*)host | 117 - (id)initWithHost:(ExtensionHost*)host |
| 118 parentWindow:(NSWindow*)parentWindow | 118 parentWindow:(NSWindow*)parentWindow |
| 119 anchoredAt:(NSPoint)anchoredAt | 119 anchoredAt:(NSPoint)anchoredAt |
| 120 arrowLocation:(info_bubble::BubbleArrowLocation)arrowLocation | 120 arrowLocation:(info_bubble::BubbleArrowLocation)arrowLocation |
| 121 devMode:(BOOL)devMode { | 121 devMode:(BOOL)devMode { |
| 122 | |
| 123 parentWindow_ = parentWindow; | |
| 124 anchor_ = [parentWindow convertBaseToScreen:anchoredAt]; | |
| 125 host_.reset(host); | |
| 126 beingInspected_ = devMode; | |
| 127 | |
| 128 scoped_nsobject<InfoBubbleView> view([[InfoBubbleView alloc] init]); | |
| 129 if (!view.get()) | |
| 130 return nil; | |
| 131 [view setArrowLocation:arrowLocation]; | |
| 132 | |
| 133 extensionView_ = host->view()->native_view(); | |
| 134 container_.reset(new ExtensionPopupContainer(self)); | |
| 135 host->view()->set_container(container_.get()); | |
| 136 | |
| 137 NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; | |
| 138 [center addObserver:self | |
| 139 selector:@selector(extensionViewFrameChanged) | |
| 140 name:NSViewFrameDidChangeNotification | |
| 141 object:extensionView_]; | |
| 142 | |
| 143 // Watch to see if the parent window closes, and if so, close this one. | |
| 144 [center addObserver:self | |
| 145 selector:@selector(parentWindowWillClose:) | |
| 146 name:NSWindowWillCloseNotification | |
| 147 object:parentWindow_]; | |
| 148 | |
| 149 [view addSubview:extensionView_]; | |
| 150 scoped_nsobject<InfoBubbleWindow> window( | 122 scoped_nsobject<InfoBubbleWindow> window( |
| 151 [[InfoBubbleWindow alloc] | 123 [[InfoBubbleWindow alloc] |
| 152 initWithContentRect:NSZeroRect | 124 initWithContentRect:NSZeroRect |
| 153 styleMask:NSBorderlessWindowMask | 125 styleMask:NSBorderlessWindowMask |
| 154 backing:NSBackingStoreBuffered | 126 backing:NSBackingStoreBuffered |
| 155 defer:YES]); | 127 defer:YES]); |
| 156 if (!window.get()) | 128 if (!window.get()) |
| 157 return nil; | 129 return nil; |
| 130 anchoredAt = [parentWindow convertBaseToScreen:anchoredAt]; |
| 131 if ((self = [super initWithWindow:window |
| 132 parentWindow:parentWindow |
| 133 anchoredAt:anchoredAt])) { |
| 134 host_.reset(host); |
| 135 beingInspected_ = devMode; |
| 158 | 136 |
| 159 [window setDelegate:self]; | 137 InfoBubbleView* view = self.bubble; |
| 160 [window setContentView:view]; | 138 [view setArrowLocation:arrowLocation]; |
| 161 self = [super initWithWindow:window]; | 139 |
| 162 if (beingInspected_) { | 140 extensionView_ = host->view()->native_view(); |
| 163 // Listen for the the devtools window closing. | 141 container_.reset(new ExtensionPopupContainer(self)); |
| 164 notificationBridge_.reset(new DevtoolsNotificationBridge(self)); | 142 host->view()->set_container(container_.get()); |
| 165 registrar_.reset(new content::NotificationRegistrar); | 143 |
| 166 registrar_->Add(notificationBridge_.get(), | 144 NSNotificationCenter* center = [NSNotificationCenter defaultCenter]; |
| 167 content::NOTIFICATION_DEVTOOLS_WINDOW_CLOSING, | 145 [center addObserver:self |
| 168 content::Source<content::BrowserContext>(host->profile())); | 146 selector:@selector(extensionViewFrameChanged) |
| 169 registrar_->Add(notificationBridge_.get(), | 147 name:NSViewFrameDidChangeNotification |
| 170 chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, | 148 object:extensionView_]; |
| 171 content::Source<Profile>(host->profile())); | 149 |
| 150 [view addSubview:extensionView_]; |
| 151 |
| 152 if (beingInspected_) { |
| 153 // Listen for the the devtools window closing. |
| 154 notificationBridge_.reset(new DevtoolsNotificationBridge(self)); |
| 155 registrar_.reset(new content::NotificationRegistrar); |
| 156 registrar_->Add(notificationBridge_.get(), |
| 157 content::NOTIFICATION_DEVTOOLS_WINDOW_CLOSING, |
| 158 content::Source<content::BrowserContext>( |
| 159 host->profile())); |
| 160 registrar_->Add(notificationBridge_.get(), |
| 161 chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING, |
| 162 content::Source<Profile>(host->profile())); |
| 163 } |
| 172 } | 164 } |
| 173 return self; | 165 return self; |
| 174 } | 166 } |
| 175 | 167 |
| 176 - (void)showDevTools { | |
| 177 DevToolsWindow::OpenDevToolsWindow(host_->render_view_host()); | |
| 178 } | |
| 179 | |
| 180 - (void)dealloc { | 168 - (void)dealloc { |
| 181 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 169 [[NSNotificationCenter defaultCenter] removeObserver:self]; |
| 182 [super dealloc]; | 170 [super dealloc]; |
| 183 } | 171 } |
| 184 | 172 |
| 185 - (void)parentWindowWillClose:(NSNotification*)notification { | 173 - (void)showDevTools { |
| 186 [self close]; | 174 DevToolsWindow::OpenDevToolsWindow(host_->render_view_host()); |
| 187 } | 175 } |
| 188 | 176 |
| 189 - (void)windowWillClose:(NSNotification *)notification { | 177 - (void)windowWillClose:(NSNotification *)notification { |
| 190 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 178 [super windowWillClose:notification]; |
| 191 [gPopup autorelease]; | |
| 192 gPopup = nil; | 179 gPopup = nil; |
| 193 if (host_->view()) | 180 if (host_->view()) |
| 194 host_->view()->set_container(NULL); | 181 host_->view()->set_container(NULL); |
| 195 } | 182 } |
| 196 | 183 |
| 197 - (void)windowDidResignKey:(NSNotification *)notification { | 184 - (void)windowDidResignKey:(NSNotification*)notification { |
| 198 NSWindow* window = [self window]; | 185 if (!beingInspected_) |
| 199 DCHECK_EQ([notification object], window); | 186 [super windowDidResignKey:notification]; |
| 200 // If the window isn't visible, it is already closed, and this notification | |
| 201 // has been sent as part of the closing operation, so no need to close. | |
| 202 if ([window isVisible] && !beingInspected_) { | |
| 203 [self close]; | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 - (void)close { | |
| 208 [[[self window] parentWindow] removeChildWindow:[self window]]; | |
| 209 [super close]; | |
| 210 } | 187 } |
| 211 | 188 |
| 212 - (BOOL)isClosing { | 189 - (BOOL)isClosing { |
| 213 return [static_cast<InfoBubbleWindow*>([self window]) isClosing]; | 190 return [static_cast<InfoBubbleWindow*>([self window]) isClosing]; |
| 214 } | 191 } |
| 215 | 192 |
| 216 - (ExtensionHost*)extensionHost { | 193 - (ExtensionHost*)extensionHost { |
| 217 return host_.get(); | 194 return host_.get(); |
| 218 } | 195 } |
| 219 | 196 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 284 CGFloat inset = info_bubble::kBubbleCornerRadius / 2.0; | 261 CGFloat inset = info_bubble::kBubbleCornerRadius / 2.0; |
| 285 [extensionView_ setFrameOrigin:NSMakePoint(inset, inset)]; | 262 [extensionView_ setFrameOrigin:NSMakePoint(inset, inset)]; |
| 286 | 263 |
| 287 NSRect frame = [extensionView_ frame]; | 264 NSRect frame = [extensionView_ frame]; |
| 288 frame.size.height += info_bubble::kBubbleArrowHeight + | 265 frame.size.height += info_bubble::kBubbleArrowHeight + |
| 289 info_bubble::kBubbleCornerRadius; | 266 info_bubble::kBubbleCornerRadius; |
| 290 frame.size.width += info_bubble::kBubbleCornerRadius; | 267 frame.size.width += info_bubble::kBubbleCornerRadius; |
| 291 frame = [extensionView_ convertRectToBase:frame]; | 268 frame = [extensionView_ convertRectToBase:frame]; |
| 292 // Adjust the origin according to the height and width so that the arrow is | 269 // Adjust the origin according to the height and width so that the arrow is |
| 293 // positioned correctly at the middle and slightly down from the button. | 270 // positioned correctly at the middle and slightly down from the button. |
| 294 NSPoint windowOrigin = anchor_; | 271 NSPoint windowOrigin = self.anchorPoint; |
| 295 NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset + | 272 NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset + |
| 296 info_bubble::kBubbleArrowWidth / 2.0, | 273 info_bubble::kBubbleArrowWidth / 2.0, |
| 297 info_bubble::kBubbleArrowHeight / 2.0); | 274 info_bubble::kBubbleArrowHeight / 2.0); |
| 298 offsets = [extensionView_ convertSize:offsets toView:nil]; | 275 offsets = [extensionView_ convertSize:offsets toView:nil]; |
| 299 windowOrigin.x -= NSWidth(frame) - offsets.width; | 276 windowOrigin.x -= NSWidth(frame) - offsets.width; |
| 300 windowOrigin.y -= NSHeight(frame) - offsets.height; | 277 windowOrigin.y -= NSHeight(frame) - offsets.height; |
| 301 frame.origin = windowOrigin; | 278 frame.origin = windowOrigin; |
| 302 | 279 |
| 303 // Is the window still animating in? If so, then cancel that and create a new | 280 // Is the window still animating in? If so, then cancel that and create a new |
| 304 // animation setting the opacity and new frame value. Otherwise the current | 281 // animation setting the opacity and new frame value. Otherwise the current |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 return; | 324 return; |
| 348 | 325 |
| 349 [extensionView_ setFrame:frame]; | 326 [extensionView_ setFrame:frame]; |
| 350 [extensionView_ setNeedsDisplay:YES]; | 327 [extensionView_ setNeedsDisplay:YES]; |
| 351 } | 328 } |
| 352 | 329 |
| 353 - (void)onViewDidShow { | 330 - (void)onViewDidShow { |
| 354 [self onPreferredSizeChanged:pendingPreferredSize_]; | 331 [self onPreferredSizeChanged:pendingPreferredSize_]; |
| 355 } | 332 } |
| 356 | 333 |
| 357 // We want this to be a child of a browser window. addChildWindow: (called from | |
| 358 // this function) will bring the window on-screen; unfortunately, | |
| 359 // [NSWindowController showWindow:] will also bring it on-screen (but will cause | |
| 360 // unexpected changes to the window's position). We cannot have an | |
| 361 // addChildWindow: and a subsequent showWindow:. Thus, we have our own version. | |
| 362 - (void)showWindow:(id)sender { | |
| 363 [parentWindow_ addChildWindow:[self window] ordered:NSWindowAbove]; | |
| 364 [[self window] makeKeyAndOrderFront:self]; | |
| 365 } | |
| 366 | |
| 367 - (void)windowDidResize:(NSNotification*)notification { | 334 - (void)windowDidResize:(NSNotification*)notification { |
| 368 // Let the extension view know, so that it can tell plugins. | 335 // Let the extension view know, so that it can tell plugins. |
| 369 if (host_->view()) | 336 if (host_->view()) |
| 370 host_->view()->WindowFrameChanged(); | 337 host_->view()->WindowFrameChanged(); |
| 371 } | 338 } |
| 372 | 339 |
| 373 - (void)windowDidMove:(NSNotification*)notification { | 340 - (void)windowDidMove:(NSNotification*)notification { |
| 374 // Let the extension view know, so that it can tell plugins. | 341 // Let the extension view know, so that it can tell plugins. |
| 375 if (host_->view()) | 342 if (host_->view()) |
| 376 host_->view()->WindowFrameChanged(); | 343 host_->view()->WindowFrameChanged(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 387 return minSize; | 354 return minSize; |
| 388 } | 355 } |
| 389 | 356 |
| 390 // Private (TestingAPI) | 357 // Private (TestingAPI) |
| 391 + (NSSize)maxPopupSize { | 358 + (NSSize)maxPopupSize { |
| 392 NSSize maxSize = {ExtensionViewMac::kMaxWidth, ExtensionViewMac::kMaxHeight}; | 359 NSSize maxSize = {ExtensionViewMac::kMaxWidth, ExtensionViewMac::kMaxHeight}; |
| 393 return maxSize; | 360 return maxSize; |
| 394 } | 361 } |
| 395 | 362 |
| 396 @end | 363 @end |
| OLD | NEW |