| 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_strip.h" | 5 #include "chrome/browser/ui/views/tabs/tab_strip.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 25 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" | 25 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h" |
| 26 #include "grit/generated_resources.h" | 26 #include "grit/generated_resources.h" |
| 27 #include "grit/theme_resources.h" | 27 #include "grit/theme_resources.h" |
| 28 #include "grit/theme_resources_standard.h" | 28 #include "grit/theme_resources_standard.h" |
| 29 #include "ui/base/accessibility/accessible_view_state.h" | 29 #include "ui/base/accessibility/accessible_view_state.h" |
| 30 #include "ui/base/animation/animation_container.h" | 30 #include "ui/base/animation/animation_container.h" |
| 31 #include "ui/base/animation/throb_animation.h" | 31 #include "ui/base/animation/throb_animation.h" |
| 32 #include "ui/base/dragdrop/drag_drop_types.h" | 32 #include "ui/base/dragdrop/drag_drop_types.h" |
| 33 #include "ui/base/l10n/l10n_util.h" | 33 #include "ui/base/l10n/l10n_util.h" |
| 34 #include "ui/base/resource/resource_bundle.h" | 34 #include "ui/base/resource/resource_bundle.h" |
| 35 #include "ui/base/scale.h" |
| 35 #include "ui/base/touch/touch_mode_support.h" | 36 #include "ui/base/touch/touch_mode_support.h" |
| 36 #include "ui/gfx/canvas.h" | 37 #include "ui/gfx/canvas.h" |
| 37 #include "ui/gfx/path.h" | 38 #include "ui/gfx/path.h" |
| 38 #include "ui/gfx/size.h" | 39 #include "ui/gfx/size.h" |
| 39 #include "ui/gfx/skbitmap_operations.h" | 40 #include "ui/gfx/skbitmap_operations.h" |
| 40 #include "ui/views/controls/image_view.h" | 41 #include "ui/views/controls/image_view.h" |
| 41 #include "ui/views/mouse_watcher_view_host.h" | 42 #include "ui/views/mouse_watcher_view_host.h" |
| 42 #include "ui/views/view_model_utils.h" | 43 #include "ui/views/view_model_utils.h" |
| 43 #include "ui/views/widget/default_theme_provider.h" | 44 #include "ui/views/widget/default_theme_provider.h" |
| 44 #include "ui/views/widget/root_view.h" | 45 #include "ui/views/widget/root_view.h" |
| 45 #include "ui/views/widget/widget.h" | 46 #include "ui/views/widget/widget.h" |
| 46 #include "ui/views/window/non_client_view.h" | 47 #include "ui/views/window/non_client_view.h" |
| 47 | 48 |
| 48 #if defined(OS_WIN) | 49 #if defined(OS_WIN) |
| 49 #include "ui/base/win/hwnd_util.h" | 50 #include "ui/base/win/hwnd_util.h" |
| 50 #include "ui/views/widget/monitor_win.h" | 51 #include "ui/views/widget/monitor_win.h" |
| 51 #endif | 52 #endif |
| 52 | 53 |
| 53 using views::DropTargetEvent; | 54 using views::DropTargetEvent; |
| 54 | 55 |
| 55 // Offset for the new tab button to bring it closer to the rightmost tab. | 56 namespace { |
| 56 #if defined(USE_ASH) | 57 |
| 57 static const int kNewTabButtonHOffset = -11; | 58 // Offsets for the new tab button to bring it closer to the rightmost tab. |
| 58 static const int kNewTabButtonVOffset = 7; | 59 |
| 59 #else | 60 const int GetNewTabButtonHOffset() { |
| 60 static const int kNewTabButtonHOffset = -5; | 61 switch (ui::GetDisplayScale()) { |
| 61 static const int kNewTabButtonVOffset = 5; | 62 case ui::DS_ASH: |
| 62 #endif | 63 return -11; |
| 64 case ui::DS_METRO_100: |
| 65 case ui::DS_METRO_140: |
| 66 case ui::DS_METRO_180: |
| 67 // TODO(joi): Metro scales other than 100%. |
| 68 return -6; |
| 69 default: |
| 70 return -5; |
| 71 } |
| 72 } |
| 73 |
| 74 const int GetNewTabButtonVOffset() { |
| 75 switch (ui::GetDisplayScale()) { |
| 76 case ui::DS_ASH: |
| 77 return 7; |
| 78 case ui::DS_METRO_100: |
| 79 case ui::DS_METRO_140: |
| 80 case ui::DS_METRO_180: |
| 81 // TODO(joi): Metro scales other than 100%. |
| 82 return 10; |
| 83 default: |
| 84 return 5; |
| 85 } |
| 86 } |
| 87 |
| 63 // Amount the left edge of a tab is offset from the rectangle of the tab's | 88 // Amount the left edge of a tab is offset from the rectangle of the tab's |
| 64 // favicon/title/close box. Related to the width of IDR_TAB_ACTIVE_LEFT. | 89 // favicon/title/close box. Related to the width of IDR_TAB_ACTIVE_LEFT. |
| 65 #if defined(USE_ASH) | 90 |
| 66 static const int kTabHOffset = -27; | 91 const int GetTabHOffset() { |
| 67 #else | 92 switch (ui::GetDisplayScale()) { |
| 68 static const int kTabHOffset = -16; | 93 case ui::DS_ASH: |
| 69 #endif | 94 return -27; |
| 95 case ui::DS_METRO_100: |
| 96 case ui::DS_METRO_140: |
| 97 case ui::DS_METRO_180: |
| 98 // TODO(joi): Metro scales other than 100%. |
| 99 return -16; |
| 100 default: |
| 101 return -16; |
| 102 } |
| 103 } |
| 104 |
| 70 static const int kTabStripAnimationVSlop = 40; | 105 static const int kTabStripAnimationVSlop = 40; |
| 71 // Inactive tabs in a native frame are slightly transparent. | 106 // Inactive tabs in a native frame are slightly transparent. |
| 72 static const int kNativeFrameInactiveTabAlpha = 200; | 107 static const int kNativeFrameInactiveTabAlpha = 200; |
| 73 // If there are multiple tabs selected then make non-selected inactive tabs | 108 // If there are multiple tabs selected then make non-selected inactive tabs |
| 74 // even more transparent. | 109 // even more transparent. |
| 75 static const int kNativeFrameInactiveTabAlphaMultiSelection = 150; | 110 static const int kNativeFrameInactiveTabAlphaMultiSelection = 150; |
| 76 | 111 |
| 77 // Inverse ratio of the width of a tab edge to the width of the tab. When | 112 // Inverse ratio of the width of a tab edge to the width of the tab. When |
| 78 // hovering over the left or right edge of a tab, the drop indicator will | 113 // hovering over the left or right edge of a tab, the drop indicator will |
| 79 // point between tabs. | 114 // point between tabs. |
| 80 static const int kTabEdgeRatioInverse = 4; | 115 static const int kTabEdgeRatioInverse = 4; |
| 81 | 116 |
| 82 // Size of the drop indicator. | 117 // Size of the drop indicator. |
| 83 static int drop_indicator_width; | 118 static int drop_indicator_width; |
| 84 static int drop_indicator_height; | 119 static int drop_indicator_height; |
| 85 | 120 |
| 86 static inline int Round(double x) { | 121 static inline int Round(double x) { |
| 87 // Why oh why is this not in a standard header? | 122 // Why oh why is this not in a standard header? |
| 88 return static_cast<int>(floor(x + 0.5)); | 123 return static_cast<int>(floor(x + 0.5)); |
| 89 } | 124 } |
| 90 | 125 |
| 91 // Max width reserved for stacked tabs along a particular edge. | 126 // Max width reserved for stacked tabs along a particular edge. |
| 92 static const double kMaxEdgeStackWidth = 24; | 127 static const double kMaxEdgeStackWidth = 24; |
| 93 | 128 |
| 94 namespace { | |
| 95 | |
| 96 // Animation delegate used when a dragged tab is released. When done sets the | 129 // Animation delegate used when a dragged tab is released. When done sets the |
| 97 // dragging state to false. | 130 // dragging state to false. |
| 98 class ResetDraggingStateDelegate | 131 class ResetDraggingStateDelegate |
| 99 : public views::BoundsAnimator::OwnedAnimationDelegate { | 132 : public views::BoundsAnimator::OwnedAnimationDelegate { |
| 100 public: | 133 public: |
| 101 explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) { | 134 explicit ResetDraggingStateDelegate(BaseTab* tab) : tab_(tab) { |
| 102 } | 135 } |
| 103 | 136 |
| 104 virtual void AnimationEnded(const ui::Animation* animation) { | 137 virtual void AnimationEnded(const ui::Animation* animation) { |
| 105 tab_->set_dragging(false); | 138 tab_->set_dragging(false); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 int height = mask->height(); | 277 int height = mask->height(); |
| 245 int width = mask->width(); | 278 int width = mask->width(); |
| 246 gfx::Canvas canvas(gfx::Size(width, height), false); | 279 gfx::Canvas canvas(gfx::Size(width, height), false); |
| 247 | 280 |
| 248 // For custom images the background starts at the top of the tab strip. | 281 // For custom images the background starts at the top of the tab strip. |
| 249 // Otherwise the background starts at the top of the frame. | 282 // Otherwise the background starts at the top of the frame. |
| 250 SkBitmap* background = GetThemeProvider()->GetBitmapNamed(background_id); | 283 SkBitmap* background = GetThemeProvider()->GetBitmapNamed(background_id); |
| 251 int offset_y = GetThemeProvider()->HasCustomImage(background_id) ? | 284 int offset_y = GetThemeProvider()->HasCustomImage(background_id) ? |
| 252 0 : background_offset_.y(); | 285 0 : background_offset_.y(); |
| 253 canvas.TileImageInt(*background, GetMirroredX() + background_offset_.x(), | 286 canvas.TileImageInt(*background, GetMirroredX() + background_offset_.x(), |
| 254 kNewTabButtonVOffset + offset_y, 0, 0, width, height); | 287 GetNewTabButtonVOffset() + offset_y, 0, 0, width, height); |
| 255 | 288 |
| 256 if (alpha != 255) { | 289 if (alpha != 255) { |
| 257 SkPaint paint; | 290 SkPaint paint; |
| 258 paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); | 291 paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); |
| 259 paint.setXfermodeMode(SkXfermode::kDstIn_Mode); | 292 paint.setXfermodeMode(SkXfermode::kDstIn_Mode); |
| 260 paint.setStyle(SkPaint::kFill_Style); | 293 paint.setStyle(SkPaint::kFill_Style); |
| 261 canvas.DrawRect(gfx::Rect(0, 0, width, height), paint); | 294 canvas.DrawRect(gfx::Rect(0, 0, width, height), paint); |
| 262 } | 295 } |
| 263 | 296 |
| 264 // White highlight on hover. | 297 // White highlight on hover. |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 | 527 |
| 495 int model_count = GetModelCount(); | 528 int model_count = GetModelCount(); |
| 496 if (model_index + 1 != model_count && model_count > 1) { | 529 if (model_index + 1 != model_count && model_count > 1) { |
| 497 // The user is about to close a tab other than the last tab. Set | 530 // The user is about to close a tab other than the last tab. Set |
| 498 // available_width_for_tabs_ so that if we do a layout we don't position a | 531 // available_width_for_tabs_ so that if we do a layout we don't position a |
| 499 // tab past the end of the second to last tab. We do this so that as the | 532 // tab past the end of the second to last tab. We do this so that as the |
| 500 // user closes tabs with the mouse a tab continues to fall under the mouse. | 533 // user closes tabs with the mouse a tab continues to fall under the mouse. |
| 501 Tab* last_tab = tab_at(model_count - 1); | 534 Tab* last_tab = tab_at(model_count - 1); |
| 502 Tab* tab_being_removed = tab_at(model_index); | 535 Tab* tab_being_removed = tab_at(model_index); |
| 503 available_width_for_tabs_ = last_tab->x() + last_tab->width() - | 536 available_width_for_tabs_ = last_tab->x() + last_tab->width() - |
| 504 tab_being_removed->width() - kTabHOffset; | 537 tab_being_removed->width() - GetTabHOffset(); |
| 505 if (model_index == 0 && tab_being_removed->data().mini && | 538 if (model_index == 0 && tab_being_removed->data().mini && |
| 506 !tab_at(1)->data().mini) { | 539 !tab_at(1)->data().mini) { |
| 507 available_width_for_tabs_ -= kMiniToNonMiniGap; | 540 available_width_for_tabs_ -= kMiniToNonMiniGap; |
| 508 } | 541 } |
| 509 } | 542 } |
| 510 | 543 |
| 511 in_tab_close_ = true; | 544 in_tab_close_ = true; |
| 512 AddMessageLoopObserver(); | 545 AddMessageLoopObserver(); |
| 513 } | 546 } |
| 514 | 547 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 919 std::string TabStrip::GetClassName() const { | 952 std::string TabStrip::GetClassName() const { |
| 920 return kViewClassName; | 953 return kViewClassName; |
| 921 } | 954 } |
| 922 | 955 |
| 923 gfx::Size TabStrip::GetPreferredSize() { | 956 gfx::Size TabStrip::GetPreferredSize() { |
| 924 // Report the minimum width as the size required for a single selected tab | 957 // Report the minimum width as the size required for a single selected tab |
| 925 // plus the new tab button. Don't base it on the actual number of tabs because | 958 // plus the new tab button. Don't base it on the actual number of tabs because |
| 926 // it's undesirable to have the minimum window size change when a new tab is | 959 // it's undesirable to have the minimum window size change when a new tab is |
| 927 // opened. | 960 // opened. |
| 928 int needed_width = Tab::GetMinimumSelectedSize().width(); | 961 int needed_width = Tab::GetMinimumSelectedSize().width(); |
| 929 needed_width += kNewTabButtonHOffset - kTabHOffset; | 962 needed_width += GetNewTabButtonHOffset() - GetTabHOffset(); |
| 930 needed_width += newtab_button_bounds_.width(); | 963 needed_width += newtab_button_bounds_.width(); |
| 931 return gfx::Size(needed_width, Tab::GetMinimumUnselectedSize().height()); | 964 return gfx::Size(needed_width, Tab::GetMinimumUnselectedSize().height()); |
| 932 } | 965 } |
| 933 | 966 |
| 934 void TabStrip::OnDragEntered(const DropTargetEvent& event) { | 967 void TabStrip::OnDragEntered(const DropTargetEvent& event) { |
| 935 // Force animations to stop, otherwise it makes the index calculation tricky. | 968 // Force animations to stop, otherwise it makes the index calculation tricky. |
| 936 StopAnimating(true); | 969 StopAnimating(true); |
| 937 | 970 |
| 938 UpdateDropIndex(event); | 971 UpdateDropIndex(event); |
| 939 } | 972 } |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1096 available_width_for_tabs_ = -1; | 1129 available_width_for_tabs_ = -1; |
| 1097 | 1130 |
| 1098 GenerateIdealBounds(); | 1131 GenerateIdealBounds(); |
| 1099 | 1132 |
| 1100 BaseTab* tab = tab_at(model_index); | 1133 BaseTab* tab = tab_at(model_index); |
| 1101 if (model_index == 0) { | 1134 if (model_index == 0) { |
| 1102 tab->SetBounds(0, ideal_bounds(model_index).y(), 0, | 1135 tab->SetBounds(0, ideal_bounds(model_index).y(), 0, |
| 1103 ideal_bounds(model_index).height()); | 1136 ideal_bounds(model_index).height()); |
| 1104 } else { | 1137 } else { |
| 1105 BaseTab* last_tab = tab_at(model_index - 1); | 1138 BaseTab* last_tab = tab_at(model_index - 1); |
| 1106 tab->SetBounds(last_tab->bounds().right() + kTabHOffset, | 1139 tab->SetBounds(last_tab->bounds().right() + GetTabHOffset(), |
| 1107 ideal_bounds(model_index).y(), 0, | 1140 ideal_bounds(model_index).y(), 0, |
| 1108 ideal_bounds(model_index).height()); | 1141 ideal_bounds(model_index).height()); |
| 1109 } | 1142 } |
| 1110 | 1143 |
| 1111 AnimateToIdealBounds(); | 1144 AnimateToIdealBounds(); |
| 1112 } | 1145 } |
| 1113 | 1146 |
| 1114 void TabStrip::StartMoveTabAnimation() { | 1147 void TabStrip::StartMoveTabAnimation() { |
| 1115 PrepareForAnimation(); | 1148 PrepareForAnimation(); |
| 1116 GenerateIdealBounds(); | 1149 GenerateIdealBounds(); |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1181 GenerateIdealBounds(); | 1214 GenerateIdealBounds(); |
| 1182 | 1215 |
| 1183 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); | 1216 views::ViewModelUtils::SetViewBoundsToIdealBounds(tabs_); |
| 1184 | 1217 |
| 1185 SchedulePaint(); | 1218 SchedulePaint(); |
| 1186 | 1219 |
| 1187 // It is possible we don't have a new tab button yet. | 1220 // It is possible we don't have a new tab button yet. |
| 1188 if (newtab_button_) { | 1221 if (newtab_button_) { |
| 1189 if (SizeTabButtonToTopOfTabStrip()) { | 1222 if (SizeTabButtonToTopOfTabStrip()) { |
| 1190 newtab_button_bounds_.set_height( | 1223 newtab_button_bounds_.set_height( |
| 1191 kNewTabButtonHeight + kNewTabButtonVOffset); | 1224 kNewTabButtonHeight + GetNewTabButtonVOffset()); |
| 1192 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, | 1225 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
| 1193 views::ImageButton::ALIGN_BOTTOM); | 1226 views::ImageButton::ALIGN_BOTTOM); |
| 1194 } else { | 1227 } else { |
| 1195 newtab_button_bounds_.set_height(kNewTabButtonHeight); | 1228 newtab_button_bounds_.set_height(kNewTabButtonHeight); |
| 1196 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, | 1229 newtab_button_->SetImageAlignment(views::ImageButton::ALIGN_LEFT, |
| 1197 views::ImageButton::ALIGN_TOP); | 1230 views::ImageButton::ALIGN_TOP); |
| 1198 } | 1231 } |
| 1199 newtab_button_->SetBoundsRect(newtab_button_bounds_); | 1232 newtab_button_->SetBoundsRect(newtab_button_bounds_); |
| 1200 } | 1233 } |
| 1201 } | 1234 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1246 void TabStrip::CalculateBoundsForDraggedTabs(const std::vector<BaseTab*>& tabs, | 1279 void TabStrip::CalculateBoundsForDraggedTabs(const std::vector<BaseTab*>& tabs, |
| 1247 std::vector<gfx::Rect>* bounds) { | 1280 std::vector<gfx::Rect>* bounds) { |
| 1248 int x = 0; | 1281 int x = 0; |
| 1249 for (size_t i = 0; i < tabs.size(); ++i) { | 1282 for (size_t i = 0; i < tabs.size(); ++i) { |
| 1250 BaseTab* tab = tabs[i]; | 1283 BaseTab* tab = tabs[i]; |
| 1251 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) | 1284 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) |
| 1252 x += kMiniToNonMiniGap; | 1285 x += kMiniToNonMiniGap; |
| 1253 gfx::Rect new_bounds = tab->bounds(); | 1286 gfx::Rect new_bounds = tab->bounds(); |
| 1254 new_bounds.set_origin(gfx::Point(x, 0)); | 1287 new_bounds.set_origin(gfx::Point(x, 0)); |
| 1255 bounds->push_back(new_bounds); | 1288 bounds->push_back(new_bounds); |
| 1256 x += tab->width() + kTabHOffset; | 1289 x += tab->width() + GetTabHOffset(); |
| 1257 } | 1290 } |
| 1258 } | 1291 } |
| 1259 | 1292 |
| 1260 int TabStrip::GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) { | 1293 int TabStrip::GetSizeNeededForTabs(const std::vector<BaseTab*>& tabs) { |
| 1261 int width = 0; | 1294 int width = 0; |
| 1262 for (size_t i = 0; i < tabs.size(); ++i) { | 1295 for (size_t i = 0; i < tabs.size(); ++i) { |
| 1263 BaseTab* tab = tabs[i]; | 1296 BaseTab* tab = tabs[i]; |
| 1264 width += tab->width(); | 1297 width += tab->width(); |
| 1265 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) | 1298 if (i > 0 && tab->data().mini != tabs[i - 1]->data().mini) |
| 1266 width += kMiniToNonMiniGap; | 1299 width += kMiniToNonMiniGap; |
| 1267 } | 1300 } |
| 1268 if (tabs.size() > 0) | 1301 if (tabs.size() > 0) |
| 1269 width += kTabHOffset * static_cast<int>(tabs.size() - 1); | 1302 width += GetTabHOffset() * static_cast<int>(tabs.size() - 1); |
| 1270 return width; | 1303 return width; |
| 1271 } | 1304 } |
| 1272 | 1305 |
| 1273 void TabStrip::RemoveTabFromViewModel(int index) { | 1306 void TabStrip::RemoveTabFromViewModel(int index) { |
| 1274 // We still need to paint the tab until we actually remove it. Put it | 1307 // We still need to paint the tab until we actually remove it. Put it |
| 1275 // in tabs_closing_map_ so we can find it. | 1308 // in tabs_closing_map_ so we can find it. |
| 1276 tabs_closing_map_[index].push_back(tab_at(index)); | 1309 tabs_closing_map_[index].push_back(tab_at(index)); |
| 1277 UpdateTabsClosingMap(index + 1, -1); | 1310 UpdateTabsClosingMap(index + 1, -1); |
| 1278 tabs_.Remove(index); | 1311 tabs_.Remove(index); |
| 1279 } | 1312 } |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1398 for (int i = index1; i < index2; ++i) { | 1431 for (int i = index1; i < index2; ++i) { |
| 1399 if (!tab_at(i)->closing()) | 1432 if (!tab_at(i)->closing()) |
| 1400 count++; | 1433 count++; |
| 1401 } | 1434 } |
| 1402 return count; | 1435 return count; |
| 1403 } | 1436 } |
| 1404 | 1437 |
| 1405 void TabStrip::UpdateNumVisibleTabs(int non_closing_tab_count, | 1438 void TabStrip::UpdateNumVisibleTabs(int non_closing_tab_count, |
| 1406 int width, | 1439 int width, |
| 1407 double tab_size) { | 1440 double tab_size) { |
| 1408 num_visible_tabs_ = (width + kTabHOffset) / (tab_size + kTabHOffset); | 1441 num_visible_tabs_ = (width + GetTabHOffset()) / (tab_size + GetTabHOffset()); |
| 1409 num_visible_tabs_ = std::max(1, num_visible_tabs_); | 1442 num_visible_tabs_ = std::max(1, num_visible_tabs_); |
| 1410 // Make sure the first_visible_tab_index_ is valid. | 1443 // Make sure the first_visible_tab_index_ is valid. |
| 1411 // TODO: this isn't quite right, it doesn't take into account closing tabs. | 1444 // TODO: this isn't quite right, it doesn't take into account closing tabs. |
| 1412 first_visible_tab_index_ = | 1445 first_visible_tab_index_ = |
| 1413 std::min(first_visible_tab_index_, non_closing_tab_count - | 1446 std::min(first_visible_tab_index_, non_closing_tab_count - |
| 1414 num_visible_tabs_); | 1447 num_visible_tabs_); |
| 1415 first_visible_tab_index_ = std::max(0, first_visible_tab_index_); | 1448 first_visible_tab_index_ = std::max(0, first_visible_tab_index_); |
| 1416 } | 1449 } |
| 1417 | 1450 |
| 1418 void TabStrip::EnsureModelIndexIsVisible(int model_index) { | 1451 void TabStrip::EnsureModelIndexIsVisible(int model_index) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1446 | 1479 |
| 1447 if (tab_count == 0) { | 1480 if (tab_count == 0) { |
| 1448 // Return immediately to avoid divide-by-zero below. | 1481 // Return immediately to avoid divide-by-zero below. |
| 1449 return; | 1482 return; |
| 1450 } | 1483 } |
| 1451 | 1484 |
| 1452 // Determine how much space we can actually allocate to tabs. | 1485 // Determine how much space we can actually allocate to tabs. |
| 1453 int available_width; | 1486 int available_width; |
| 1454 if (available_width_for_tabs_ < 0) { | 1487 if (available_width_for_tabs_ < 0) { |
| 1455 available_width = width(); | 1488 available_width = width(); |
| 1456 available_width -= (kNewTabButtonHOffset + newtab_button_bounds_.width()); | 1489 available_width -= |
| 1490 (GetNewTabButtonHOffset() + newtab_button_bounds_.width()); |
| 1457 } else { | 1491 } else { |
| 1458 // Interesting corner case: if |available_width_for_tabs_| > the result | 1492 // Interesting corner case: if |available_width_for_tabs_| > the result |
| 1459 // of the calculation in the conditional arm above, the strip is in | 1493 // of the calculation in the conditional arm above, the strip is in |
| 1460 // overflow. We can either use the specified width or the true available | 1494 // overflow. We can either use the specified width or the true available |
| 1461 // width here; the first preserves the consistent "leave the last tab under | 1495 // width here; the first preserves the consistent "leave the last tab under |
| 1462 // the user's mouse so they can close many tabs" behavior at the cost of | 1496 // the user's mouse so they can close many tabs" behavior at the cost of |
| 1463 // prolonging the glitchy appearance of the overflow state, while the second | 1497 // prolonging the glitchy appearance of the overflow state, while the second |
| 1464 // gets us out of overflow as soon as possible but forces the user to move | 1498 // gets us out of overflow as soon as possible but forces the user to move |
| 1465 // their mouse for a few tabs' worth of closing. We choose visual | 1499 // their mouse for a few tabs' worth of closing. We choose visual |
| 1466 // imperfection over behavioral imperfection and select the first option. | 1500 // imperfection over behavioral imperfection and select the first option. |
| 1467 available_width = available_width_for_tabs_; | 1501 available_width = available_width_for_tabs_; |
| 1468 } | 1502 } |
| 1469 | 1503 |
| 1470 if (mini_tab_count > 0) { | 1504 if (mini_tab_count > 0) { |
| 1471 available_width -= mini_tab_count * (Tab::GetMiniWidth() + kTabHOffset); | 1505 available_width -= mini_tab_count * (Tab::GetMiniWidth() + GetTabHOffset()); |
| 1472 tab_count -= mini_tab_count; | 1506 tab_count -= mini_tab_count; |
| 1473 if (tab_count == 0) { | 1507 if (tab_count == 0) { |
| 1474 *selected_width = *unselected_width = Tab::GetStandardSize().width(); | 1508 *selected_width = *unselected_width = Tab::GetStandardSize().width(); |
| 1475 return; | 1509 return; |
| 1476 } | 1510 } |
| 1477 // Account for gap between the last mini-tab and first non-mini-tab. | 1511 // Account for gap between the last mini-tab and first non-mini-tab. |
| 1478 available_width -= kMiniToNonMiniGap; | 1512 available_width -= kMiniToNonMiniGap; |
| 1479 } | 1513 } |
| 1480 | 1514 |
| 1481 // Calculate the desired tab widths by dividing the available space into equal | 1515 // Calculate the desired tab widths by dividing the available space into equal |
| 1482 // portions. Don't let tabs get larger than the "standard width" or smaller | 1516 // portions. Don't let tabs get larger than the "standard width" or smaller |
| 1483 // than the minimum width for each type, respectively. | 1517 // than the minimum width for each type, respectively. |
| 1484 const int total_offset = kTabHOffset * (tab_count - 1); | 1518 const int total_offset = GetTabHOffset() * (tab_count - 1); |
| 1485 const double desired_tab_width = std::min((static_cast<double>( | 1519 const double desired_tab_width = std::min((static_cast<double>( |
| 1486 available_width - total_offset) / static_cast<double>(tab_count)), | 1520 available_width - total_offset) / static_cast<double>(tab_count)), |
| 1487 static_cast<double>(Tab::GetStandardSize().width())); | 1521 static_cast<double>(Tab::GetStandardSize().width())); |
| 1488 *unselected_width = std::max(desired_tab_width, min_unselected_width); | 1522 *unselected_width = std::max(desired_tab_width, min_unselected_width); |
| 1489 *selected_width = std::max(desired_tab_width, min_selected_width); | 1523 *selected_width = std::max(desired_tab_width, min_selected_width); |
| 1490 | 1524 |
| 1491 // When there are multiple tabs, we'll have one selected and some unselected | 1525 // When there are multiple tabs, we'll have one selected and some unselected |
| 1492 // tabs. If the desired width was between the minimum sizes of these types, | 1526 // tabs. If the desired width was between the minimum sizes of these types, |
| 1493 // try to shrink the tabs with the smaller minimum. For example, if we have | 1527 // try to shrink the tabs with the smaller minimum. For example, if we have |
| 1494 // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5. If | 1528 // a strip of width 10 with 4 tabs, the desired width per tab will be 2.5. If |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1567 } | 1601 } |
| 1568 | 1602 |
| 1569 gfx::Rect TabStrip::GetDropBounds(int drop_index, | 1603 gfx::Rect TabStrip::GetDropBounds(int drop_index, |
| 1570 bool drop_before, | 1604 bool drop_before, |
| 1571 bool* is_beneath) { | 1605 bool* is_beneath) { |
| 1572 DCHECK_NE(drop_index, -1); | 1606 DCHECK_NE(drop_index, -1); |
| 1573 int center_x; | 1607 int center_x; |
| 1574 if (drop_index < tab_count()) { | 1608 if (drop_index < tab_count()) { |
| 1575 Tab* tab = tab_at(drop_index); | 1609 Tab* tab = tab_at(drop_index); |
| 1576 if (drop_before) | 1610 if (drop_before) |
| 1577 center_x = tab->x() - (kTabHOffset / 2); | 1611 center_x = tab->x() - (GetTabHOffset() / 2); |
| 1578 else | 1612 else |
| 1579 center_x = tab->x() + (tab->width() / 2); | 1613 center_x = tab->x() + (tab->width() / 2); |
| 1580 } else { | 1614 } else { |
| 1581 Tab* last_tab = tab_at(drop_index - 1); | 1615 Tab* last_tab = tab_at(drop_index - 1); |
| 1582 center_x = last_tab->x() + last_tab->width() + (kTabHOffset / 2); | 1616 center_x = last_tab->x() + last_tab->width() + (GetTabHOffset() / 2); |
| 1583 } | 1617 } |
| 1584 | 1618 |
| 1585 // Mirror the center point if necessary. | 1619 // Mirror the center point if necessary. |
| 1586 center_x = GetMirroredXInView(center_x); | 1620 center_x = GetMirroredXInView(center_x); |
| 1587 | 1621 |
| 1588 // Determine the screen bounds. | 1622 // Determine the screen bounds. |
| 1589 gfx::Point drop_loc(center_x - drop_indicator_width / 2, | 1623 gfx::Point drop_loc(center_x - drop_indicator_width / 2, |
| 1590 -drop_indicator_height); | 1624 -drop_indicator_height); |
| 1591 ConvertPointToScreen(this, &drop_loc); | 1625 ConvertPointToScreen(this, &drop_loc); |
| 1592 gfx::Rect drop_bounds(drop_loc.x(), drop_loc.y(), drop_indicator_width, | 1626 gfx::Rect drop_bounds(drop_loc.x(), drop_loc.y(), drop_indicator_width, |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1758 tab_x += kMiniToNonMiniGap; | 1792 tab_x += kMiniToNonMiniGap; |
| 1759 } | 1793 } |
| 1760 if (tab->IsActive()) | 1794 if (tab->IsActive()) |
| 1761 tab_width = selected; | 1795 tab_width = selected; |
| 1762 } | 1796 } |
| 1763 double end_of_tab = tab_x + tab_width; | 1797 double end_of_tab = tab_x + tab_width; |
| 1764 int rounded_tab_x = Round(tab_x); | 1798 int rounded_tab_x = Round(tab_x); |
| 1765 set_ideal_bounds(i, | 1799 set_ideal_bounds(i, |
| 1766 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, | 1800 gfx::Rect(rounded_tab_x, 0, Round(end_of_tab) - rounded_tab_x, |
| 1767 tab_height)); | 1801 tab_height)); |
| 1768 tab_x = end_of_tab + kTabHOffset; | 1802 tab_x = end_of_tab + GetTabHOffset(); |
| 1769 last_was_mini = tab->data().mini; | 1803 last_was_mini = tab->data().mini; |
| 1770 } | 1804 } |
| 1771 } | 1805 } |
| 1772 | 1806 |
| 1773 // If we're in stacking mode, update the positions now that we have | 1807 // If we're in stacking mode, update the positions now that we have |
| 1774 // appropriate widths. | 1808 // appropriate widths. |
| 1775 if (stacking_ && tab_x - kTabHOffset > | 1809 if (stacking_ && tab_x - GetTabHOffset() > |
| 1776 width() - newtab_button_bounds_.width()) { | 1810 width() - newtab_button_bounds_.width()) { |
| 1777 tab_x = GenerateIdealBoundsWithStacking( | 1811 tab_x = GenerateIdealBoundsWithStacking( |
| 1778 mini_tab_count, non_closing_tab_count, tab_x, selected); | 1812 mini_tab_count, non_closing_tab_count, tab_x, selected); |
| 1779 } | 1813 } |
| 1780 | 1814 |
| 1781 // Update bounds of new tab button. | 1815 // Update bounds of new tab button. |
| 1782 int new_tab_x; | 1816 int new_tab_x; |
| 1783 int new_tab_y = SizeTabButtonToTopOfTabStrip() ? 0 : kNewTabButtonVOffset; | 1817 int new_tab_y = SizeTabButtonToTopOfTabStrip() ? 0 : GetNewTabButtonVOffset(); |
| 1784 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && | 1818 if (abs(Round(unselected) - Tab::GetStandardSize().width()) > 1 && |
| 1785 !in_tab_close_) { | 1819 !in_tab_close_) { |
| 1786 // We're shrinking tabs, so we need to anchor the New Tab button to the | 1820 // We're shrinking tabs, so we need to anchor the New Tab button to the |
| 1787 // right edge of the TabStrip's bounds, rather than the right edge of the | 1821 // right edge of the TabStrip's bounds, rather than the right edge of the |
| 1788 // right-most Tab, otherwise it'll bounce when animating. | 1822 // right-most Tab, otherwise it'll bounce when animating. |
| 1789 new_tab_x = width() - newtab_button_bounds_.width(); | 1823 new_tab_x = width() - newtab_button_bounds_.width(); |
| 1790 } else { | 1824 } else { |
| 1791 new_tab_x = Round(tab_x - kTabHOffset) + kNewTabButtonHOffset; | 1825 new_tab_x = Round(tab_x - GetTabHOffset()) + GetNewTabButtonHOffset(); |
| 1792 } | 1826 } |
| 1793 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); | 1827 newtab_button_bounds_.set_origin(gfx::Point(new_tab_x, new_tab_y)); |
| 1794 } | 1828 } |
| 1795 | 1829 |
| 1796 double TabStrip::GenerateIdealBoundsWithStacking(int mini_tab_count, | 1830 double TabStrip::GenerateIdealBoundsWithStacking(int mini_tab_count, |
| 1797 int non_closing_tab_count, | 1831 int non_closing_tab_count, |
| 1798 double new_tab_x, | 1832 double new_tab_x, |
| 1799 double selected_size) { | 1833 double selected_size) { |
| 1800 if (non_closing_tab_count == mini_tab_count) | 1834 if (non_closing_tab_count == mini_tab_count) |
| 1801 return new_tab_x; | 1835 return new_tab_x; |
| 1802 | 1836 |
| 1803 // Pinned tabs always have their desired size, and don't stack. We rely on | 1837 // Pinned tabs always have their desired size, and don't stack. We rely on |
| 1804 // GenerateIdealBounds to have positioned pinned tabs already, so don't move | 1838 // GenerateIdealBounds to have positioned pinned tabs already, so don't move |
| 1805 // them. | 1839 // them. |
| 1806 int tab_index = 0; | 1840 int tab_index = 0; |
| 1807 double next_x = 0; | 1841 double next_x = 0; |
| 1808 for (; tab_index < tab_count(); ++tab_index) { | 1842 for (; tab_index < tab_count(); ++tab_index) { |
| 1809 BaseTab* tab = tab_at(tab_index); | 1843 BaseTab* tab = tab_at(tab_index); |
| 1810 if (!tab->closing() && !tab->data().mini) { | 1844 if (!tab->closing() && !tab->data().mini) { |
| 1811 next_x = ideal_bounds(tab_index).x(); | 1845 next_x = ideal_bounds(tab_index).x(); |
| 1812 break; | 1846 break; |
| 1813 } | 1847 } |
| 1814 } | 1848 } |
| 1815 if (tab_index == tab_count()) | 1849 if (tab_index == tab_count()) |
| 1816 return new_tab_x; | 1850 return new_tab_x; |
| 1817 | 1851 |
| 1818 // Always reserve kMaxEdgeStackWidth on each side for stacking. We don't | 1852 // Always reserve kMaxEdgeStackWidth on each side for stacking. We don't |
| 1819 // later try to adjust as it can lead to tabs bouncing around. | 1853 // later try to adjust as it can lead to tabs bouncing around. |
| 1820 int available_width = width() - | 1854 int available_width = width() - |
| 1821 (kNewTabButtonHOffset + newtab_button_bounds_.width()) - next_x - | 1855 (GetNewTabButtonHOffset() + newtab_button_bounds_.width()) - next_x - |
| 1822 2 * kMaxEdgeStackWidth; | 1856 2 * kMaxEdgeStackWidth; |
| 1823 if (available_width <= 0) | 1857 if (available_width <= 0) |
| 1824 return new_tab_x; | 1858 return new_tab_x; |
| 1825 UpdateNumVisibleTabs(non_closing_tab_count, available_width, selected_size); | 1859 UpdateNumVisibleTabs(non_closing_tab_count, available_width, selected_size); |
| 1826 int stacked_leading_index = tab_index; | 1860 int stacked_leading_index = tab_index; |
| 1827 int stacked_trailing_index = first_visible_tab_index_; | 1861 int stacked_trailing_index = first_visible_tab_index_; |
| 1828 for (int visible_count = 0; | 1862 for (int visible_count = 0; |
| 1829 stacked_trailing_index < tab_count() && | 1863 stacked_trailing_index < tab_count() && |
| 1830 visible_count < num_visible_tabs_; ++stacked_trailing_index) { | 1864 visible_count < num_visible_tabs_; ++stacked_trailing_index) { |
| 1831 if (!tab_at(stacked_trailing_index)->closing()) | 1865 if (!tab_at(stacked_trailing_index)->closing()) |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1850 } | 1884 } |
| 1851 } else { | 1885 } else { |
| 1852 tab_index = first_visible_tab_index_; | 1886 tab_index = first_visible_tab_index_; |
| 1853 } | 1887 } |
| 1854 | 1888 |
| 1855 if (stacked_leading_count > 0 && stacked_trailing_count == 0) { | 1889 if (stacked_leading_count > 0 && stacked_trailing_count == 0) { |
| 1856 // If there are no stacked tabs on the right and there is extra space, give | 1890 // If there are no stacked tabs on the right and there is extra space, give |
| 1857 // it to the last stacked tab on the left. | 1891 // it to the last stacked tab on the left. |
| 1858 next_x += available_width + kMaxEdgeStackWidth - | 1892 next_x += available_width + kMaxEdgeStackWidth - |
| 1859 (num_visible_tabs_ * selected_size + | 1893 (num_visible_tabs_ * selected_size + |
| 1860 std::max(num_visible_tabs_ - 1, 0) * kTabHOffset); | 1894 std::max(num_visible_tabs_ - 1, 0) * GetTabHOffset()); |
| 1861 } | 1895 } |
| 1862 | 1896 |
| 1863 // Totally visible tabs. | 1897 // Totally visible tabs. |
| 1864 for (int visible_count = 0; | 1898 for (int visible_count = 0; |
| 1865 tab_index < tab_count() && visible_count < num_visible_tabs_; | 1899 tab_index < tab_count() && visible_count < num_visible_tabs_; |
| 1866 tab_index++) { | 1900 tab_index++) { |
| 1867 if (tab_at(tab_index)->closing()) | 1901 if (tab_at(tab_index)->closing()) |
| 1868 continue; | 1902 continue; |
| 1869 gfx::Rect bounds = ideal_bounds(tab_index); | 1903 gfx::Rect bounds = ideal_bounds(tab_index); |
| 1870 bounds.set_x(next_x); | 1904 bounds.set_x(next_x); |
| 1871 next_x = bounds.right() + kTabHOffset; | 1905 next_x = bounds.right() + GetTabHOffset(); |
| 1872 set_ideal_bounds(tab_index, bounds); | 1906 set_ideal_bounds(tab_index, bounds); |
| 1873 visible_count++; | 1907 visible_count++; |
| 1874 } | 1908 } |
| 1875 | 1909 |
| 1876 // Stacked tabs to the right. | 1910 // Stacked tabs to the right. |
| 1877 if (stacked_trailing_count == 0) | 1911 if (stacked_trailing_count == 0) |
| 1878 return next_x; | 1912 return next_x; |
| 1879 | 1913 |
| 1880 double stacked_offset = | 1914 double stacked_offset = |
| 1881 kMaxEdgeStackWidth / static_cast<double>(stacked_trailing_count); | 1915 kMaxEdgeStackWidth / static_cast<double>(stacked_trailing_count); |
| 1882 next_x = width() - (kNewTabButtonHOffset + newtab_button_bounds_.width()) - | 1916 next_x = width() - |
| 1917 (GetNewTabButtonHOffset() + newtab_button_bounds_.width()) - |
| 1883 (stacked_trailing_count - 1) * stacked_offset - selected_size; | 1918 (stacked_trailing_count - 1) * stacked_offset - selected_size; |
| 1884 for (; tab_index < tab_count(); ++tab_index) { | 1919 for (; tab_index < tab_count(); ++tab_index) { |
| 1885 if (tab_at(tab_index)->closing()) | 1920 if (tab_at(tab_index)->closing()) |
| 1886 continue; | 1921 continue; |
| 1887 gfx::Rect bounds = ideal_bounds(tab_index); | 1922 gfx::Rect bounds = ideal_bounds(tab_index); |
| 1888 bounds.set_x(next_x); | 1923 bounds.set_x(next_x); |
| 1889 set_ideal_bounds(tab_index, bounds); | 1924 set_ideal_bounds(tab_index, bounds); |
| 1890 next_x += stacked_offset; | 1925 next_x += stacked_offset; |
| 1891 } | 1926 } |
| 1892 | 1927 |
| 1893 return next_x + kTabHOffset; | 1928 return next_x + GetTabHOffset(); |
| 1894 } | 1929 } |
| 1895 | 1930 |
| 1896 void TabStrip::StartResizeLayoutAnimation() { | 1931 void TabStrip::StartResizeLayoutAnimation() { |
| 1897 PrepareForAnimation(); | 1932 PrepareForAnimation(); |
| 1898 GenerateIdealBounds(); | 1933 GenerateIdealBounds(); |
| 1899 AnimateToIdealBounds(); | 1934 AnimateToIdealBounds(); |
| 1900 } | 1935 } |
| 1901 | 1936 |
| 1902 void TabStrip::StartMiniTabAnimation() { | 1937 void TabStrip::StartMiniTabAnimation() { |
| 1903 in_tab_close_ = false; | 1938 in_tab_close_ = false; |
| 1904 available_width_for_tabs_ = -1; | 1939 available_width_for_tabs_ = -1; |
| 1905 | 1940 |
| 1906 PrepareForAnimation(); | 1941 PrepareForAnimation(); |
| 1907 | 1942 |
| 1908 GenerateIdealBounds(); | 1943 GenerateIdealBounds(); |
| 1909 AnimateToIdealBounds(); | 1944 AnimateToIdealBounds(); |
| 1910 } | 1945 } |
| 1911 | 1946 |
| 1912 void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) { | 1947 void TabStrip::StartMouseInitiatedRemoveTabAnimation(int model_index) { |
| 1913 // The user initiated the close. We want to persist the bounds of all the | 1948 // The user initiated the close. We want to persist the bounds of all the |
| 1914 // existing tabs, so we manually shift ideal_bounds then animate. | 1949 // existing tabs, so we manually shift ideal_bounds then animate. |
| 1915 BaseTab* tab_closing = tab_at(model_index); | 1950 BaseTab* tab_closing = tab_at(model_index); |
| 1916 int delta = tab_closing->width() + kTabHOffset; | 1951 int delta = tab_closing->width() + GetTabHOffset(); |
| 1917 // If the tab being closed is a mini-tab next to a non-mini-tab, be sure to | 1952 // If the tab being closed is a mini-tab next to a non-mini-tab, be sure to |
| 1918 // add the extra padding. | 1953 // add the extra padding. |
| 1919 DCHECK_NE(model_index + 1, tab_count()); | 1954 DCHECK_NE(model_index + 1, tab_count()); |
| 1920 if (tab_closing->data().mini && model_index + 1 < tab_count() && | 1955 if (tab_closing->data().mini && model_index + 1 < tab_count() && |
| 1921 !tab_at(model_index + 1)->data().mini) { | 1956 !tab_at(model_index + 1)->data().mini) { |
| 1922 delta += kMiniToNonMiniGap; | 1957 delta += kMiniToNonMiniGap; |
| 1923 } | 1958 } |
| 1924 | 1959 |
| 1925 for (int i = model_index + 1; i < tab_count(); ++i) { | 1960 for (int i = model_index + 1; i < tab_count(); ++i) { |
| 1926 gfx::Rect bounds = ideal_bounds(i); | 1961 gfx::Rect bounds = ideal_bounds(i); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1951 new RemoveTabDelegate(this, tab_closing), | 1986 new RemoveTabDelegate(this, tab_closing), |
| 1952 true); | 1987 true); |
| 1953 } | 1988 } |
| 1954 | 1989 |
| 1955 bool TabStrip::IsPointInTab(Tab* tab, | 1990 bool TabStrip::IsPointInTab(Tab* tab, |
| 1956 const gfx::Point& point_in_tabstrip_coords) { | 1991 const gfx::Point& point_in_tabstrip_coords) { |
| 1957 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); | 1992 gfx::Point point_in_tab_coords(point_in_tabstrip_coords); |
| 1958 View::ConvertPointToView(this, tab, &point_in_tab_coords); | 1993 View::ConvertPointToView(this, tab, &point_in_tab_coords); |
| 1959 return tab->HitTest(point_in_tab_coords); | 1994 return tab->HitTest(point_in_tab_coords); |
| 1960 } | 1995 } |
| OLD | NEW |