| 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/gtk/tabs/tab_strip_gtk.h" | 5 #include "chrome/browser/ui/gtk/tabs/tab_strip_gtk.h" |
| 6 | 6 |
| 7 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/debug/trace_event.h" | 12 #include "base/debug/trace_event.h" |
| 13 #include "base/i18n/rtl.h" | 13 #include "base/i18n/rtl.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
| 16 #include "chrome/browser/autocomplete/autocomplete.h" | 16 #include "chrome/browser/autocomplete/autocomplete.h" |
| 17 #include "chrome/browser/autocomplete/autocomplete_classifier.h" | 17 #include "chrome/browser/autocomplete/autocomplete_classifier.h" |
| 18 #include "chrome/browser/autocomplete/autocomplete_match.h" | 18 #include "chrome/browser/autocomplete/autocomplete_match.h" |
| 19 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
| 20 #include "chrome/browser/themes/theme_service.h" | 20 #include "chrome/browser/themes/theme_service.h" |
| 21 #include "chrome/browser/ui/browser.h" | 21 #include "chrome/browser/ui/browser.h" |
| 22 #include "chrome/browser/ui/browser_navigator.h" | 22 #include "chrome/browser/ui/browser_navigator.h" |
| 23 #include "chrome/browser/ui/gtk/browser_window_gtk.h" | 23 #include "chrome/browser/ui/gtk/browser_window_gtk.h" |
| 24 #include "chrome/browser/ui/gtk/custom_button.h" | 24 #include "chrome/browser/ui/gtk/custom_button.h" |
| 25 #include "chrome/browser/ui/gtk/gtk_theme_service.h" | 25 #include "chrome/browser/ui/gtk/gtk_theme_service.h" |
| 26 #include "chrome/browser/ui/gtk/gtk_util.h" | 26 #include "chrome/browser/ui/gtk/gtk_util.h" |
| 27 #include "chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h" | 27 #include "chrome/browser/ui/gtk/tabs/dragged_tab_controller_gtk.h" |
| 28 #include "chrome/browser/ui/gtk/tabs/tab_strip_menu_controller.h" | 28 #include "chrome/browser/ui/gtk/tabs/tab_strip_menu_controller.h" |
| 29 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 29 #include "chrome/browser/ui/tab_contents/tab_contents.h" |
| 30 #include "chrome/common/chrome_notification_types.h" | 30 #include "chrome/common/chrome_notification_types.h" |
| 31 #include "content/public/browser/notification_source.h" | 31 #include "content/public/browser/notification_source.h" |
| 32 #include "content/public/browser/web_contents.h" | 32 #include "content/public/browser/web_contents.h" |
| 33 #include "grit/generated_resources.h" | 33 #include "grit/generated_resources.h" |
| 34 #include "grit/theme_resources.h" | 34 #include "grit/theme_resources.h" |
| 35 #include "grit/theme_resources_standard.h" | 35 #include "grit/theme_resources_standard.h" |
| 36 #include "grit/ui_resources.h" | 36 #include "grit/ui_resources.h" |
| 37 #include "ui/base/animation/animation_delegate.h" | 37 #include "ui/base/animation/animation_delegate.h" |
| 38 #include "ui/base/animation/slide_animation.h" | 38 #include "ui/base/animation/slide_animation.h" |
| 39 #include "ui/base/dragdrop/gtk_dnd_util.h" | 39 #include "ui/base/dragdrop/gtk_dnd_util.h" |
| (...skipping 805 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 845 bounds_ = bounds; | 845 bounds_ = bounds; |
| 846 } | 846 } |
| 847 | 847 |
| 848 void TabStripGtk::UpdateLoadingAnimations() { | 848 void TabStripGtk::UpdateLoadingAnimations() { |
| 849 for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) { | 849 for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) { |
| 850 TabGtk* current_tab = GetTabAt(i); | 850 TabGtk* current_tab = GetTabAt(i); |
| 851 if (current_tab->closing()) { | 851 if (current_tab->closing()) { |
| 852 --index; | 852 --index; |
| 853 } else { | 853 } else { |
| 854 TabRendererGtk::AnimationState state; | 854 TabRendererGtk::AnimationState state; |
| 855 TabContentsWrapper* contents = model_->GetTabContentsAt(index); | 855 TabContents* contents = model_->GetTabContentsAt(index); |
| 856 if (!contents || !contents->web_contents()->IsLoading()) { | 856 if (!contents || !contents->web_contents()->IsLoading()) { |
| 857 state = TabGtk::ANIMATION_NONE; | 857 state = TabGtk::ANIMATION_NONE; |
| 858 } else if (contents->web_contents()->IsWaitingForResponse()) { | 858 } else if (contents->web_contents()->IsWaitingForResponse()) { |
| 859 state = TabGtk::ANIMATION_WAITING; | 859 state = TabGtk::ANIMATION_WAITING; |
| 860 } else { | 860 } else { |
| 861 state = TabGtk::ANIMATION_LOADING; | 861 state = TabGtk::ANIMATION_LOADING; |
| 862 } | 862 } |
| 863 if (current_tab->ValidateLoadingAnimation(state)) { | 863 if (current_tab->ValidateLoadingAnimation(state)) { |
| 864 // Queue the tab's icon area to be repainted. | 864 // Queue the tab's icon area to be repainted. |
| 865 gfx::Rect favicon_bounds = current_tab->favicon_bounds(); | 865 gfx::Rect favicon_bounds = current_tab->favicon_bounds(); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 961 } | 961 } |
| 962 } | 962 } |
| 963 } | 963 } |
| 964 | 964 |
| 965 return NULL; | 965 return NULL; |
| 966 } | 966 } |
| 967 | 967 |
| 968 //////////////////////////////////////////////////////////////////////////////// | 968 //////////////////////////////////////////////////////////////////////////////// |
| 969 // TabStripGtk, TabStripModelObserver implementation: | 969 // TabStripGtk, TabStripModelObserver implementation: |
| 970 | 970 |
| 971 void TabStripGtk::TabInsertedAt(TabContentsWrapper* contents, | 971 void TabStripGtk::TabInsertedAt(TabContents* contents, |
| 972 int index, | 972 int index, |
| 973 bool foreground) { | 973 bool foreground) { |
| 974 TRACE_EVENT0("ui::gtk", "TabStripGtk::TabInsertedAt"); | 974 TRACE_EVENT0("ui::gtk", "TabStripGtk::TabInsertedAt"); |
| 975 | 975 |
| 976 DCHECK(contents); | 976 DCHECK(contents); |
| 977 DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index)); | 977 DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index)); |
| 978 | 978 |
| 979 StopAnimation(); | 979 StopAnimation(); |
| 980 | 980 |
| 981 bool contains_tab = false; | 981 bool contains_tab = false; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1026 // if GTK paints before the animation event the tab is painted at 0x0 | 1026 // if GTK paints before the animation event the tab is painted at 0x0 |
| 1027 // which is most likely not where it should be positioned. | 1027 // which is most likely not where it should be positioned. |
| 1028 active_animation_->AnimationProgressed(NULL); | 1028 active_animation_->AnimationProgressed(NULL); |
| 1029 } else { | 1029 } else { |
| 1030 Layout(); | 1030 Layout(); |
| 1031 } | 1031 } |
| 1032 | 1032 |
| 1033 ReStack(); | 1033 ReStack(); |
| 1034 } | 1034 } |
| 1035 | 1035 |
| 1036 void TabStripGtk::TabDetachedAt(TabContentsWrapper* contents, int index) { | 1036 void TabStripGtk::TabDetachedAt(TabContents* contents, int index) { |
| 1037 GenerateIdealBounds(); | 1037 GenerateIdealBounds(); |
| 1038 StartRemoveTabAnimation(index, contents->web_contents()); | 1038 StartRemoveTabAnimation(index, contents->web_contents()); |
| 1039 // Have to do this _after_ calling StartRemoveTabAnimation, so that any | 1039 // Have to do this _after_ calling StartRemoveTabAnimation, so that any |
| 1040 // previous remove is completed fully and index is valid in sync with the | 1040 // previous remove is completed fully and index is valid in sync with the |
| 1041 // model index. | 1041 // model index. |
| 1042 GetTabAt(index)->set_closing(true); | 1042 GetTabAt(index)->set_closing(true); |
| 1043 } | 1043 } |
| 1044 | 1044 |
| 1045 void TabStripGtk::ActiveTabChanged(TabContentsWrapper* old_contents, | 1045 void TabStripGtk::ActiveTabChanged(TabContents* old_contents, |
| 1046 TabContentsWrapper* new_contents, | 1046 TabContents* new_contents, |
| 1047 int index, | 1047 int index, |
| 1048 bool user_gesture) { | 1048 bool user_gesture) { |
| 1049 TRACE_EVENT0("ui::gtk", "TabStripGtk::ActiveTabChanged"); | 1049 TRACE_EVENT0("ui::gtk", "TabStripGtk::ActiveTabChanged"); |
| 1050 ReStack(); | 1050 ReStack(); |
| 1051 } | 1051 } |
| 1052 | 1052 |
| 1053 void TabStripGtk::TabSelectionChanged(TabStripModel* tab_strip_model, | 1053 void TabStripGtk::TabSelectionChanged(TabStripModel* tab_strip_model, |
| 1054 const TabStripSelectionModel& old_model) { | 1054 const TabStripSelectionModel& old_model) { |
| 1055 // We have "tiny tabs" if the tabs are so tiny that the unselected ones are | 1055 // We have "tiny tabs" if the tabs are so tiny that the unselected ones are |
| 1056 // a different size to the selected ones. | 1056 // a different size to the selected ones. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1090 old_model.selected_indices().end(), | 1090 old_model.selected_indices().end(), |
| 1091 model_->selection_model().selected_indices().begin(), | 1091 model_->selection_model().selected_indices().begin(), |
| 1092 model_->selection_model().selected_indices().end(), | 1092 model_->selection_model().selected_indices().end(), |
| 1093 it2); | 1093 it2); |
| 1094 for (std::vector<int>::iterator it = no_longer_selected.begin(); | 1094 for (std::vector<int>::iterator it = no_longer_selected.begin(); |
| 1095 it != no_longer_selected.end(); ++it) { | 1095 it != no_longer_selected.end(); ++it) { |
| 1096 GetTabAtAdjustForAnimation(*it)->StopMiniTabTitleAnimation(); | 1096 GetTabAtAdjustForAnimation(*it)->StopMiniTabTitleAnimation(); |
| 1097 } | 1097 } |
| 1098 } | 1098 } |
| 1099 | 1099 |
| 1100 void TabStripGtk::TabMoved(TabContentsWrapper* contents, | 1100 void TabStripGtk::TabMoved(TabContents* contents, |
| 1101 int from_index, | 1101 int from_index, |
| 1102 int to_index) { | 1102 int to_index) { |
| 1103 gfx::Rect start_bounds = GetIdealBounds(from_index); | 1103 gfx::Rect start_bounds = GetIdealBounds(from_index); |
| 1104 TabGtk* tab = GetTabAt(from_index); | 1104 TabGtk* tab = GetTabAt(from_index); |
| 1105 tab_data_.erase(tab_data_.begin() + from_index); | 1105 tab_data_.erase(tab_data_.begin() + from_index); |
| 1106 TabData data = {tab, gfx::Rect()}; | 1106 TabData data = {tab, gfx::Rect()}; |
| 1107 tab->set_mini(model_->IsMiniTab(to_index)); | 1107 tab->set_mini(model_->IsMiniTab(to_index)); |
| 1108 tab->SetBlocked(model_->IsTabBlocked(to_index)); | 1108 tab->SetBlocked(model_->IsTabBlocked(to_index)); |
| 1109 tab_data_.insert(tab_data_.begin() + to_index, data); | 1109 tab_data_.insert(tab_data_.begin() + to_index, data); |
| 1110 GenerateIdealBounds(); | 1110 GenerateIdealBounds(); |
| 1111 StartMoveTabAnimation(from_index, to_index); | 1111 StartMoveTabAnimation(from_index, to_index); |
| 1112 ReStack(); | 1112 ReStack(); |
| 1113 } | 1113 } |
| 1114 | 1114 |
| 1115 void TabStripGtk::TabChangedAt(TabContentsWrapper* contents, int index, | 1115 void TabStripGtk::TabChangedAt(TabContents* contents, int index, |
| 1116 TabChangeType change_type) { | 1116 TabChangeType change_type) { |
| 1117 // Index is in terms of the model. Need to make sure we adjust that index in | 1117 // Index is in terms of the model. Need to make sure we adjust that index in |
| 1118 // case we have an animation going. | 1118 // case we have an animation going. |
| 1119 TabGtk* tab = GetTabAtAdjustForAnimation(index); | 1119 TabGtk* tab = GetTabAtAdjustForAnimation(index); |
| 1120 if (change_type == TITLE_NOT_LOADING) { | 1120 if (change_type == TITLE_NOT_LOADING) { |
| 1121 if (tab->mini() && !tab->IsActive()) | 1121 if (tab->mini() && !tab->IsActive()) |
| 1122 tab->StartMiniTabTitleAnimation(); | 1122 tab->StartMiniTabTitleAnimation(); |
| 1123 // We'll receive another notification of the change asynchronously. | 1123 // We'll receive another notification of the change asynchronously. |
| 1124 return; | 1124 return; |
| 1125 } | 1125 } |
| 1126 tab->UpdateData(contents->web_contents(), | 1126 tab->UpdateData(contents->web_contents(), |
| 1127 model_->IsAppTab(index), | 1127 model_->IsAppTab(index), |
| 1128 change_type == LOADING_ONLY); | 1128 change_type == LOADING_ONLY); |
| 1129 tab->UpdateFromModel(); | 1129 tab->UpdateFromModel(); |
| 1130 } | 1130 } |
| 1131 | 1131 |
| 1132 void TabStripGtk::TabReplacedAt(TabStripModel* tab_strip_model, | 1132 void TabStripGtk::TabReplacedAt(TabStripModel* tab_strip_model, |
| 1133 TabContentsWrapper* old_contents, | 1133 TabContents* old_contents, |
| 1134 TabContentsWrapper* new_contents, | 1134 TabContents* new_contents, |
| 1135 int index) { | 1135 int index) { |
| 1136 TabChangedAt(new_contents, index, ALL); | 1136 TabChangedAt(new_contents, index, ALL); |
| 1137 } | 1137 } |
| 1138 | 1138 |
| 1139 void TabStripGtk::TabMiniStateChanged(TabContentsWrapper* contents, int index) { | 1139 void TabStripGtk::TabMiniStateChanged(TabContents* contents, int index) { |
| 1140 // Don't do anything if we've already picked up the change from TabMoved. | 1140 // Don't do anything if we've already picked up the change from TabMoved. |
| 1141 if (GetTabAt(index)->mini() == model_->IsMiniTab(index)) | 1141 if (GetTabAt(index)->mini() == model_->IsMiniTab(index)) |
| 1142 return; | 1142 return; |
| 1143 | 1143 |
| 1144 GetTabAt(index)->set_mini(model_->IsMiniTab(index)); | 1144 GetTabAt(index)->set_mini(model_->IsMiniTab(index)); |
| 1145 // Don't animate if the window isn't visible yet. The window won't be visible | 1145 // Don't animate if the window isn't visible yet. The window won't be visible |
| 1146 // when dragging a mini-tab to a new window. | 1146 // when dragging a mini-tab to a new window. |
| 1147 if (window_ && window_->window() && | 1147 if (window_ && window_->window() && |
| 1148 gtk_widget_get_visible(GTK_WIDGET(window_->window()))) { | 1148 gtk_widget_get_visible(GTK_WIDGET(window_->window()))) { |
| 1149 StartMiniTabAnimation(index); | 1149 StartMiniTabAnimation(index); |
| 1150 } else { | 1150 } else { |
| 1151 Layout(); | 1151 Layout(); |
| 1152 } | 1152 } |
| 1153 } | 1153 } |
| 1154 | 1154 |
| 1155 void TabStripGtk::TabBlockedStateChanged(TabContentsWrapper* contents, | 1155 void TabStripGtk::TabBlockedStateChanged(TabContents* contents, |
| 1156 int index) { | 1156 int index) { |
| 1157 GetTabAt(index)->SetBlocked(model_->IsTabBlocked(index)); | 1157 GetTabAt(index)->SetBlocked(model_->IsTabBlocked(index)); |
| 1158 } | 1158 } |
| 1159 | 1159 |
| 1160 //////////////////////////////////////////////////////////////////////////////// | 1160 //////////////////////////////////////////////////////////////////////////////// |
| 1161 // TabStripGtk, TabGtk::TabDelegate implementation: | 1161 // TabStripGtk, TabGtk::TabDelegate implementation: |
| 1162 | 1162 |
| 1163 bool TabStripGtk::IsTabActive(const TabGtk* tab) const { | 1163 bool TabStripGtk::IsTabActive(const TabGtk* tab) const { |
| 1164 if (tab->closing()) | 1164 if (tab->closing()) |
| 1165 return false; | 1165 return false; |
| (...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2065 gtk_container_propagate_expose(GTK_CONTAINER(tabstrip_.get()), | 2065 gtk_container_propagate_expose(GTK_CONTAINER(tabstrip_.get()), |
| 2066 newtab_button_->widget(), event); | 2066 newtab_button_->widget(), event); |
| 2067 | 2067 |
| 2068 // Paint the tabs in reverse order, so they stack to the left. | 2068 // Paint the tabs in reverse order, so they stack to the left. |
| 2069 TabGtk* selected_tab = NULL; | 2069 TabGtk* selected_tab = NULL; |
| 2070 int tab_count = GetTabCount(); | 2070 int tab_count = GetTabCount(); |
| 2071 for (int i = tab_count - 1; i >= 0; --i) { | 2071 for (int i = tab_count - 1; i >= 0; --i) { |
| 2072 TabGtk* tab = GetTabAt(i); | 2072 TabGtk* tab = GetTabAt(i); |
| 2073 // We must ask the _Tab's_ model, not ourselves, because in some situations | 2073 // We must ask the _Tab's_ model, not ourselves, because in some situations |
| 2074 // the model will be different to this object, e.g. when a Tab is being | 2074 // the model will be different to this object, e.g. when a Tab is being |
| 2075 // removed after its TabContentsWrapper has been destroyed. | 2075 // removed after its TabContents has been destroyed. |
| 2076 if (!tab->IsActive()) { | 2076 if (!tab->IsActive()) { |
| 2077 gtk_container_propagate_expose(GTK_CONTAINER(tabstrip_.get()), | 2077 gtk_container_propagate_expose(GTK_CONTAINER(tabstrip_.get()), |
| 2078 tab->widget(), event); | 2078 tab->widget(), event); |
| 2079 } else { | 2079 } else { |
| 2080 selected_tab = tab; | 2080 selected_tab = tab; |
| 2081 } | 2081 } |
| 2082 } | 2082 } |
| 2083 | 2083 |
| 2084 // Paint the selected tab last, so it overlaps all the others. | 2084 // Paint the selected tab last, so it overlaps all the others. |
| 2085 if (selected_tab) { | 2085 if (selected_tab) { |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2256 } | 2256 } |
| 2257 | 2257 |
| 2258 void TabStripGtk::SetNewTabButtonBackground() { | 2258 void TabStripGtk::SetNewTabButtonBackground() { |
| 2259 SkColor color = theme_service_->GetColor( | 2259 SkColor color = theme_service_->GetColor( |
| 2260 ThemeService::COLOR_BUTTON_BACKGROUND); | 2260 ThemeService::COLOR_BUTTON_BACKGROUND); |
| 2261 SkBitmap* background = theme_service_->GetBitmapNamed( | 2261 SkBitmap* background = theme_service_->GetBitmapNamed( |
| 2262 IDR_THEME_WINDOW_CONTROL_BACKGROUND); | 2262 IDR_THEME_WINDOW_CONTROL_BACKGROUND); |
| 2263 SkBitmap* mask = theme_service_->GetBitmapNamed(IDR_NEWTAB_BUTTON_MASK); | 2263 SkBitmap* mask = theme_service_->GetBitmapNamed(IDR_NEWTAB_BUTTON_MASK); |
| 2264 newtab_button_->SetBackground(color, background, mask); | 2264 newtab_button_->SetBackground(color, background, mask); |
| 2265 } | 2265 } |
| OLD | NEW |