| 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 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <windowsx.h> | 8 #include <windowsx.h> |
| 9 #endif | 9 #endif |
| 10 | 10 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "chrome/common/chrome_switches.h" | 31 #include "chrome/common/chrome_switches.h" |
| 32 #include "chrome/grit/generated_resources.h" | 32 #include "chrome/grit/generated_resources.h" |
| 33 #include "content/public/browser/user_metrics.h" | 33 #include "content/public/browser/user_metrics.h" |
| 34 #include "grit/theme_resources.h" | 34 #include "grit/theme_resources.h" |
| 35 #include "ui/accessibility/ax_view_state.h" | 35 #include "ui/accessibility/ax_view_state.h" |
| 36 #include "ui/base/default_theme_provider.h" | 36 #include "ui/base/default_theme_provider.h" |
| 37 #include "ui/base/dragdrop/drag_drop_types.h" | 37 #include "ui/base/dragdrop/drag_drop_types.h" |
| 38 #include "ui/base/l10n/l10n_util.h" | 38 #include "ui/base/l10n/l10n_util.h" |
| 39 #include "ui/base/models/list_selection_model.h" | 39 #include "ui/base/models/list_selection_model.h" |
| 40 #include "ui/base/resource/resource_bundle.h" | 40 #include "ui/base/resource/resource_bundle.h" |
| 41 #include "ui/compositor/paint_context.h" | 41 #include "ui/compositor/compositing_recorder.h" |
| 42 #include "ui/compositor/paint_recorder.h" |
| 42 #include "ui/gfx/animation/animation_container.h" | 43 #include "ui/gfx/animation/animation_container.h" |
| 43 #include "ui/gfx/animation/throb_animation.h" | 44 #include "ui/gfx/animation/throb_animation.h" |
| 44 #include "ui/gfx/canvas.h" | 45 #include "ui/gfx/canvas.h" |
| 45 #include "ui/gfx/display.h" | 46 #include "ui/gfx/display.h" |
| 46 #include "ui/gfx/geometry/rect_conversions.h" | 47 #include "ui/gfx/geometry/rect_conversions.h" |
| 47 #include "ui/gfx/geometry/size.h" | 48 #include "ui/gfx/geometry/size.h" |
| 48 #include "ui/gfx/image/image_skia.h" | 49 #include "ui/gfx/image/image_skia.h" |
| 49 #include "ui/gfx/image/image_skia_operations.h" | 50 #include "ui/gfx/image/image_skia_operations.h" |
| 50 #include "ui/gfx/path.h" | 51 #include "ui/gfx/path.h" |
| 51 #include "ui/gfx/screen.h" | 52 #include "ui/gfx/screen.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 67 #include "ui/views/win/hwnd_util.h" | 68 #include "ui/views/win/hwnd_util.h" |
| 68 #endif | 69 #endif |
| 69 | 70 |
| 70 using base::UserMetricsAction; | 71 using base::UserMetricsAction; |
| 71 using ui::DropTargetEvent; | 72 using ui::DropTargetEvent; |
| 72 | 73 |
| 73 namespace { | 74 namespace { |
| 74 | 75 |
| 75 static const int kTabStripAnimationVSlop = 40; | 76 static const int kTabStripAnimationVSlop = 40; |
| 76 // Inactive tabs in a native frame are slightly transparent. | 77 // Inactive tabs in a native frame are slightly transparent. |
| 77 static const int kGlassFrameInactiveTabAlpha = 200; | 78 static const uint8_t kGlassFrameInactiveTabAlpha = 200; |
| 78 // If there are multiple tabs selected then make non-selected inactive tabs | 79 // If there are multiple tabs selected then make non-selected inactive tabs |
| 79 // even more transparent. | 80 // even more transparent. |
| 80 static const int kGlassFrameInactiveTabAlphaMultiSelection = 150; | 81 static const int kGlassFrameInactiveTabAlphaMultiSelection = 150; |
| 81 | 82 |
| 82 // Alpha applied to all elements save the selected tabs. | 83 // Alpha applied to all elements save the selected tabs. |
| 83 static const int kInactiveTabAndNewTabButtonAlphaAsh = 230; | 84 static const uint8_t kInactiveTabAndNewTabButtonAlphaAsh = 230; |
| 84 static const int kInactiveTabAndNewTabButtonAlpha = 255; | 85 static const uint8_t kInactiveTabAndNewTabButtonAlpha = 255; |
| 85 | 86 |
| 86 // Inverse ratio of the width of a tab edge to the width of the tab. When | 87 // Inverse ratio of the width of a tab edge to the width of the tab. When |
| 87 // hovering over the left or right edge of a tab, the drop indicator will | 88 // hovering over the left or right edge of a tab, the drop indicator will |
| 88 // point between tabs. | 89 // point between tabs. |
| 89 static const int kTabEdgeRatioInverse = 4; | 90 static const int kTabEdgeRatioInverse = 4; |
| 90 | 91 |
| 91 // Size of the drop indicator. | 92 // Size of the drop indicator. |
| 92 static int drop_indicator_width; | 93 static int drop_indicator_width; |
| 93 static int drop_indicator_height; | 94 static int drop_indicator_height; |
| 94 | 95 |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 IDR_NEWTAB_BUTTON_P : IDR_NEWTAB_BUTTON; | 452 IDR_NEWTAB_BUTTON_P : IDR_NEWTAB_BUTTON; |
| 452 gfx::ImageSkia* overlay = GetThemeProvider()->GetImageSkiaNamed(overlay_id); | 453 gfx::ImageSkia* overlay = GetThemeProvider()->GetImageSkiaNamed(overlay_id); |
| 453 | 454 |
| 454 gfx::Canvas canvas( | 455 gfx::Canvas canvas( |
| 455 gfx::Size(overlay->width(), overlay->height()), | 456 gfx::Size(overlay->width(), overlay->height()), |
| 456 scale, | 457 scale, |
| 457 false); | 458 false); |
| 458 canvas.DrawImageInt(GetBackgroundImage(state, scale), 0, 0); | 459 canvas.DrawImageInt(GetBackgroundImage(state, scale), 0, 0); |
| 459 | 460 |
| 460 // Draw the button border with a slight alpha. | 461 // Draw the button border with a slight alpha. |
| 461 const int kGlassFrameOverlayAlpha = 178; | 462 const uint8_t kGlassFrameOverlayAlpha = 178; |
| 462 const int kOpaqueFrameOverlayAlpha = 230; | 463 const uint8_t kOpaqueFrameOverlayAlpha = 230; |
| 463 uint8 alpha = ShouldWindowContentsBeTransparent() ? | 464 uint8_t alpha = ShouldWindowContentsBeTransparent() |
| 464 kGlassFrameOverlayAlpha : kOpaqueFrameOverlayAlpha; | 465 ? kGlassFrameOverlayAlpha |
| 466 : kOpaqueFrameOverlayAlpha; |
| 465 canvas.DrawImageInt(*overlay, 0, 0, alpha); | 467 canvas.DrawImageInt(*overlay, 0, 0, alpha); |
| 466 | 468 |
| 467 return gfx::ImageSkia(canvas.ExtractImageRep()); | 469 return gfx::ImageSkia(canvas.ExtractImageRep()); |
| 468 } | 470 } |
| 469 | 471 |
| 470 gfx::ImageSkia NewTabButton::GetImageForScale(float scale) const { | 472 gfx::ImageSkia NewTabButton::GetImageForScale(float scale) const { |
| 471 if (!hover_animation_->is_animating()) | 473 if (!hover_animation_->is_animating()) |
| 472 return GetImageForState(state(), scale); | 474 return GetImageForState(state(), scale); |
| 473 return gfx::ImageSkiaOperations::CreateBlendedImage( | 475 return gfx::ImageSkiaOperations::CreateBlendedImage( |
| 474 GetImageForState(views::CustomButton::STATE_NORMAL, scale), | 476 GetImageForState(views::CustomButton::STATE_NORMAL, scale), |
| (...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1235 void TabStrip::Layout() { | 1237 void TabStrip::Layout() { |
| 1236 // Only do a layout if our size changed. | 1238 // Only do a layout if our size changed. |
| 1237 if (last_layout_size_ == size()) | 1239 if (last_layout_size_ == size()) |
| 1238 return; | 1240 return; |
| 1239 if (IsDragSessionActive()) | 1241 if (IsDragSessionActive()) |
| 1240 return; | 1242 return; |
| 1241 DoLayout(); | 1243 DoLayout(); |
| 1242 } | 1244 } |
| 1243 | 1245 |
| 1244 void TabStrip::PaintChildren(const ui::PaintContext& context) { | 1246 void TabStrip::PaintChildren(const ui::PaintContext& context) { |
| 1245 gfx::Canvas* canvas = context.canvas(); | |
| 1246 // The view order doesn't match the paint order (tabs_ contains the tab | 1247 // The view order doesn't match the paint order (tabs_ contains the tab |
| 1247 // ordering). Additionally we need to paint the tabs that are closing in | 1248 // ordering). Additionally we need to paint the tabs that are closing in |
| 1248 // |tabs_closing_map_|. | 1249 // |tabs_closing_map_|. |
| 1249 Tab* active_tab = NULL; | 1250 Tab* active_tab = NULL; |
| 1250 Tabs tabs_dragging; | 1251 Tabs tabs_dragging; |
| 1251 Tabs selected_tabs; | 1252 Tabs selected_tabs; |
| 1252 int selected_tab_count = 0; | 1253 int selected_tab_count = 0; |
| 1253 bool is_dragging = false; | 1254 bool is_dragging = false; |
| 1254 int active_tab_index = -1; | 1255 int active_tab_index = -1; |
| 1255 | 1256 |
| 1256 const chrome::HostDesktopType host_desktop_type = | 1257 const chrome::HostDesktopType host_desktop_type = |
| 1257 chrome::GetHostDesktopTypeForNativeView(GetWidget()->GetNativeView()); | 1258 chrome::GetHostDesktopTypeForNativeView(GetWidget()->GetNativeView()); |
| 1258 const int inactive_tab_alpha = | 1259 const uint8_t inactive_tab_alpha = |
| 1259 (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) ? | 1260 (host_desktop_type == chrome::HOST_DESKTOP_TYPE_ASH) |
| 1260 kInactiveTabAndNewTabButtonAlphaAsh : kInactiveTabAndNewTabButtonAlpha; | 1261 ? kInactiveTabAndNewTabButtonAlphaAsh |
| 1262 : kInactiveTabAndNewTabButtonAlpha; |
| 1261 | 1263 |
| 1262 if (inactive_tab_alpha < 255) | 1264 { |
| 1263 canvas->SaveLayerAlpha(inactive_tab_alpha); | 1265 ui::CompositingRecorder opacity_recorder(context, inactive_tab_alpha); |
| 1264 | 1266 |
| 1265 PaintClosingTabs(tab_count(), context); | 1267 PaintClosingTabs(tab_count(), context); |
| 1266 | 1268 |
| 1267 for (int i = tab_count() - 1; i >= 0; --i) { | 1269 for (int i = tab_count() - 1; i >= 0; --i) { |
| 1268 Tab* tab = tab_at(i); | 1270 Tab* tab = tab_at(i); |
| 1269 if (tab->IsSelected()) | 1271 if (tab->IsSelected()) |
| 1270 selected_tab_count++; | 1272 selected_tab_count++; |
| 1271 if (tab->dragging() && !stacked_layout_) { | 1273 if (tab->dragging() && !stacked_layout_) { |
| 1272 is_dragging = true; | 1274 is_dragging = true; |
| 1273 if (tab->IsActive()) { | 1275 if (tab->IsActive()) { |
| 1276 active_tab = tab; |
| 1277 active_tab_index = i; |
| 1278 } else { |
| 1279 tabs_dragging.push_back(tab); |
| 1280 } |
| 1281 } else if (!tab->IsActive()) { |
| 1282 if (!tab->IsSelected()) { |
| 1283 if (!stacked_layout_) |
| 1284 tab->Paint(context); |
| 1285 } else { |
| 1286 selected_tabs.push_back(tab); |
| 1287 } |
| 1288 } else { |
| 1274 active_tab = tab; | 1289 active_tab = tab; |
| 1275 active_tab_index = i; | 1290 active_tab_index = i; |
| 1276 } else { | |
| 1277 tabs_dragging.push_back(tab); | |
| 1278 } | 1291 } |
| 1279 } else if (!tab->IsActive()) { | 1292 PaintClosingTabs(i, context); |
| 1280 if (!tab->IsSelected()) { | 1293 } |
| 1281 if (!stacked_layout_) | 1294 |
| 1282 tab->Paint(context); | 1295 // Draw from the left and then the right if we're in touch mode. |
| 1283 } else { | 1296 if (stacked_layout_ && active_tab_index >= 0) { |
| 1284 selected_tabs.push_back(tab); | 1297 for (int i = 0; i < active_tab_index; ++i) { |
| 1298 Tab* tab = tab_at(i); |
| 1299 tab->Paint(context); |
| 1285 } | 1300 } |
| 1286 } else { | 1301 |
| 1287 active_tab = tab; | 1302 for (int i = tab_count() - 1; i > active_tab_index; --i) { |
| 1288 active_tab_index = i; | 1303 Tab* tab = tab_at(i); |
| 1304 tab->Paint(context); |
| 1305 } |
| 1289 } | 1306 } |
| 1290 PaintClosingTabs(i, context); | |
| 1291 } | 1307 } |
| 1292 | 1308 |
| 1293 // Draw from the left and then the right if we're in touch mode. | |
| 1294 if (stacked_layout_ && active_tab_index >= 0) { | |
| 1295 for (int i = 0; i < active_tab_index; ++i) { | |
| 1296 Tab* tab = tab_at(i); | |
| 1297 tab->Paint(context); | |
| 1298 } | |
| 1299 | |
| 1300 for (int i = tab_count() - 1; i > active_tab_index; --i) { | |
| 1301 Tab* tab = tab_at(i); | |
| 1302 tab->Paint(context); | |
| 1303 } | |
| 1304 } | |
| 1305 if (inactive_tab_alpha < 255) | |
| 1306 canvas->Restore(); | |
| 1307 | |
| 1308 if (GetWidget()->ShouldWindowContentsBeTransparent()) { | 1309 if (GetWidget()->ShouldWindowContentsBeTransparent()) { |
| 1310 ui::PaintRecorder recorder(context); |
| 1309 // Make sure non-active tabs are somewhat transparent. | 1311 // Make sure non-active tabs are somewhat transparent. |
| 1310 SkPaint paint; | 1312 SkPaint paint; |
| 1311 // If there are multiple tabs selected, fade non-selected tabs more to make | 1313 // If there are multiple tabs selected, fade non-selected tabs more to make |
| 1312 // the selected tabs more noticable. | 1314 // the selected tabs more noticable. |
| 1313 int alpha = selected_tab_count > 1 ? | 1315 uint8_t alpha = selected_tab_count > 1 |
| 1314 kGlassFrameInactiveTabAlphaMultiSelection : | 1316 ? kGlassFrameInactiveTabAlphaMultiSelection |
| 1315 kGlassFrameInactiveTabAlpha; | 1317 : kGlassFrameInactiveTabAlpha; |
| 1316 paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); | 1318 paint.setColor(SkColorSetARGB(alpha, 255, 255, 255)); |
| 1317 paint.setXfermodeMode(SkXfermode::kDstIn_Mode); | 1319 paint.setXfermodeMode(SkXfermode::kDstIn_Mode); |
| 1318 paint.setStyle(SkPaint::kFill_Style); | 1320 paint.setStyle(SkPaint::kFill_Style); |
| 1319 | 1321 |
| 1320 // The tab graphics include some shadows at the top, so the actual | 1322 // The tab graphics include some shadows at the top, so the actual |
| 1321 // tabstrip top is 4 px. above the apparent top of the tab, to provide room | 1323 // tabstrip top is 4 px. above the apparent top of the tab, to provide room |
| 1322 // to draw these. Exclude this region when trying to make tabs transparent | 1324 // to draw these. Exclude this region when trying to make tabs transparent |
| 1323 // as it's transparent enough already, and drawing in this region can | 1325 // as it's transparent enough already, and drawing in this region can |
| 1324 // overlap the avatar button, leading to visual artifacts. | 1326 // overlap the avatar button, leading to visual artifacts. |
| 1325 const int kTopOffset = 4; | 1327 const int kTopOffset = 4; |
| 1326 // The tabstrip area overlaps the toolbar area by 2 px. | 1328 // The tabstrip area overlaps the toolbar area by 2 px. |
| 1327 canvas->DrawRect( | 1329 recorder.canvas()->DrawRect( |
| 1328 gfx::Rect(0, kTopOffset, width(), height() - kTopOffset - 2), paint); | 1330 gfx::Rect(0, kTopOffset, width(), height() - kTopOffset - 2), paint); |
| 1329 } | 1331 } |
| 1330 | 1332 |
| 1331 // Now selected but not active. We don't want these dimmed if using native | 1333 // Now selected but not active. We don't want these dimmed if using native |
| 1332 // frame, so they're painted after initial pass. | 1334 // frame, so they're painted after initial pass. |
| 1333 for (size_t i = 0; i < selected_tabs.size(); ++i) | 1335 for (size_t i = 0; i < selected_tabs.size(); ++i) |
| 1334 selected_tabs[i]->Paint(context); | 1336 selected_tabs[i]->Paint(context); |
| 1335 | 1337 |
| 1336 // Next comes the active tab. | 1338 // Next comes the active tab. |
| 1337 if (active_tab && !is_dragging) | 1339 if (active_tab && !is_dragging) |
| 1338 active_tab->Paint(context); | 1340 active_tab->Paint(context); |
| 1339 | 1341 |
| 1340 // Paint the New Tab button. | 1342 // Paint the New Tab button. |
| 1341 if (inactive_tab_alpha < 255) | 1343 { |
| 1342 canvas->SaveLayerAlpha(inactive_tab_alpha); | 1344 ui::CompositingRecorder opacity_recorder(context, inactive_tab_alpha); |
| 1343 newtab_button_->Paint(context); | 1345 newtab_button_->Paint(context); |
| 1344 if (inactive_tab_alpha < 255) | 1346 } |
| 1345 canvas->Restore(); | |
| 1346 | 1347 |
| 1347 // And the dragged tabs. | 1348 // And the dragged tabs. |
| 1348 for (size_t i = 0; i < tabs_dragging.size(); ++i) | 1349 for (size_t i = 0; i < tabs_dragging.size(); ++i) |
| 1349 tabs_dragging[i]->Paint(context); | 1350 tabs_dragging[i]->Paint(context); |
| 1350 | 1351 |
| 1351 // If the active tab is being dragged, it goes last. | 1352 // If the active tab is being dragged, it goes last. |
| 1352 if (active_tab && is_dragging) | 1353 if (active_tab && is_dragging) |
| 1353 active_tab->Paint(context); | 1354 active_tab->Paint(context); |
| 1354 } | 1355 } |
| 1355 | 1356 |
| (...skipping 1402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2758 ConvertPointToViewAndGetEventHandler(this, newtab_button_, point); | 2759 ConvertPointToViewAndGetEventHandler(this, newtab_button_, point); |
| 2759 if (view) | 2760 if (view) |
| 2760 return view; | 2761 return view; |
| 2761 } | 2762 } |
| 2762 Tab* tab = FindTabForEvent(point); | 2763 Tab* tab = FindTabForEvent(point); |
| 2763 if (tab) | 2764 if (tab) |
| 2764 return ConvertPointToViewAndGetEventHandler(this, tab, point); | 2765 return ConvertPointToViewAndGetEventHandler(this, tab, point); |
| 2765 } | 2766 } |
| 2766 return this; | 2767 return this; |
| 2767 } | 2768 } |
| OLD | NEW |