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 #include "chrome/browser/ui/cocoa/extensions/shell_window_cocoa.h" | 5 #include "chrome/browser/ui/cocoa/extensions/shell_window_cocoa.h" |
6 | 6 |
7 #include "base/mac/mac_util.h" | 7 #include "base/mac/mac_util.h" |
8 #include "base/sys_string_conversions.h" | 8 #include "base/sys_string_conversions.h" |
9 #include "chrome/browser/profiles/profile.h" | 9 #include "chrome/browser/profiles/profile.h" |
10 #include "chrome/browser/ui/cocoa/browser_window_utils.h" | 10 #include "chrome/browser/ui/cocoa/browser_window_utils.h" |
11 #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h" | 11 #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h" |
12 #include "chrome/browser/ui/cocoa/extensions/extension_keybinding_registry_cocoa
.h" | 12 #include "chrome/browser/ui/cocoa/extensions/extension_keybinding_registry_cocoa
.h" |
13 #include "chrome/browser/ui/cocoa/extensions/extension_view_mac.h" | 13 #include "chrome/browser/ui/cocoa/extensions/extension_view_mac.h" |
14 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 14 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
15 #include "chrome/common/extensions/extension.h" | 15 #include "chrome/common/extensions/extension.h" |
16 #include "content/public/browser/native_web_keyboard_event.h" | 16 #include "content/public/browser/native_web_keyboard_event.h" |
17 #include "content/public/browser/render_widget_host_view.h" | 17 #include "content/public/browser/render_widget_host_view.h" |
18 #include "content/public/browser/web_contents.h" | 18 #include "content/public/browser/web_contents.h" |
19 #include "content/public/browser/web_contents_view.h" | 19 #include "content/public/browser/web_contents_view.h" |
20 #include "third_party/skia/include/core/SkRegion.h" | |
21 | 20 |
22 @interface NSWindow (NSPrivateApis) | 21 @interface NSWindow (NSPrivateApis) |
23 - (void)setBottomCornerRounded:(BOOL)rounded; | 22 - (void)setBottomCornerRounded:(BOOL)rounded; |
24 @end | 23 @end |
25 | 24 |
26 // Replicate specific 10.7 SDK declarations for building with prior SDKs. | 25 // Replicate specific 10.7 SDK declarations for building with prior SDKs. |
27 #if !defined(MAC_OS_X_VERSION_10_7) || \ | 26 #if !defined(MAC_OS_X_VERSION_10_7) || \ |
28 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 | 27 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 |
29 | 28 |
30 @interface NSWindow (LionSDKDeclarations) | 29 @interface NSWindow (LionSDKDeclarations) |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 return self; | 159 return self; |
161 } | 160 } |
162 | 161 |
163 - (BOOL)mouseDownCanMoveWindow { | 162 - (BOOL)mouseDownCanMoveWindow { |
164 return NO; | 163 return NO; |
165 } | 164 } |
166 | 165 |
167 - (NSView*)hitTest:(NSPoint)aPoint { | 166 - (NSView*)hitTest:(NSPoint)aPoint { |
168 if (shellWindow_->use_system_drag()) | 167 if (shellWindow_->use_system_drag()) |
169 return nil; | 168 return nil; |
170 if (!shellWindow_->draggable_region() || | 169 if (!shellWindow_->IsInsideDraggableRegions(aPoint.x, aPoint.y)) |
171 !shellWindow_->draggable_region()->contains(aPoint.x, aPoint.y)) { | |
172 return nil; | 170 return nil; |
173 } | |
174 return self; | 171 return self; |
175 } | 172 } |
176 | 173 |
177 - (void)mouseDown:(NSEvent*)event { | 174 - (void)mouseDown:(NSEvent*)event { |
178 shellWindow_->HandleMouseEvent(event); | 175 shellWindow_->HandleMouseEvent(event); |
179 } | 176 } |
180 | 177 |
181 - (void)mouseDragged:(NSEvent*)event { | 178 - (void)mouseDragged:(NSEvent*)event { |
182 shellWindow_->HandleMouseEvent(event); | 179 shellWindow_->HandleMouseEvent(event); |
183 } | 180 } |
184 | 181 |
185 @end | 182 @end |
186 | 183 |
187 @interface NSView (WebContentsView) | 184 @interface NSView (WebContentsView) |
188 - (void)setMouseDownCanMoveWindow:(BOOL)can_move; | 185 - (void)setMouseDownCanMoveWindow:(BOOL)can_move; |
189 @end | 186 @end |
190 | 187 |
191 ShellWindowCocoa::ShellWindowCocoa(ShellWindow* shell_window, | 188 ShellWindowCocoa::ShellWindowCocoa(ShellWindow* shell_window, |
192 const ShellWindow::CreateParams& params) | 189 const ShellWindow::CreateParams& params) |
193 : shell_window_(shell_window), | 190 : NativeShellWindow(params), |
194 has_frame_(params.frame == ShellWindow::CreateParams::FRAME_CHROME), | 191 shell_window_(shell_window), |
195 attention_request_id_(0), | 192 attention_request_id_(0), |
196 use_system_drag_(true) { | 193 use_system_drag_(true) { |
197 // Flip coordinates based on the primary screen. | 194 // Flip coordinates based on the primary screen. |
198 NSRect main_screen_rect = [[[NSScreen screens] objectAtIndex:0] frame]; | 195 NSRect main_screen_rect = [[[NSScreen screens] objectAtIndex:0] frame]; |
199 NSRect cocoa_bounds = NSMakeRect(params.bounds.x(), | 196 NSRect cocoa_bounds = NSMakeRect(params.bounds.x(), |
200 NSHeight(main_screen_rect) - params.bounds.y() - params.bounds.height(), | 197 NSHeight(main_screen_rect) - params.bounds.y() - params.bounds.height(), |
201 params.bounds.width(), params.bounds.height()); | 198 params.bounds.width(), params.bounds.height()); |
202 | 199 |
203 // If coordinates are < 0, center window on primary screen | 200 // If coordinates are < 0, center window on primary screen |
204 if (params.bounds.x() < 0) { | 201 if (params.bounds.x() < 0) { |
205 cocoa_bounds.origin.x = | 202 cocoa_bounds.origin.x = |
206 (NSWidth(main_screen_rect) - NSWidth(cocoa_bounds)) / 2; | 203 (NSWidth(main_screen_rect) - NSWidth(cocoa_bounds)) / 2; |
207 } | 204 } |
208 if (params.bounds.y() < 0) { | 205 if (params.bounds.y() < 0) { |
209 cocoa_bounds.origin.y = | 206 cocoa_bounds.origin.y = |
210 (NSHeight(main_screen_rect) - NSHeight(cocoa_bounds)) / 2; | 207 (NSHeight(main_screen_rect) - NSHeight(cocoa_bounds)) / 2; |
211 } | 208 } |
212 | 209 |
213 NSUInteger style_mask = NSTitledWindowMask | NSClosableWindowMask | | 210 NSUInteger style_mask = NSTitledWindowMask | NSClosableWindowMask | |
214 NSMiniaturizableWindowMask | NSResizableWindowMask | | 211 NSMiniaturizableWindowMask | NSResizableWindowMask | |
215 NSTexturedBackgroundWindowMask; | 212 NSTexturedBackgroundWindowMask; |
216 scoped_nsobject<NSWindow> window; | 213 scoped_nsobject<NSWindow> window; |
217 if (has_frame_) { | 214 if (frameless()) { |
218 window.reset([[ShellNSWindow alloc] | 215 window.reset([[ShellFramelessNSWindow alloc] |
219 initWithContentRect:cocoa_bounds | 216 initWithContentRect:cocoa_bounds |
220 styleMask:style_mask | 217 styleMask:style_mask |
221 backing:NSBackingStoreBuffered | 218 backing:NSBackingStoreBuffered |
222 defer:NO]); | 219 defer:NO]); |
223 } else { | 220 } else { |
224 window.reset([[ShellFramelessNSWindow alloc] | 221 window.reset([[ShellNSWindow alloc] |
225 initWithContentRect:cocoa_bounds | 222 initWithContentRect:cocoa_bounds |
226 styleMask:style_mask | 223 styleMask:style_mask |
227 backing:NSBackingStoreBuffered | 224 backing:NSBackingStoreBuffered |
228 defer:NO]); | 225 defer:NO]); |
229 } | 226 } |
230 [window setTitle:base::SysUTF8ToNSString(extension()->name())]; | 227 [window setTitle:base::SysUTF8ToNSString(extension()->name())]; |
231 gfx::Size min_size = params.minimum_size; | 228 gfx::Size min_size = params.minimum_size; |
232 if (min_size.width() || min_size.height()) { | 229 if (min_size.width() || min_size.height()) { |
233 [window setContentMinSize:NSMakeSize(min_size.width(), min_size.height())]; | 230 [window setContentMinSize:NSMakeSize(min_size.width(), min_size.height())]; |
234 } | 231 } |
235 gfx::Size max_size = params.maximum_size; | 232 gfx::Size max_size = params.maximum_size; |
236 if (max_size.width() || max_size.height()) { | 233 if (max_size.width() || max_size.height()) { |
237 CGFloat max_width = max_size.width() ? max_size.width() : CGFLOAT_MAX; | 234 CGFloat max_width = max_size.width() ? max_size.width() : CGFLOAT_MAX; |
238 CGFloat max_height = max_size.height() ? max_size.height() : CGFLOAT_MAX; | 235 CGFloat max_height = max_size.height() ? max_size.height() : CGFLOAT_MAX; |
239 [window setContentMaxSize:NSMakeSize(max_width, max_height)]; | 236 [window setContentMaxSize:NSMakeSize(max_width, max_height)]; |
240 } | 237 } |
241 | 238 |
242 if (base::mac::IsOSSnowLeopard() && | 239 if (base::mac::IsOSSnowLeopard() && |
243 [window respondsToSelector:@selector(setBottomCornerRounded:)]) | 240 [window respondsToSelector:@selector(setBottomCornerRounded:)]) |
244 [window setBottomCornerRounded:NO]; | 241 [window setBottomCornerRounded:NO]; |
245 | 242 |
246 window_controller_.reset( | 243 window_controller_.reset( |
247 [[ShellWindowController alloc] initWithWindow:window.release()]); | 244 [[ShellWindowController alloc] initWithWindow:window.release()]); |
248 | 245 |
249 NSView* view = web_contents()->GetView()->GetNativeView(); | 246 NSView* view = web_contents()->GetView()->GetNativeView(); |
250 [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; | 247 [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; |
251 | 248 |
252 // By default, the whole frameless window is not draggable. | 249 // By default, the whole frameless window is not draggable. |
253 if (!has_frame_) { | 250 if (frameless()) { |
254 gfx::Rect window_bounds( | 251 gfx::Rect window_bounds( |
255 0, 0, NSWidth(cocoa_bounds), NSHeight(cocoa_bounds)); | 252 0, 0, NSWidth(cocoa_bounds), NSHeight(cocoa_bounds)); |
256 system_drag_exclude_areas_.push_back(window_bounds); | 253 system_drag_exclude_areas_.push_back(window_bounds); |
257 } | 254 } |
258 | 255 |
259 InstallView(); | 256 InstallView(); |
260 | 257 |
261 [[window_controller_ window] setDelegate:window_controller_]; | 258 [[window_controller_ window] setDelegate:window_controller_]; |
262 [window_controller_ setShellWindow:this]; | 259 [window_controller_ setShellWindow:this]; |
263 | 260 |
264 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryCocoa( | 261 extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryCocoa( |
265 shell_window_->profile(), | 262 shell_window_->profile(), |
266 window, | 263 window, |
267 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, | 264 extensions::ExtensionKeybindingRegistry::PLATFORM_APPS_ONLY, |
268 shell_window)); | 265 shell_window)); |
269 } | 266 } |
270 | 267 |
271 void ShellWindowCocoa::InstallView() { | 268 void ShellWindowCocoa::InstallView() { |
272 NSView* view = web_contents()->GetView()->GetNativeView(); | 269 NSView* view = web_contents()->GetView()->GetNativeView(); |
273 if (has_frame_) { | 270 if (frameless()) { |
274 [view setFrame:[[window() contentView] bounds]]; | |
275 [[window() contentView] addSubview:view]; | |
276 } else { | |
277 // TODO(jeremya): find a cleaner way to send this information to the | 271 // TODO(jeremya): find a cleaner way to send this information to the |
278 // WebContentsViewCocoa view. | 272 // WebContentsViewCocoa view. |
279 DCHECK([view | 273 DCHECK([view |
280 respondsToSelector:@selector(setMouseDownCanMoveWindow:)]); | 274 respondsToSelector:@selector(setMouseDownCanMoveWindow:)]); |
281 [view setMouseDownCanMoveWindow:YES]; | 275 [view setMouseDownCanMoveWindow:YES]; |
282 | 276 |
283 NSView* frameView = [[window() contentView] superview]; | 277 NSView* frameView = [[window() contentView] superview]; |
284 [view setFrame:[frameView bounds]]; | 278 [view setFrame:[frameView bounds]]; |
285 [frameView addSubview:view]; | 279 [frameView addSubview:view]; |
286 | 280 |
287 [[window() standardWindowButton:NSWindowZoomButton] setHidden:YES]; | 281 [[window() standardWindowButton:NSWindowZoomButton] setHidden:YES]; |
288 [[window() standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES]; | 282 [[window() standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES]; |
289 [[window() standardWindowButton:NSWindowCloseButton] setHidden:YES]; | 283 [[window() standardWindowButton:NSWindowCloseButton] setHidden:YES]; |
290 | 284 |
291 InstallDraggableRegionViews(); | 285 InstallDraggableRegionViews(); |
| 286 } else { |
| 287 [view setFrame:[[window() contentView] bounds]]; |
| 288 [[window() contentView] addSubview:view]; |
292 } | 289 } |
293 } | 290 } |
294 | 291 |
295 void ShellWindowCocoa::UninstallView() { | 292 void ShellWindowCocoa::UninstallView() { |
296 NSView* view = web_contents()->GetView()->GetNativeView(); | 293 NSView* view = web_contents()->GetView()->GetNativeView(); |
297 [view removeFromSuperview]; | 294 [view removeFromSuperview]; |
298 } | 295 } |
299 | 296 |
300 bool ShellWindowCocoa::IsActive() const { | 297 bool ShellWindowCocoa::IsActive() const { |
301 return [window() isKeyWindow]; | 298 return [window() isKeyWindow]; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
457 } | 454 } |
458 | 455 |
459 void ShellWindowCocoa::UpdateWindowTitle() { | 456 void ShellWindowCocoa::UpdateWindowTitle() { |
460 string16 title = shell_window_->GetTitle(); | 457 string16 title = shell_window_->GetTitle(); |
461 [window() setTitle:base::SysUTF16ToNSString(title)]; | 458 [window() setTitle:base::SysUTF16ToNSString(title)]; |
462 } | 459 } |
463 | 460 |
464 void ShellWindowCocoa::UpdateDraggableRegions( | 461 void ShellWindowCocoa::UpdateDraggableRegions( |
465 const std::vector<extensions::DraggableRegion>& regions) { | 462 const std::vector<extensions::DraggableRegion>& regions) { |
466 // Draggable region is not supported for non-frameless window. | 463 // Draggable region is not supported for non-frameless window. |
467 if (has_frame_) | 464 if (!frameless()) |
468 return; | 465 return; |
469 | 466 |
470 // To use system drag, the window has to be marked as draggable with | 467 // To use system drag, the window has to be marked as draggable with |
471 // non-draggable areas being excluded via overlapping views. | 468 // non-draggable areas being excluded via overlapping views. |
472 // 1) If no draggable area is provided, the window is not draggable at all. | 469 // 1) If no draggable area is provided, the window is not draggable at all. |
473 // 2) If only one draggable area is given, as this is the most common | 470 // 2) If only one draggable area is given, as this is the most common |
474 // case, use the system drag. The non-draggable areas that are opposite of | 471 // case, use the system drag. The non-draggable areas that are opposite of |
475 // the draggable area are computed. | 472 // the draggable area are computed. |
476 // 3) Otherwise, use the custom drag. As such, we lose the capability to | 473 // 3) Otherwise, use the custom drag. As such, we lose the capability to |
477 // support some features like snapping into other space. | 474 // support some features like snapping into other space. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
576 // We still need one ControlRegionView to cover the whole window such that | 573 // We still need one ControlRegionView to cover the whole window such that |
577 // mouse events could be captured. | 574 // mouse events could be captured. |
578 NSView* web_view = web_contents()->GetView()->GetNativeView(); | 575 NSView* web_view = web_contents()->GetView()->GetNativeView(); |
579 gfx::Rect window_bounds( | 576 gfx::Rect window_bounds( |
580 0, 0, NSWidth([web_view bounds]), NSHeight([web_view bounds])); | 577 0, 0, NSWidth([web_view bounds]), NSHeight([web_view bounds])); |
581 system_drag_exclude_areas_.clear(); | 578 system_drag_exclude_areas_.clear(); |
582 system_drag_exclude_areas_.push_back(window_bounds); | 579 system_drag_exclude_areas_.push_back(window_bounds); |
583 | 580 |
584 // Aggregate the draggable areas and non-draggable areas such that hit test | 581 // Aggregate the draggable areas and non-draggable areas such that hit test |
585 // could be performed easily. | 582 // could be performed easily. |
586 SkRegion* draggable_region = new SkRegion; | 583 NativeShellWindow::UpdateDraggableRegions(regions); |
587 for (std::vector<extensions::DraggableRegion>::const_iterator iter = | |
588 regions.begin(); | |
589 iter != regions.end(); | |
590 ++iter) { | |
591 const extensions::DraggableRegion& region = *iter; | |
592 draggable_region->op( | |
593 region.bounds.x(), | |
594 region.bounds.y(), | |
595 region.bounds.right(), | |
596 region.bounds.bottom(), | |
597 region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op); | |
598 } | |
599 draggable_region_.reset(draggable_region); | |
600 } | |
601 | |
602 void ShellWindowCocoa::UpdateLegacyDraggableRegions( | |
603 const std::vector<extensions::DraggableRegion>& regions) { | |
604 // Draggable region is not supported for non-frameless window. | |
605 if (has_frame_) | |
606 return; | |
607 | |
608 system_drag_exclude_areas_.clear(); | |
609 for (std::vector<extensions::DraggableRegion>::const_iterator iter = | |
610 regions.begin(); | |
611 iter != regions.end(); | |
612 ++iter) { | |
613 system_drag_exclude_areas_.push_back(iter->bounds); | |
614 } | |
615 InstallDraggableRegionViews(); | |
616 } | 584 } |
617 | 585 |
618 void ShellWindowCocoa::HandleKeyboardEvent( | 586 void ShellWindowCocoa::HandleKeyboardEvent( |
619 const content::NativeWebKeyboardEvent& event) { | 587 const content::NativeWebKeyboardEvent& event) { |
620 if (event.skip_in_browser || | 588 if (event.skip_in_browser || |
621 event.type == content::NativeWebKeyboardEvent::Char) { | 589 event.type == content::NativeWebKeyboardEvent::Char) { |
622 return; | 590 return; |
623 } | 591 } |
624 [window() redispatchKeyEvent:event.os_event]; | 592 [window() redispatchKeyEvent:event.os_event]; |
625 } | 593 } |
626 | 594 |
627 void ShellWindowCocoa::InstallDraggableRegionViews() { | 595 void ShellWindowCocoa::InstallDraggableRegionViews() { |
628 DCHECK(!has_frame_); | 596 DCHECK(frameless()); |
629 | 597 |
630 // All ControlRegionViews should be added as children of the WebContentsView, | 598 // All ControlRegionViews should be added as children of the WebContentsView, |
631 // because WebContentsView will be removed and re-added when entering and | 599 // because WebContentsView will be removed and re-added when entering and |
632 // leaving fullscreen mode. | 600 // leaving fullscreen mode. |
633 NSView* webView = web_contents()->GetView()->GetNativeView(); | 601 NSView* webView = web_contents()->GetView()->GetNativeView(); |
634 NSInteger webViewHeight = NSHeight([webView bounds]); | 602 NSInteger webViewHeight = NSHeight([webView bounds]); |
635 | 603 |
636 // Remove all ControlRegionViews that are added last time. | 604 // Remove all ControlRegionViews that are added last time. |
637 // Note that [webView subviews] returns the view's mutable internal array and | 605 // Note that [webView subviews] returns the view's mutable internal array and |
638 // it should be copied to avoid mutating the original array while enumerating | 606 // it should be copied to avoid mutating the original array while enumerating |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
733 NSWindow* window = [window_controller_ window]; | 701 NSWindow* window = [window_controller_ window]; |
734 CHECK(!window || [window isKindOfClass:[ShellNSWindow class]]); | 702 CHECK(!window || [window isKindOfClass:[ShellNSWindow class]]); |
735 return static_cast<ShellNSWindow*>(window); | 703 return static_cast<ShellNSWindow*>(window); |
736 } | 704 } |
737 | 705 |
738 // static | 706 // static |
739 NativeShellWindow* NativeShellWindow::Create( | 707 NativeShellWindow* NativeShellWindow::Create( |
740 ShellWindow* shell_window, const ShellWindow::CreateParams& params) { | 708 ShellWindow* shell_window, const ShellWindow::CreateParams& params) { |
741 return new ShellWindowCocoa(shell_window, params); | 709 return new ShellWindowCocoa(shell_window, params); |
742 } | 710 } |
OLD | NEW |