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 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 |
245 // Scale to resize the current favicon by when projecting. | 248 // Scale to resize the current favicon by when projecting. |
246 const double kProjectingFaviconResizeScale = 0.75; | 249 const double kProjectingFaviconResizeScale = 0.75; |
247 | 250 |
248 // Scale to resize the projection sheet glow by. | 251 // Scale to resize the projection sheet glow by. |
249 const double kProjectingGlowResizeScale = 2.0; | 252 const double kProjectingGlowResizeScale = 2.0; |
250 | 253 |
| 254 const char kTabCloseButtonName[] = "TabCloseButton"; |
| 255 |
251 void DrawIconAtLocation(gfx::Canvas* canvas, | 256 void DrawIconAtLocation(gfx::Canvas* canvas, |
252 const gfx::ImageSkia& image, | 257 const gfx::ImageSkia& image, |
253 int image_offset, | 258 int image_offset, |
254 int dst_x, | 259 int dst_x, |
255 int dst_y, | 260 int dst_y, |
256 int icon_width, | 261 int icon_width, |
257 int icon_height, | 262 int icon_height, |
258 bool filter, | 263 bool filter, |
259 const SkPaint& paint) { | 264 const SkPaint& paint) { |
260 // NOTE: the clipping is a work around for 69528, it shouldn't be necessary. | 265 // 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... |
350 // TabCloseButton | 355 // TabCloseButton |
351 // | 356 // |
352 // This is a Button subclass that causes middle clicks to be forwarded to the | 357 // This is a Button subclass that causes middle clicks to be forwarded to the |
353 // parent View by explicitly not handling them in OnMousePressed. | 358 // parent View by explicitly not handling them in OnMousePressed. |
354 class Tab::TabCloseButton : public views::ImageButton { | 359 class Tab::TabCloseButton : public views::ImageButton { |
355 public: | 360 public: |
356 explicit TabCloseButton(Tab* tab) : views::ImageButton(tab), tab_(tab) {} | 361 explicit TabCloseButton(Tab* tab) : views::ImageButton(tab), tab_(tab) {} |
357 virtual ~TabCloseButton() {} | 362 virtual ~TabCloseButton() {} |
358 | 363 |
359 // Overridden from views::View. | 364 // Overridden from views::View. |
360 virtual View* GetEventHandlerForPoint(const gfx::Point& point) OVERRIDE { | 365 virtual View* GetEventHandlerForRect(const gfx::Rect& rect) OVERRIDE { |
| 366 if (!views::UsePointBasedTargeting(rect)) |
| 367 return View::GetEventHandlerForRect(rect); |
| 368 |
361 // Ignore the padding set on the button. | 369 // Ignore the padding set on the button. |
362 gfx::Rect rect = GetContentsBounds(); | 370 gfx::Rect contents_bounds = GetContentsBounds(); |
363 rect.set_x(GetMirroredXForRect(rect)); | 371 contents_bounds.set_x(GetMirroredXForRect(contents_bounds)); |
364 | 372 |
365 #if defined(USE_ASH) | 373 #if defined(USE_ASH) |
366 // Include the padding in hit-test for touch events. | 374 // Include the padding in hit-test for touch events. |
367 if (aura::Env::GetInstance()->is_touch_down()) | 375 if (aura::Env::GetInstance()->is_touch_down()) |
368 rect = GetLocalBounds(); | 376 contents_bounds = GetLocalBounds(); |
369 #elif defined(OS_WIN) | 377 #elif defined(OS_WIN) |
370 // TODO(sky): Use local-bounds if a touch-point is active. | 378 // TODO(sky): Use local-bounds if a touch-point is active. |
371 // http://crbug.com/145258 | 379 // http://crbug.com/145258 |
372 #endif | 380 #endif |
373 | 381 |
374 return rect.Contains(point) ? this : parent(); | 382 return contents_bounds.Intersects(rect) ? this : parent(); |
375 } | 383 } |
376 | 384 |
377 // Overridden from views::View. | 385 // Overridden from views::View. |
378 virtual View* GetTooltipHandlerForPoint(const gfx::Point& point) OVERRIDE { | 386 virtual View* GetTooltipHandlerForPoint(const gfx::Point& point) OVERRIDE { |
379 // Tab close button has no children, so tooltip handler should be the same | 387 // Tab close button has no children, so tooltip handler should be the same |
380 // as the event handler. | 388 // as the event handler. |
381 // In addition, a hit test has to be performed for the point (as | 389 // In addition, a hit test has to be performed for the point (as |
382 // GetTooltipHandlerForPoint() is responsible for it). | 390 // GetTooltipHandlerForPoint() is responsible for it). |
383 if (!HitTestPoint(point)) | 391 if (!HitTestPoint(point)) |
384 return NULL; | 392 return NULL; |
(...skipping 22 matching lines...) Expand all Loading... |
407 CustomButton::OnMouseReleased(event); | 415 CustomButton::OnMouseReleased(event); |
408 } | 416 } |
409 | 417 |
410 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { | 418 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { |
411 // Consume all gesture events here so that the parent (Tab) does not | 419 // Consume all gesture events here so that the parent (Tab) does not |
412 // start consuming gestures. | 420 // start consuming gestures. |
413 ImageButton::OnGestureEvent(event); | 421 ImageButton::OnGestureEvent(event); |
414 event->SetHandled(); | 422 event->SetHandled(); |
415 } | 423 } |
416 | 424 |
| 425 virtual bool HasHitTestMask() const OVERRIDE { |
| 426 return true; |
| 427 } |
| 428 |
| 429 virtual void GetHitTestMask(gfx::Path* path) const OVERRIDE { |
| 430 // Use the button's contents bounds (which does not include padding) |
| 431 // and the hit test mask of our parent |tab_| to determine if the |
| 432 // button is completely hidden behind another tab. |
| 433 gfx::Path tab_mask; |
| 434 tab_->GetHitTestMask(&tab_mask); |
| 435 |
| 436 gfx::Rect button_bounds(GetContentsBounds()); |
| 437 gfx::Rect tab_bounds( |
| 438 gfx::ToEnclosingRect(gfx::SkRectToRectF(tab_mask.getBounds()))); |
| 439 views::View::ConvertRectToTarget(tab_, this, &tab_bounds); |
| 440 |
| 441 // If the button is completely hidden behind another tab, the hit test |
| 442 // mask is empty. Otherwise set the hit test mask to be the contents bounds. |
| 443 path->reset(); |
| 444 if (tab_bounds.Contains(button_bounds)) { |
| 445 #if defined(USE_ASH) |
| 446 // Include the padding in the hit test mask for touch events. |
| 447 if (aura::Env::GetInstance()->is_touch_down()) |
| 448 button_bounds = GetLocalBounds(); |
| 449 #endif |
| 450 path->addRect(RectToSkRect(button_bounds)); |
| 451 } |
| 452 } |
| 453 |
| 454 virtual const char* GetClassName() const OVERRIDE { |
| 455 return kTabCloseButtonName; |
| 456 } |
| 457 |
417 private: | 458 private: |
418 Tab* tab_; | 459 Tab* tab_; |
419 | 460 |
420 DISALLOW_COPY_AND_ASSIGN(TabCloseButton); | 461 DISALLOW_COPY_AND_ASSIGN(TabCloseButton); |
421 }; | 462 }; |
422 | 463 |
423 //////////////////////////////////////////////////////////////////////////////// | 464 //////////////////////////////////////////////////////////////////////////////// |
424 // ImageCacheEntry | 465 // ImageCacheEntry |
425 | 466 |
426 Tab::ImageCacheEntry::ImageCacheEntry() | 467 Tab::ImageCacheEntry::ImageCacheEntry() |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
875 } | 916 } |
876 | 917 |
877 void Tab::GetHitTestMask(gfx::Path* path) const { | 918 void Tab::GetHitTestMask(gfx::Path* path) const { |
878 // 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 |
879 // 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 |
880 // 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. |
881 const views::Widget* widget = GetWidget(); | 922 const views::Widget* widget = GetWidget(); |
882 bool include_top_shadow = | 923 bool include_top_shadow = |
883 widget && (widget->IsMaximized() || widget->IsFullscreen()); | 924 widget && (widget->IsMaximized() || widget->IsFullscreen()); |
884 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 } |
885 } | 940 } |
886 | 941 |
887 bool Tab::GetTooltipText(const gfx::Point& p, string16* tooltip) const { | 942 bool Tab::GetTooltipText(const gfx::Point& p, string16* tooltip) const { |
888 if (data_.title.empty()) | 943 if (data_.title.empty()) |
889 return false; | 944 return false; |
890 | 945 |
891 // Only show the tooltip if the title is truncated. | 946 // Only show the tooltip if the title is truncated. |
892 if (font_->GetStringWidth(data_.title) > GetTitleBounds().width()) { | 947 if (font_->GetStringWidth(data_.title) > GetTitleBounds().width()) { |
893 *tooltip = data_.title; | 948 *tooltip = data_.title; |
894 return true; | 949 return true; |
(...skipping 979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1874 const gfx::ImageSkia& image) { | 1929 const gfx::ImageSkia& image) { |
1875 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); | 1930 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); |
1876 ImageCacheEntry entry; | 1931 ImageCacheEntry entry; |
1877 entry.resource_id = resource_id; | 1932 entry.resource_id = resource_id; |
1878 entry.scale_factor = scale_factor; | 1933 entry.scale_factor = scale_factor; |
1879 entry.image = image; | 1934 entry.image = image; |
1880 image_cache_->push_front(entry); | 1935 image_cache_->push_front(entry); |
1881 if (image_cache_->size() > kMaxImageCacheSize) | 1936 if (image_cache_->size() > kMaxImageCacheSize) |
1882 image_cache_->pop_back(); | 1937 image_cache_->pop_back(); |
1883 } | 1938 } |
OLD | NEW |