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/views/tabs/tab.h" | 5 #include "chrome/browser/ui/views/tabs/tab.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/debug/alias.h" | 10 #include "base/debug/alias.h" |
(...skipping 21 matching lines...) Expand all Loading... |
32 #include "ui/base/theme_provider.h" | 32 #include "ui/base/theme_provider.h" |
33 #include "ui/gfx/animation/animation_container.h" | 33 #include "ui/gfx/animation/animation_container.h" |
34 #include "ui/gfx/animation/multi_animation.h" | 34 #include "ui/gfx/animation/multi_animation.h" |
35 #include "ui/gfx/animation/throb_animation.h" | 35 #include "ui/gfx/animation/throb_animation.h" |
36 #include "ui/gfx/canvas.h" | 36 #include "ui/gfx/canvas.h" |
37 #include "ui/gfx/color_analysis.h" | 37 #include "ui/gfx/color_analysis.h" |
38 #include "ui/gfx/favicon_size.h" | 38 #include "ui/gfx/favicon_size.h" |
39 #include "ui/gfx/font.h" | 39 #include "ui/gfx/font.h" |
40 #include "ui/gfx/image/image_skia_operations.h" | 40 #include "ui/gfx/image/image_skia_operations.h" |
41 #include "ui/gfx/path.h" | 41 #include "ui/gfx/path.h" |
| 42 #include "ui/gfx/rect_conversions.h" |
| 43 #include "ui/gfx/skia_util.h" |
42 #include "ui/gfx/text_elider.h" | 44 #include "ui/gfx/text_elider.h" |
43 #include "ui/views/controls/button/image_button.h" | 45 #include "ui/views/controls/button/image_button.h" |
| 46 #include "ui/views/rect_based_targeting_utils.h" |
44 #include "ui/views/widget/tooltip_manager.h" | 47 #include "ui/views/widget/tooltip_manager.h" |
45 #include "ui/views/widget/widget.h" | 48 #include "ui/views/widget/widget.h" |
46 #include "ui/views/window/non_client_view.h" | 49 #include "ui/views/window/non_client_view.h" |
47 | 50 |
48 #if defined(OS_WIN) | 51 #if defined(OS_WIN) |
49 #include "win8/util/win8_util.h" | 52 #include "win8/util/win8_util.h" |
50 #endif | 53 #endif |
51 | 54 |
52 #if defined(USE_ASH) | 55 #if defined(USE_ASH) |
53 #include "ui/aura/env.h" | 56 #include "ui/aura/env.h" |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 const SkColor kImmersiveActiveTabColor = SkColorSetRGB(235, 235, 235); | 238 const SkColor kImmersiveActiveTabColor = SkColorSetRGB(235, 235, 235); |
236 const SkColor kImmersiveInactiveTabColor = SkColorSetRGB(190, 190, 190); | 239 const SkColor kImmersiveInactiveTabColor = SkColorSetRGB(190, 190, 190); |
237 | 240 |
238 // The minimum opacity (out of 1) when a tab (either active or inactive) is | 241 // The minimum opacity (out of 1) when a tab (either active or inactive) is |
239 // throbbing in the immersive mode light strip. | 242 // throbbing in the immersive mode light strip. |
240 const double kImmersiveTabMinThrobOpacity = 0.66; | 243 const double kImmersiveTabMinThrobOpacity = 0.66; |
241 | 244 |
242 // Number of steps in the immersive mode loading animation. | 245 // Number of steps in the immersive mode loading animation. |
243 const int kImmersiveLoadingStepCount = 32; | 246 const int kImmersiveLoadingStepCount = 32; |
244 | 247 |
| 248 const char kTabCloseButtonName[] = "TabCloseButton"; |
| 249 |
245 void DrawIconAtLocation(gfx::Canvas* canvas, | 250 void DrawIconAtLocation(gfx::Canvas* canvas, |
246 const gfx::ImageSkia& image, | 251 const gfx::ImageSkia& image, |
247 int image_offset, | 252 int image_offset, |
248 int dst_x, | 253 int dst_x, |
249 int dst_y, | 254 int dst_y, |
250 int icon_width, | 255 int icon_width, |
251 int icon_height, | 256 int icon_height, |
252 bool filter, | 257 bool filter, |
253 const SkPaint& paint) { | 258 const SkPaint& paint) { |
254 // NOTE: the clipping is a work around for 69528, it shouldn't be necessary. | 259 // NOTE: the clipping is a work around for 69528, it shouldn't be necessary. |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 // TabCloseButton | 349 // TabCloseButton |
345 // | 350 // |
346 // This is a Button subclass that causes middle clicks to be forwarded to the | 351 // This is a Button subclass that causes middle clicks to be forwarded to the |
347 // parent View by explicitly not handling them in OnMousePressed. | 352 // parent View by explicitly not handling them in OnMousePressed. |
348 class Tab::TabCloseButton : public views::ImageButton { | 353 class Tab::TabCloseButton : public views::ImageButton { |
349 public: | 354 public: |
350 explicit TabCloseButton(Tab* tab) : views::ImageButton(tab), tab_(tab) {} | 355 explicit TabCloseButton(Tab* tab) : views::ImageButton(tab), tab_(tab) {} |
351 virtual ~TabCloseButton() {} | 356 virtual ~TabCloseButton() {} |
352 | 357 |
353 // Overridden from views::View. | 358 // Overridden from views::View. |
354 virtual View* GetEventHandlerForPoint(const gfx::Point& point) OVERRIDE { | 359 virtual View* GetEventHandlerForRect(const gfx::Rect& rect) OVERRIDE { |
| 360 if (!views::UsePointBasedTargeting(rect)) |
| 361 return View::GetEventHandlerForRect(rect); |
| 362 |
355 // Ignore the padding set on the button. | 363 // Ignore the padding set on the button. |
356 gfx::Rect rect = GetContentsBounds(); | 364 gfx::Rect contents_bounds = GetContentsBounds(); |
357 rect.set_x(GetMirroredXForRect(rect)); | 365 contents_bounds.set_x(GetMirroredXForRect(contents_bounds)); |
358 | 366 |
| 367 // TODO(tdanderson): Remove this ifdef if rect-based targeting |
| 368 // is turned on by default. |
359 #if defined(USE_ASH) | 369 #if defined(USE_ASH) |
360 // Include the padding in hit-test for touch events. | 370 // Include the padding in hit-test for touch events. |
361 if (aura::Env::GetInstance()->is_touch_down()) | 371 if (aura::Env::GetInstance()->is_touch_down()) |
362 rect = GetLocalBounds(); | 372 contents_bounds = GetLocalBounds(); |
363 #elif defined(OS_WIN) | 373 #elif defined(OS_WIN) |
364 // TODO(sky): Use local-bounds if a touch-point is active. | 374 // TODO(sky): Use local-bounds if a touch-point is active. |
365 // http://crbug.com/145258 | 375 // http://crbug.com/145258 |
366 #endif | 376 #endif |
367 | 377 |
368 return rect.Contains(point) ? this : parent(); | 378 return contents_bounds.Intersects(rect) ? this : parent(); |
369 } | 379 } |
370 | 380 |
371 // Overridden from views::View. | 381 // Overridden from views::View. |
372 virtual View* GetTooltipHandlerForPoint(const gfx::Point& point) OVERRIDE { | 382 virtual View* GetTooltipHandlerForPoint(const gfx::Point& point) OVERRIDE { |
373 // Tab close button has no children, so tooltip handler should be the same | 383 // Tab close button has no children, so tooltip handler should be the same |
374 // as the event handler. | 384 // as the event handler. |
375 // In addition, a hit test has to be performed for the point (as | 385 // In addition, a hit test has to be performed for the point (as |
376 // GetTooltipHandlerForPoint() is responsible for it). | 386 // GetTooltipHandlerForPoint() is responsible for it). |
377 if (!HitTestPoint(point)) | 387 if (!HitTestPoint(point)) |
378 return NULL; | 388 return NULL; |
(...skipping 22 matching lines...) Expand all Loading... |
401 CustomButton::OnMouseReleased(event); | 411 CustomButton::OnMouseReleased(event); |
402 } | 412 } |
403 | 413 |
404 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { | 414 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { |
405 // Consume all gesture events here so that the parent (Tab) does not | 415 // Consume all gesture events here so that the parent (Tab) does not |
406 // start consuming gestures. | 416 // start consuming gestures. |
407 ImageButton::OnGestureEvent(event); | 417 ImageButton::OnGestureEvent(event); |
408 event->SetHandled(); | 418 event->SetHandled(); |
409 } | 419 } |
410 | 420 |
| 421 virtual bool HasHitTestMask() const OVERRIDE { |
| 422 return true; |
| 423 } |
| 424 |
| 425 virtual void GetHitTestMask(gfx::Path* path, |
| 426 HitTestSource source = HIT_TEST_SOURCE_MOUSE) const OVERRIDE { |
| 427 // Use the button's contents bounds (which does not include padding) |
| 428 // and the hit test mask of our parent |tab_| to determine if the |
| 429 // button is completely hidden behind another tab. |
| 430 gfx::Path tab_mask; |
| 431 tab_->GetHitTestMask(&tab_mask, source); |
| 432 |
| 433 gfx::Rect button_bounds(GetContentsBounds()); |
| 434 gfx::RectF tab_bounds_f(gfx::SkRectToRectF(tab_mask.getBounds())); |
| 435 views::View::ConvertRectToTarget(tab_, this, &tab_bounds_f); |
| 436 gfx::Rect tab_bounds = gfx::ToEnclosingRect(tab_bounds_f); |
| 437 |
| 438 // If the button is completely hidden behind another tab, the hit test |
| 439 // mask is empty. Otherwise set the hit test mask to be the contents bounds. |
| 440 path->reset(); |
| 441 if (tab_bounds.Contains(button_bounds)) { |
| 442 // Include the padding in the hit test mask for touch events. |
| 443 if (source == HIT_TEST_SOURCE_TOUCH) |
| 444 button_bounds = GetLocalBounds(); |
| 445 |
| 446 path->addRect(RectToSkRect(button_bounds)); |
| 447 } |
| 448 } |
| 449 |
| 450 virtual const char* GetClassName() const OVERRIDE { |
| 451 return kTabCloseButtonName; |
| 452 } |
| 453 |
411 private: | 454 private: |
412 Tab* tab_; | 455 Tab* tab_; |
413 | 456 |
414 DISALLOW_COPY_AND_ASSIGN(TabCloseButton); | 457 DISALLOW_COPY_AND_ASSIGN(TabCloseButton); |
415 }; | 458 }; |
416 | 459 |
417 //////////////////////////////////////////////////////////////////////////////// | 460 //////////////////////////////////////////////////////////////////////////////// |
418 // ImageCacheEntry | 461 // ImageCacheEntry |
419 | 462 |
420 Tab::ImageCacheEntry::ImageCacheEntry() | 463 Tab::ImageCacheEntry::ImageCacheEntry() |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
865 } | 908 } |
866 | 909 |
867 const char* Tab::GetClassName() const { | 910 const char* Tab::GetClassName() const { |
868 return kViewClassName; | 911 return kViewClassName; |
869 } | 912 } |
870 | 913 |
871 bool Tab::HasHitTestMask() const { | 914 bool Tab::HasHitTestMask() const { |
872 return true; | 915 return true; |
873 } | 916 } |
874 | 917 |
875 void Tab::GetHitTestMask(gfx::Path* path) const { | 918 void Tab::GetHitTestMask(gfx::Path* path, HitTestSource source) const { |
876 // When the window is maximized we don't want to shave off the edges or top | 919 // When the window is maximized we don't want to shave off the edges or top |
877 // shadow of the tab, such that the user can click anywhere along the top | 920 // shadow of the tab, such that the user can click anywhere along the top |
878 // edge of the screen to select a tab. Ditto for immersive fullscreen. | 921 // edge of the screen to select a tab. Ditto for immersive fullscreen. |
879 const views::Widget* widget = GetWidget(); | 922 const views::Widget* widget = GetWidget(); |
880 bool include_top_shadow = | 923 bool include_top_shadow = |
881 widget && (widget->IsMaximized() || widget->IsFullscreen()); | 924 widget && (widget->IsMaximized() || widget->IsFullscreen()); |
882 TabResources::GetHitTestMask(width(), height(), include_top_shadow, path); | 925 TabResources::GetHitTestMask(width(), height(), include_top_shadow, path); |
| 926 |
| 927 // It is possible for a portion of the tab to be occluded if tabs are |
| 928 // stacked, so modify the hit test mask to only include the visible |
| 929 // region of the tab. |
| 930 if (controller()) { |
| 931 gfx::Rect clip; |
| 932 controller()->ShouldPaintTab(this, &clip); |
| 933 if (clip.size().GetArea()) { |
| 934 SkRect intersection(path->getBounds()); |
| 935 intersection.intersect(RectToSkRect(clip)); |
| 936 path->reset(); |
| 937 path->addRect(intersection); |
| 938 } |
| 939 } |
883 } | 940 } |
884 | 941 |
885 bool Tab::GetTooltipText(const gfx::Point& p, string16* tooltip) const { | 942 bool Tab::GetTooltipText(const gfx::Point& p, string16* tooltip) const { |
886 // TODO(miu): Rectify inconsistent tooltip behavior. http://crbug.com/310947 | 943 // TODO(miu): Rectify inconsistent tooltip behavior. http://crbug.com/310947 |
887 | 944 |
888 if (data_.media_state != TAB_MEDIA_STATE_NONE) { | 945 if (data_.media_state != TAB_MEDIA_STATE_NONE) { |
889 *tooltip = chrome::AssembleTabTooltipText(data_.title, data_.media_state); | 946 *tooltip = chrome::AssembleTabTooltipText(data_.title, data_.media_state); |
890 return true; | 947 return true; |
891 } | 948 } |
892 | 949 |
(...skipping 838 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1731 const gfx::ImageSkia& image) { | 1788 const gfx::ImageSkia& image) { |
1732 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); | 1789 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); |
1733 ImageCacheEntry entry; | 1790 ImageCacheEntry entry; |
1734 entry.resource_id = resource_id; | 1791 entry.resource_id = resource_id; |
1735 entry.scale_factor = scale_factor; | 1792 entry.scale_factor = scale_factor; |
1736 entry.image = image; | 1793 entry.image = image; |
1737 image_cache_->push_front(entry); | 1794 image_cache_->push_front(entry); |
1738 if (image_cache_->size() > kMaxImageCacheSize) | 1795 if (image_cache_->size() > kMaxImageCacheSize) |
1739 image_cache_->pop_back(); | 1796 image_cache_->pop_back(); |
1740 } | 1797 } |
OLD | NEW |