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/extensions/shell_window.h" | 5 #include "chrome/browser/ui/extensions/shell_window.h" |
6 | 6 |
7 #include "base/utf_string_conversions.h" | 7 #include "base/utf_string_conversions.h" |
8 #include "base/values.h" | 8 #include "base/values.h" |
9 #include "chrome/browser/extensions/extension_process_manager.h" | 9 #include "chrome/browser/extensions/extension_process_manager.h" |
10 #include "chrome/browser/extensions/extension_system.h" | 10 #include "chrome/browser/extensions/extension_system.h" |
11 #include "chrome/browser/extensions/shell_window_geometry_cache.h" | 11 #include "chrome/browser/extensions/shell_window_geometry_cache.h" |
12 #include "chrome/browser/extensions/shell_window_registry.h" | 12 #include "chrome/browser/extensions/shell_window_registry.h" |
13 #include "chrome/browser/extensions/tab_helper.h" | 13 #include "chrome/browser/extensions/tab_helper.h" |
14 #include "chrome/browser/favicon/favicon_tab_helper.h" | 14 #include "chrome/browser/favicon/favicon_tab_helper.h" |
15 #include "chrome/browser/file_select_helper.h" | 15 #include "chrome/browser/file_select_helper.h" |
16 #include "chrome/browser/intents/web_intents_util.h" | 16 #include "chrome/browser/intents/web_intents_util.h" |
17 #include "chrome/browser/lifetime/application_lifetime.h" | 17 #include "chrome/browser/lifetime/application_lifetime.h" |
18 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
19 #include "chrome/browser/sessions/session_id.h" | 19 #include "chrome/browser/sessions/session_id.h" |
20 #include "chrome/browser/ui/browser.h" | 20 #include "chrome/browser/ui/browser.h" |
21 #include "chrome/browser/ui/browser_finder.h" | 21 #include "chrome/browser/ui/browser_finder.h" |
22 #include "chrome/browser/ui/browser_tabstrip.h" | 22 #include "chrome/browser/ui/browser_tabstrip.h" |
23 #include "chrome/browser/ui/browser_window.h" | 23 #include "chrome/browser/ui/browser_window.h" |
24 #include "chrome/browser/ui/constrained_window_tab_helper.h" | 24 #include "chrome/browser/ui/constrained_window_tab_helper.h" |
25 #include "chrome/browser/ui/extensions/native_shell_window.h" | 25 #include "chrome/browser/ui/extensions/native_app_window.h" |
26 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" | 26 #include "chrome/browser/ui/intents/web_intent_picker_controller.h" |
27 #include "chrome/browser/ui/tab_contents/tab_contents.h" | 27 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
28 #include "chrome/browser/view_type_utils.h" | 28 #include "chrome/browser/view_type_utils.h" |
29 #include "chrome/common/chrome_notification_types.h" | 29 #include "chrome/common/chrome_notification_types.h" |
30 #include "chrome/common/extensions/api/app_window.h" | 30 #include "chrome/common/extensions/api/app_window.h" |
31 #include "chrome/common/extensions/extension.h" | 31 #include "chrome/common/extensions/extension.h" |
32 #include "chrome/common/extensions/extension_messages.h" | 32 #include "chrome/common/extensions/extension_messages.h" |
33 #include "chrome/common/extensions/request_media_access_permission_helper.h" | 33 #include "chrome/common/extensions/request_media_access_permission_helper.h" |
34 #include "content/public/browser/browser_thread.h" | 34 #include "content/public/browser/browser_thread.h" |
35 #include "content/public/browser/invalidate_type.h" | 35 #include "content/public/browser/invalidate_type.h" |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 shell_window_geometry_cache(); | 136 shell_window_geometry_cache(); |
137 gfx::Rect cached_bounds; | 137 gfx::Rect cached_bounds; |
138 if (cache->GetGeometry(extension()->id(), params.window_key, | 138 if (cache->GetGeometry(extension()->id(), params.window_key, |
139 &cached_bounds)) | 139 &cached_bounds)) |
140 bounds = cached_bounds; | 140 bounds = cached_bounds; |
141 } | 141 } |
142 | 142 |
143 ShellWindow::CreateParams new_params = params; | 143 ShellWindow::CreateParams new_params = params; |
144 new_params.bounds = bounds; | 144 new_params.bounds = bounds; |
145 | 145 |
146 native_window_.reset(NativeShellWindow::Create(this, new_params)); | 146 native_app_window_.reset(NativeAppWindow::Create(this, new_params)); |
147 OnNativeWindowChanged(); | 147 OnNativeWindowChanged(); |
148 | 148 |
149 if (!params.hidden) | 149 if (!params.hidden) |
150 GetBaseWindow()->Show(); | 150 GetBaseWindow()->Show(); |
151 | 151 |
152 // If the new view is in the same process as the creator, block the created | 152 // If the new view is in the same process as the creator, block the created |
153 // RVH from loading anything until the background page has had a chance to do | 153 // RVH from loading anything until the background page has had a chance to do |
154 // any initialization it wants. If it's a different process, the new RVH | 154 // any initialization it wants. If it's a different process, the new RVH |
155 // shouldn't communicate with the background page anyway (e.g. sandboxed). | 155 // shouldn't communicate with the background page anyway (e.g. sandboxed). |
156 if (web_contents_->GetRenderViewHost()->GetProcess()->GetID() == | 156 if (web_contents_->GetRenderViewHost()->GetProcess()->GetID() == |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
271 disposition = | 271 disposition = |
272 disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB; | 272 disposition == NEW_BACKGROUND_TAB ? disposition : NEW_FOREGROUND_TAB; |
273 chrome::AddWebContents(browser, NULL, new_contents, disposition, initial_pos, | 273 chrome::AddWebContents(browser, NULL, new_contents, disposition, initial_pos, |
274 user_gesture, was_blocked); | 274 user_gesture, was_blocked); |
275 } | 275 } |
276 | 276 |
277 void ShellWindow::HandleKeyboardEvent( | 277 void ShellWindow::HandleKeyboardEvent( |
278 WebContents* source, | 278 WebContents* source, |
279 const content::NativeWebKeyboardEvent& event) { | 279 const content::NativeWebKeyboardEvent& event) { |
280 DCHECK_EQ(source, web_contents_); | 280 DCHECK_EQ(source, web_contents_); |
281 native_window_->HandleKeyboardEvent(event); | 281 native_app_window_->HandleKeyboardEvent(event); |
282 } | 282 } |
283 | 283 |
284 void ShellWindow::OnNativeClose() { | 284 void ShellWindow::OnNativeClose() { |
285 extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this); | 285 extensions::ShellWindowRegistry::Get(profile_)->RemoveShellWindow(this); |
286 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); | 286 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); |
287 rvh->Send(new ExtensionMsg_AppWindowClosed(rvh->GetRoutingID())); | 287 rvh->Send(new ExtensionMsg_AppWindowClosed(rvh->GetRoutingID())); |
288 delete this; | 288 delete this; |
289 } | 289 } |
290 | 290 |
291 void ShellWindow::OnNativeWindowChanged() { | 291 void ShellWindow::OnNativeWindowChanged() { |
292 SaveWindowPosition(); | 292 SaveWindowPosition(); |
293 if (!native_window_ || !web_contents_) | 293 if (!native_app_window_ || !web_contents_) |
294 return; | 294 return; |
295 ListValue args; | 295 ListValue args; |
296 DictionaryValue* dictionary = new DictionaryValue(); | 296 DictionaryValue* dictionary = new DictionaryValue(); |
297 args.Append(dictionary); | 297 args.Append(dictionary); |
298 | 298 |
299 gfx::Rect bounds = native_window_->GetBounds(); | 299 gfx::Rect bounds = native_app_window_->GetBounds(); |
300 app_window::Bounds update; | 300 app_window::Bounds update; |
301 update.left.reset(new int(bounds.x())); | 301 update.left.reset(new int(bounds.x())); |
302 update.top.reset(new int(bounds.y())); | 302 update.top.reset(new int(bounds.y())); |
303 update.width.reset(new int(bounds.width())); | 303 update.width.reset(new int(bounds.width())); |
304 update.height.reset(new int(bounds.height())); | 304 update.height.reset(new int(bounds.height())); |
305 dictionary->Set("bounds", update.ToValue().release()); | 305 dictionary->Set("bounds", update.ToValue().release()); |
306 dictionary->SetBoolean("minimized", native_window_->IsMinimized()); | 306 dictionary->SetBoolean("minimized", native_app_window_->IsMinimized()); |
307 dictionary->SetBoolean("maximized", native_window_->IsMaximized()); | 307 dictionary->SetBoolean("maximized", native_app_window_->IsMaximized()); |
308 | 308 |
309 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); | 309 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); |
310 rvh->Send(new ExtensionMsg_MessageInvoke(rvh->GetRoutingID(), | 310 rvh->Send(new ExtensionMsg_MessageInvoke(rvh->GetRoutingID(), |
311 extension_->id(), | 311 extension_->id(), |
312 "updateAppWindowProperties", | 312 "updateAppWindowProperties", |
313 args, | 313 args, |
314 GURL(), | 314 GURL(), |
315 false)); | 315 false)); |
316 } | 316 } |
317 | 317 |
318 | 318 |
319 BaseWindow* ShellWindow::GetBaseWindow() { | 319 BaseWindow* ShellWindow::GetBaseWindow() { |
320 return native_window_.get(); | 320 return native_app_window_.get(); |
321 } | 321 } |
322 | 322 |
323 string16 ShellWindow::GetTitle() const { | 323 string16 ShellWindow::GetTitle() const { |
324 // WebContents::GetTitle() will return the page's URL if there's no <title> | 324 // WebContents::GetTitle() will return the page's URL if there's no <title> |
325 // specified. However, we'd prefer to show the name of the extension in that | 325 // specified. However, we'd prefer to show the name of the extension in that |
326 // case, so we directly inspect the NavigationEntry's title. | 326 // case, so we directly inspect the NavigationEntry's title. |
327 if (!web_contents()->GetController().GetActiveEntry() || | 327 if (!web_contents()->GetController().GetActiveEntry() || |
328 web_contents()->GetController().GetActiveEntry()->GetTitle().empty()) | 328 web_contents()->GetController().GetActiveEntry()->GetTitle().empty()) |
329 return UTF8ToUTF16(extension()->name()); | 329 return UTF8ToUTF16(extension()->name()); |
330 string16 title = web_contents()->GetTitle(); | 330 string16 title = web_contents()->GetTitle(); |
331 Browser::FormatTitleForDisplay(&title); | 331 Browser::FormatTitleForDisplay(&title); |
332 return title; | 332 return title; |
333 } | 333 } |
334 | 334 |
335 bool ShellWindow::OnMessageReceived(const IPC::Message& message) { | 335 bool ShellWindow::OnMessageReceived(const IPC::Message& message) { |
336 bool handled = true; | 336 bool handled = true; |
337 IPC_BEGIN_MESSAGE_MAP(ShellWindow, message) | 337 IPC_BEGIN_MESSAGE_MAP(ShellWindow, message) |
338 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) | 338 IPC_MESSAGE_HANDLER(ExtensionHostMsg_Request, OnRequest) |
339 IPC_MESSAGE_HANDLER(ExtensionHostMsg_UpdateDraggableRegions, | 339 IPC_MESSAGE_HANDLER(ExtensionHostMsg_UpdateDraggableRegions, |
340 UpdateDraggableRegions) | 340 UpdateDraggableRegions) |
341 IPC_MESSAGE_UNHANDLED(handled = false) | 341 IPC_MESSAGE_UNHANDLED(handled = false) |
342 IPC_END_MESSAGE_MAP() | 342 IPC_END_MESSAGE_MAP() |
343 return handled; | 343 return handled; |
344 } | 344 } |
345 | 345 |
346 void ShellWindow::UpdateDraggableRegions( | 346 void ShellWindow::UpdateDraggableRegions( |
347 const std::vector<extensions::DraggableRegion>& regions) { | 347 const std::vector<extensions::DraggableRegion>& regions) { |
348 native_window_->UpdateDraggableRegions(regions); | 348 native_app_window_->UpdateDraggableRegions(regions); |
349 } | 349 } |
350 | 350 |
351 void ShellWindow::OnImageLoaded(const gfx::Image& image, | 351 void ShellWindow::OnImageLoaded(const gfx::Image& image, |
352 const std::string& extension_id, | 352 const std::string& extension_id, |
353 int index) { | 353 int index) { |
354 if (!image.IsEmpty()) { | 354 if (!image.IsEmpty()) { |
355 app_icon_ = image; | 355 app_icon_ = image; |
356 native_window_->UpdateWindowIcon(); | 356 native_app_window_->UpdateWindowIcon(); |
357 } | 357 } |
358 app_icon_loader_.reset(); | 358 app_icon_loader_.reset(); |
359 } | 359 } |
360 | 360 |
361 void ShellWindow::UpdateExtensionAppIcon() { | 361 void ShellWindow::UpdateExtensionAppIcon() { |
362 app_icon_loader_.reset(new ImageLoadingTracker(this)); | 362 app_icon_loader_.reset(new ImageLoadingTracker(this)); |
363 app_icon_loader_->LoadImage( | 363 app_icon_loader_->LoadImage( |
364 extension(), | 364 extension(), |
365 extension()->GetIconResource(extension_misc::EXTENSION_ICON_SMALL, | 365 extension()->GetIconResource(extension_misc::EXTENSION_ICON_SMALL, |
366 ExtensionIconSet::MATCH_BIGGER), | 366 ExtensionIconSet::MATCH_BIGGER), |
367 gfx::Size(extension_misc::EXTENSION_ICON_SMALL, | 367 gfx::Size(extension_misc::EXTENSION_ICON_SMALL, |
368 extension_misc::EXTENSION_ICON_SMALL), | 368 extension_misc::EXTENSION_ICON_SMALL), |
369 ImageLoadingTracker::CACHE); | 369 ImageLoadingTracker::CACHE); |
370 } | 370 } |
371 | 371 |
372 void ShellWindow::CloseContents(WebContents* contents) { | 372 void ShellWindow::CloseContents(WebContents* contents) { |
373 DCHECK(contents == web_contents_); | 373 DCHECK(contents == web_contents_); |
374 native_window_->Close(); | 374 native_app_window_->Close(); |
375 } | 375 } |
376 | 376 |
377 bool ShellWindow::ShouldSuppressDialogs() { | 377 bool ShellWindow::ShouldSuppressDialogs() { |
378 return true; | 378 return true; |
379 } | 379 } |
380 | 380 |
381 void ShellWindow::WebIntentDispatch( | 381 void ShellWindow::WebIntentDispatch( |
382 content::WebContents* web_contents, | 382 content::WebContents* web_contents, |
383 content::WebIntentsDispatcher* intents_dispatcher) { | 383 content::WebIntentsDispatcher* intents_dispatcher) { |
384 if (!web_intents::IsWebIntentsEnabledForProfile(profile_)) | 384 if (!web_intents::IsWebIntentsEnabledForProfile(profile_)) |
(...skipping 12 matching lines...) Expand all Loading... |
397 FileSelectHelper::RunFileChooser(tab, params); | 397 FileSelectHelper::RunFileChooser(tab, params); |
398 } | 398 } |
399 | 399 |
400 bool ShellWindow::IsPopupOrPanel(const WebContents* source) const { | 400 bool ShellWindow::IsPopupOrPanel(const WebContents* source) const { |
401 DCHECK(source == web_contents_.get()); | 401 DCHECK(source == web_contents_.get()); |
402 return true; | 402 return true; |
403 } | 403 } |
404 | 404 |
405 void ShellWindow::MoveContents(WebContents* source, const gfx::Rect& pos) { | 405 void ShellWindow::MoveContents(WebContents* source, const gfx::Rect& pos) { |
406 DCHECK(source == web_contents_.get()); | 406 DCHECK(source == web_contents_.get()); |
407 native_window_->SetBounds(pos); | 407 native_app_window_->SetBounds(pos); |
408 } | 408 } |
409 | 409 |
410 void ShellWindow::NavigationStateChanged( | 410 void ShellWindow::NavigationStateChanged( |
411 const content::WebContents* source, unsigned changed_flags) { | 411 const content::WebContents* source, unsigned changed_flags) { |
412 DCHECK(source == web_contents_.get()); | 412 DCHECK(source == web_contents_.get()); |
413 if (changed_flags & content::INVALIDATE_TYPE_TITLE) | 413 if (changed_flags & content::INVALIDATE_TYPE_TITLE) |
414 native_window_->UpdateWindowTitle(); | 414 native_app_window_->UpdateWindowTitle(); |
415 else if (changed_flags & content::INVALIDATE_TYPE_TAB) | 415 else if (changed_flags & content::INVALIDATE_TYPE_TAB) |
416 native_window_->UpdateWindowIcon(); | 416 native_app_window_->UpdateWindowIcon(); |
417 } | 417 } |
418 | 418 |
419 void ShellWindow::ToggleFullscreenModeForTab(content::WebContents* source, | 419 void ShellWindow::ToggleFullscreenModeForTab(content::WebContents* source, |
420 bool enter_fullscreen) { | 420 bool enter_fullscreen) { |
421 DCHECK(source == web_contents_.get()); | 421 DCHECK(source == web_contents_.get()); |
422 native_window_->SetFullscreen(enter_fullscreen); | 422 native_app_window_->SetFullscreen(enter_fullscreen); |
423 } | 423 } |
424 | 424 |
425 bool ShellWindow::IsFullscreenForTabOrPending( | 425 bool ShellWindow::IsFullscreenForTabOrPending( |
426 const content::WebContents* source) const { | 426 const content::WebContents* source) const { |
427 DCHECK(source == web_contents_.get()); | 427 DCHECK(source == web_contents_.get()); |
428 return native_window_->IsFullscreenOrPending(); | 428 return native_app_window_->IsFullscreenOrPending(); |
429 } | 429 } |
430 | 430 |
431 void ShellWindow::Observe(int type, | 431 void ShellWindow::Observe(int type, |
432 const content::NotificationSource& source, | 432 const content::NotificationSource& source, |
433 const content::NotificationDetails& details) { | 433 const content::NotificationDetails& details) { |
434 switch (type) { | 434 switch (type) { |
435 case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: { | 435 case content::NOTIFICATION_RENDER_VIEW_HOST_CHANGED: { |
436 // TODO(jeremya): once http://crbug.com/123007 is fixed, we'll no longer | 436 // TODO(jeremya): once http://crbug.com/123007 is fixed, we'll no longer |
437 // need to suspend resource requests here (the call in the constructor | 437 // need to suspend resource requests here (the call in the constructor |
438 // should be enough). | 438 // should be enough). |
439 content::Details<std::pair<RenderViewHost*, RenderViewHost*> > | 439 content::Details<std::pair<RenderViewHost*, RenderViewHost*> > |
440 host_details(details); | 440 host_details(details); |
441 if (host_details->first) | 441 if (host_details->first) |
442 SuspendRenderViewHost(host_details->second); | 442 SuspendRenderViewHost(host_details->second); |
443 // TODO(jianli): once http://crbug.com/123007 is fixed, we'll no longer | 443 // TODO(jianli): once http://crbug.com/123007 is fixed, we'll no longer |
444 // need to make the native window (ShellWindowViews specially) update | 444 // need to make the native window (ShellWindowViews specially) update |
445 // the clickthrough region for the new RVH. | 445 // the clickthrough region for the new RVH. |
446 native_window_->RenderViewHostChanged(); | 446 native_app_window_->RenderViewHostChanged(); |
447 break; | 447 break; |
448 } | 448 } |
449 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { | 449 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
450 const extensions::Extension* unloaded_extension = | 450 const extensions::Extension* unloaded_extension = |
451 content::Details<extensions::UnloadedExtensionInfo>( | 451 content::Details<extensions::UnloadedExtensionInfo>( |
452 details)->extension; | 452 details)->extension; |
453 if (extension_ == unloaded_extension) | 453 if (extension_ == unloaded_extension) |
454 native_window_->Close(); | 454 native_app_window_->Close(); |
455 break; | 455 break; |
456 } | 456 } |
457 case chrome::NOTIFICATION_APP_TERMINATING: | 457 case chrome::NOTIFICATION_APP_TERMINATING: |
458 native_window_->Close(); | 458 native_app_window_->Close(); |
459 break; | 459 break; |
460 default: | 460 default: |
461 NOTREACHED() << "Received unexpected notification"; | 461 NOTREACHED() << "Received unexpected notification"; |
462 } | 462 } |
463 } | 463 } |
464 | 464 |
465 extensions::WindowController* | 465 extensions::WindowController* |
466 ShellWindow::GetExtensionWindowController() const { | 466 ShellWindow::GetExtensionWindowController() const { |
467 return NULL; | 467 return NULL; |
468 } | 468 } |
(...skipping 17 matching lines...) Expand all Loading... |
486 const std::string& message) { | 486 const std::string& message) { |
487 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); | 487 content::RenderViewHost* rvh = web_contents_->GetRenderViewHost(); |
488 rvh->Send(new ExtensionMsg_AddMessageToConsole( | 488 rvh->Send(new ExtensionMsg_AddMessageToConsole( |
489 rvh->GetRoutingID(), level, message)); | 489 rvh->GetRoutingID(), level, message)); |
490 } | 490 } |
491 | 491 |
492 | 492 |
493 void ShellWindow::SaveWindowPosition() { | 493 void ShellWindow::SaveWindowPosition() { |
494 if (window_key_.empty()) | 494 if (window_key_.empty()) |
495 return; | 495 return; |
496 if (!native_window_) | 496 if (!native_app_window_) |
497 return; | 497 return; |
498 | 498 |
499 extensions::ShellWindowGeometryCache* cache = | 499 extensions::ShellWindowGeometryCache* cache = |
500 extensions::ExtensionSystem::Get(profile())-> | 500 extensions::ExtensionSystem::Get(profile())-> |
501 shell_window_geometry_cache(); | 501 shell_window_geometry_cache(); |
502 | 502 |
503 gfx::Rect bounds = native_window_->GetBounds(); | 503 gfx::Rect bounds = native_app_window_->GetBounds(); |
504 cache->SaveGeometry(extension()->id(), window_key_, bounds); | 504 cache->SaveGeometry(extension()->id(), window_key_, bounds); |
505 } | 505 } |
506 | 506 |
507 // static | 507 // static |
508 SkRegion* ShellWindow::RawDraggableRegionsToSkRegion( | 508 SkRegion* ShellWindow::RawDraggableRegionsToSkRegion( |
509 const std::vector<extensions::DraggableRegion>& regions) { | 509 const std::vector<extensions::DraggableRegion>& regions) { |
510 SkRegion* sk_region = new SkRegion; | 510 SkRegion* sk_region = new SkRegion; |
511 for (std::vector<extensions::DraggableRegion>::const_iterator iter = | 511 for (std::vector<extensions::DraggableRegion>::const_iterator iter = |
512 regions.begin(); | 512 regions.begin(); |
513 iter != regions.end(); ++iter) { | 513 iter != regions.end(); ++iter) { |
514 const extensions::DraggableRegion& region = *iter; | 514 const extensions::DraggableRegion& region = *iter; |
515 sk_region->op( | 515 sk_region->op( |
516 region.bounds.x(), | 516 region.bounds.x(), |
517 region.bounds.y(), | 517 region.bounds.y(), |
518 region.bounds.right(), | 518 region.bounds.right(), |
519 region.bounds.bottom(), | 519 region.bounds.bottom(), |
520 region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op); | 520 region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op); |
521 } | 521 } |
522 return sk_region; | 522 return sk_region; |
523 } | 523 } |
OLD | NEW |