OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/gtk/tabs/tab_strip_gtk.h" | 5 #include "chrome/browser/gtk/tabs/tab_strip_gtk.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "app/gtk_dnd_util.h" | 9 #include "app/gtk_dnd_util.h" |
10 #include "app/resource_bundle.h" | 10 #include "app/resource_bundle.h" |
11 #include "app/slide_animation.h" | 11 #include "app/slide_animation.h" |
12 #include "base/i18n/rtl.h" | 12 #include "base/i18n/rtl.h" |
13 #include "base/string_util.h" | 13 #include "base/string_util.h" |
14 #include "chrome/browser/autocomplete/autocomplete.h" | 14 #include "chrome/browser/autocomplete/autocomplete.h" |
15 #include "chrome/browser/gtk/browser_window_gtk.h" | 15 #include "chrome/browser/gtk/browser_window_gtk.h" |
16 #include "chrome/browser/gtk/custom_button.h" | 16 #include "chrome/browser/gtk/custom_button.h" |
17 #include "chrome/browser/gtk/gtk_theme_provider.h" | 17 #include "chrome/browser/gtk/gtk_theme_provider.h" |
18 #include "chrome/browser/gtk/gtk_util.h" | 18 #include "chrome/browser/gtk/gtk_util.h" |
19 #include "chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h" | 19 #include "chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h" |
20 #include "chrome/browser/profile.h" | 20 #include "chrome/browser/profile.h" |
21 #include "chrome/browser/tab_contents/tab_contents.h" | 21 #include "chrome/browser/tab_contents/tab_contents.h" |
| 22 #include "chrome/browser/tab_contents_wrapper.h" |
22 #include "chrome/browser/tabs/tab_strip_model_delegate.h" | 23 #include "chrome/browser/tabs/tab_strip_model_delegate.h" |
23 #include "chrome/browser/themes/browser_theme_provider.h" | 24 #include "chrome/browser/themes/browser_theme_provider.h" |
24 #include "chrome/browser/ui/browser.h" | 25 #include "chrome/browser/ui/browser.h" |
25 #include "chrome/browser/ui/browser_navigator.h" | 26 #include "chrome/browser/ui/browser_navigator.h" |
26 #include "chrome/common/notification_service.h" | 27 #include "chrome/common/notification_service.h" |
27 #include "chrome/common/notification_type.h" | 28 #include "chrome/common/notification_type.h" |
28 #include "gfx/gtk_util.h" | 29 #include "gfx/gtk_util.h" |
29 #include "gfx/point.h" | 30 #include "gfx/point.h" |
30 #include "grit/app_resources.h" | 31 #include "grit/app_resources.h" |
31 #include "grit/theme_resources.h" | 32 #include "grit/theme_resources.h" |
(...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 bounds_ = bounds; | 806 bounds_ = bounds; |
806 } | 807 } |
807 | 808 |
808 void TabStripGtk::UpdateLoadingAnimations() { | 809 void TabStripGtk::UpdateLoadingAnimations() { |
809 for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) { | 810 for (int i = 0, index = 0; i < GetTabCount(); ++i, ++index) { |
810 TabGtk* current_tab = GetTabAt(i); | 811 TabGtk* current_tab = GetTabAt(i); |
811 if (current_tab->closing()) { | 812 if (current_tab->closing()) { |
812 --index; | 813 --index; |
813 } else { | 814 } else { |
814 TabRendererGtk::AnimationState state; | 815 TabRendererGtk::AnimationState state; |
815 TabContents* contents = model_->GetTabContentsAt(index); | 816 TabContentsWrapper* contents = model_->GetTabContentsAt(index); |
816 if (!contents || !contents->is_loading()) { | 817 if (!contents || !contents->tab_contents()->is_loading()) { |
817 state = TabGtk::ANIMATION_NONE; | 818 state = TabGtk::ANIMATION_NONE; |
818 } else if (contents->waiting_for_response()) { | 819 } else if (contents->tab_contents()->waiting_for_response()) { |
819 state = TabGtk::ANIMATION_WAITING; | 820 state = TabGtk::ANIMATION_WAITING; |
820 } else { | 821 } else { |
821 state = TabGtk::ANIMATION_LOADING; | 822 state = TabGtk::ANIMATION_LOADING; |
822 } | 823 } |
823 if (current_tab->ValidateLoadingAnimation(state)) { | 824 if (current_tab->ValidateLoadingAnimation(state)) { |
824 // Queue the tab's icon area to be repainted. | 825 // Queue the tab's icon area to be repainted. |
825 gfx::Rect favicon_bounds = current_tab->favicon_bounds(); | 826 gfx::Rect favicon_bounds = current_tab->favicon_bounds(); |
826 gtk_widget_queue_draw_area(tabstrip_.get(), | 827 gtk_widget_queue_draw_area(tabstrip_.get(), |
827 favicon_bounds.x() + current_tab->x(), | 828 favicon_bounds.x() + current_tab->x(), |
828 favicon_bounds.y() + current_tab->y(), | 829 favicon_bounds.y() + current_tab->y(), |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
917 } | 918 } |
918 } | 919 } |
919 } | 920 } |
920 | 921 |
921 return NULL; | 922 return NULL; |
922 } | 923 } |
923 | 924 |
924 //////////////////////////////////////////////////////////////////////////////// | 925 //////////////////////////////////////////////////////////////////////////////// |
925 // TabStripGtk, TabStripModelObserver implementation: | 926 // TabStripGtk, TabStripModelObserver implementation: |
926 | 927 |
927 void TabStripGtk::TabInsertedAt(TabContents* contents, | 928 void TabStripGtk::TabInsertedAt(TabContentsWrapper* contents, |
928 int index, | 929 int index, |
929 bool foreground) { | 930 bool foreground) { |
930 DCHECK(contents); | 931 DCHECK(contents); |
931 DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index)); | 932 DCHECK(index == TabStripModel::kNoTab || model_->ContainsIndex(index)); |
932 | 933 |
933 StopAnimation(); | 934 StopAnimation(); |
934 | 935 |
935 bool contains_tab = false; | 936 bool contains_tab = false; |
936 TabGtk* tab = NULL; | 937 TabGtk* tab = NULL; |
937 // First see if this Tab is one that was dragged out of this TabStrip and is | 938 // First see if this Tab is one that was dragged out of this TabStrip and is |
938 // now being dragged back in. In this case, the DraggedTabController actually | 939 // now being dragged back in. In this case, the DraggedTabController actually |
939 // has the Tab already constructed and we can just insert it into our list | 940 // has the Tab already constructed and we can just insert it into our list |
940 // again. | 941 // again. |
941 if (IsDragSessionActive()) { | 942 if (IsDragSessionActive()) { |
942 tab = drag_controller_->GetDragSourceTabForContents(contents); | 943 tab = drag_controller_->GetDragSourceTabForContents( |
| 944 contents->tab_contents()); |
943 if (tab) { | 945 if (tab) { |
944 // If the Tab was detached, it would have been animated closed but not | 946 // If the Tab was detached, it would have been animated closed but not |
945 // removed, so we need to reset this property. | 947 // removed, so we need to reset this property. |
946 tab->set_closing(false); | 948 tab->set_closing(false); |
947 tab->ValidateLoadingAnimation(TabRendererGtk::ANIMATION_NONE); | 949 tab->ValidateLoadingAnimation(TabRendererGtk::ANIMATION_NONE); |
948 tab->SetVisible(true); | 950 tab->SetVisible(true); |
949 } | 951 } |
950 | 952 |
951 // See if we're already in the list. We don't want to add ourselves twice. | 953 // See if we're already in the list. We don't want to add ourselves twice. |
952 std::vector<TabData>::const_iterator iter = tab_data_.begin(); | 954 std::vector<TabData>::const_iterator iter = tab_data_.begin(); |
953 for (; iter != tab_data_.end() && !contains_tab; ++iter) { | 955 for (; iter != tab_data_.end() && !contains_tab; ++iter) { |
954 if (iter->tab == tab) | 956 if (iter->tab == tab) |
955 contains_tab = true; | 957 contains_tab = true; |
956 } | 958 } |
957 } | 959 } |
958 | 960 |
959 if (!tab) | 961 if (!tab) |
960 tab = new TabGtk(this); | 962 tab = new TabGtk(this); |
961 | 963 |
962 // Only insert if we're not already in the list. | 964 // Only insert if we're not already in the list. |
963 if (!contains_tab) { | 965 if (!contains_tab) { |
964 TabData d = { tab, gfx::Rect() }; | 966 TabData d = { tab, gfx::Rect() }; |
965 tab_data_.insert(tab_data_.begin() + index, d); | 967 tab_data_.insert(tab_data_.begin() + index, d); |
966 tab->UpdateData(contents, model_->IsAppTab(index), false); | 968 tab->UpdateData(contents->tab_contents(), model_->IsAppTab(index), false); |
967 } | 969 } |
968 tab->set_mini(model_->IsMiniTab(index)); | 970 tab->set_mini(model_->IsMiniTab(index)); |
969 tab->set_app(model_->IsAppTab(index)); | 971 tab->set_app(model_->IsAppTab(index)); |
970 tab->SetBlocked(model_->IsTabBlocked(index)); | 972 tab->SetBlocked(model_->IsTabBlocked(index)); |
971 | 973 |
972 if (gtk_widget_get_parent(tab->widget()) != tabstrip_.get()) | 974 if (gtk_widget_get_parent(tab->widget()) != tabstrip_.get()) |
973 gtk_fixed_put(GTK_FIXED(tabstrip_.get()), tab->widget(), 0, 0); | 975 gtk_fixed_put(GTK_FIXED(tabstrip_.get()), tab->widget(), 0, 0); |
974 | 976 |
975 // Don't animate the first tab; it looks weird. | 977 // Don't animate the first tab; it looks weird. |
976 if (GetTabCount() > 1) { | 978 if (GetTabCount() > 1) { |
977 StartInsertTabAnimation(index); | 979 StartInsertTabAnimation(index); |
978 // We added the tab at 0x0, we need to force an animation step otherwise | 980 // We added the tab at 0x0, we need to force an animation step otherwise |
979 // if GTK paints before the animation event the tab is painted at 0x0 | 981 // if GTK paints before the animation event the tab is painted at 0x0 |
980 // which is most likely not where it should be positioned. | 982 // which is most likely not where it should be positioned. |
981 active_animation_->AnimationProgressed(NULL); | 983 active_animation_->AnimationProgressed(NULL); |
982 } else { | 984 } else { |
983 Layout(); | 985 Layout(); |
984 } | 986 } |
985 } | 987 } |
986 | 988 |
987 void TabStripGtk::TabDetachedAt(TabContents* contents, int index) { | 989 void TabStripGtk::TabDetachedAt(TabContentsWrapper* contents, int index) { |
988 GenerateIdealBounds(); | 990 GenerateIdealBounds(); |
989 StartRemoveTabAnimation(index, contents); | 991 StartRemoveTabAnimation(index, contents->tab_contents()); |
990 // Have to do this _after_ calling StartRemoveTabAnimation, so that any | 992 // Have to do this _after_ calling StartRemoveTabAnimation, so that any |
991 // previous remove is completed fully and index is valid in sync with the | 993 // previous remove is completed fully and index is valid in sync with the |
992 // model index. | 994 // model index. |
993 GetTabAt(index)->set_closing(true); | 995 GetTabAt(index)->set_closing(true); |
994 } | 996 } |
995 | 997 |
996 void TabStripGtk::TabSelectedAt(TabContents* old_contents, | 998 void TabStripGtk::TabSelectedAt(TabContentsWrapper* old_contents, |
997 TabContents* new_contents, | 999 TabContentsWrapper* new_contents, |
998 int index, | 1000 int index, |
999 bool user_gesture) { | 1001 bool user_gesture) { |
1000 DCHECK(index >= 0 && index < static_cast<int>(GetTabCount())); | 1002 DCHECK(index >= 0 && index < static_cast<int>(GetTabCount())); |
1001 | 1003 |
1002 // We have "tiny tabs" if the tabs are so tiny that the unselected ones are | 1004 // We have "tiny tabs" if the tabs are so tiny that the unselected ones are |
1003 // a different size to the selected ones. | 1005 // a different size to the selected ones. |
1004 bool tiny_tabs = current_unselected_width_ != current_selected_width_; | 1006 bool tiny_tabs = current_unselected_width_ != current_selected_width_; |
1005 if (!IsAnimating() && (!needs_resize_layout_ || tiny_tabs)) | 1007 if (!IsAnimating() && (!needs_resize_layout_ || tiny_tabs)) |
1006 Layout(); | 1008 Layout(); |
1007 | 1009 |
1008 GetTabAt(index)->SchedulePaint(); | 1010 GetTabAt(index)->SchedulePaint(); |
1009 | 1011 |
1010 int old_index = model_->GetIndexOfTabContents(old_contents); | 1012 int old_index = model_->GetIndexOfTabContents(old_contents); |
1011 if (old_index >= 0) { | 1013 if (old_index >= 0) { |
1012 GetTabAt(old_index)->SchedulePaint(); | 1014 GetTabAt(old_index)->SchedulePaint(); |
1013 GetTabAt(old_index)->StopMiniTabTitleAnimation(); | 1015 GetTabAt(old_index)->StopMiniTabTitleAnimation(); |
1014 } | 1016 } |
1015 } | 1017 } |
1016 | 1018 |
1017 void TabStripGtk::TabMoved(TabContents* contents, | 1019 void TabStripGtk::TabMoved(TabContentsWrapper* contents, |
1018 int from_index, | 1020 int from_index, |
1019 int to_index) { | 1021 int to_index) { |
1020 gfx::Rect start_bounds = GetIdealBounds(from_index); | 1022 gfx::Rect start_bounds = GetIdealBounds(from_index); |
1021 TabGtk* tab = GetTabAt(from_index); | 1023 TabGtk* tab = GetTabAt(from_index); |
1022 tab_data_.erase(tab_data_.begin() + from_index); | 1024 tab_data_.erase(tab_data_.begin() + from_index); |
1023 TabData data = {tab, gfx::Rect()}; | 1025 TabData data = {tab, gfx::Rect()}; |
1024 tab->set_mini(model_->IsMiniTab(to_index)); | 1026 tab->set_mini(model_->IsMiniTab(to_index)); |
1025 tab->SetBlocked(model_->IsTabBlocked(to_index)); | 1027 tab->SetBlocked(model_->IsTabBlocked(to_index)); |
1026 tab_data_.insert(tab_data_.begin() + to_index, data); | 1028 tab_data_.insert(tab_data_.begin() + to_index, data); |
1027 GenerateIdealBounds(); | 1029 GenerateIdealBounds(); |
1028 StartMoveTabAnimation(from_index, to_index); | 1030 StartMoveTabAnimation(from_index, to_index); |
1029 } | 1031 } |
1030 | 1032 |
1031 void TabStripGtk::TabChangedAt(TabContents* contents, int index, | 1033 void TabStripGtk::TabChangedAt(TabContentsWrapper* contents, int index, |
1032 TabChangeType change_type) { | 1034 TabChangeType change_type) { |
1033 // Index is in terms of the model. Need to make sure we adjust that index in | 1035 // Index is in terms of the model. Need to make sure we adjust that index in |
1034 // case we have an animation going. | 1036 // case we have an animation going. |
1035 TabGtk* tab = GetTabAtAdjustForAnimation(index); | 1037 TabGtk* tab = GetTabAtAdjustForAnimation(index); |
1036 if (change_type == TITLE_NOT_LOADING) { | 1038 if (change_type == TITLE_NOT_LOADING) { |
1037 if (tab->mini() && !tab->IsSelected()) | 1039 if (tab->mini() && !tab->IsSelected()) |
1038 tab->StartMiniTabTitleAnimation(); | 1040 tab->StartMiniTabTitleAnimation(); |
1039 // We'll receive another notification of the change asynchronously. | 1041 // We'll receive another notification of the change asynchronously. |
1040 return; | 1042 return; |
1041 } | 1043 } |
1042 tab->UpdateData(contents, | 1044 tab->UpdateData(contents->tab_contents(), |
1043 model_->IsAppTab(index), | 1045 model_->IsAppTab(index), |
1044 change_type == LOADING_ONLY); | 1046 change_type == LOADING_ONLY); |
1045 tab->UpdateFromModel(); | 1047 tab->UpdateFromModel(); |
1046 } | 1048 } |
1047 | 1049 |
1048 void TabStripGtk::TabReplacedAt(TabContents* old_contents, | 1050 void TabStripGtk::TabReplacedAt(TabContentsWrapper* old_contents, |
1049 TabContents* new_contents, | 1051 TabContentsWrapper* new_contents, |
1050 int index) { | 1052 int index) { |
1051 TabChangedAt(new_contents, index, ALL); | 1053 TabChangedAt(new_contents, index, ALL); |
1052 } | 1054 } |
1053 | 1055 |
1054 void TabStripGtk::TabMiniStateChanged(TabContents* contents, int index) { | 1056 void TabStripGtk::TabMiniStateChanged(TabContentsWrapper* contents, int index) { |
1055 // Don't do anything if we've already picked up the change from TabMoved. | 1057 // Don't do anything if we've already picked up the change from TabMoved. |
1056 if (GetTabAt(index)->mini() == model_->IsMiniTab(index)) | 1058 if (GetTabAt(index)->mini() == model_->IsMiniTab(index)) |
1057 return; | 1059 return; |
1058 | 1060 |
1059 GetTabAt(index)->set_mini(model_->IsMiniTab(index)); | 1061 GetTabAt(index)->set_mini(model_->IsMiniTab(index)); |
1060 // Don't animate if the window isn't visible yet. The window won't be visible | 1062 // Don't animate if the window isn't visible yet. The window won't be visible |
1061 // when dragging a mini-tab to a new window. | 1063 // when dragging a mini-tab to a new window. |
1062 if (window_ && window_->window() && | 1064 if (window_ && window_->window() && |
1063 GTK_WIDGET_VISIBLE(GTK_WIDGET(window_->window()))) { | 1065 GTK_WIDGET_VISIBLE(GTK_WIDGET(window_->window()))) { |
1064 StartMiniTabAnimation(index); | 1066 StartMiniTabAnimation(index); |
1065 } else { | 1067 } else { |
1066 Layout(); | 1068 Layout(); |
1067 } | 1069 } |
1068 } | 1070 } |
1069 | 1071 |
1070 void TabStripGtk::TabBlockedStateChanged(TabContents* contents, int index) { | 1072 void TabStripGtk::TabBlockedStateChanged(TabContentsWrapper* contents, |
| 1073 int index) { |
1071 GetTabAt(index)->SetBlocked(model_->IsTabBlocked(index)); | 1074 GetTabAt(index)->SetBlocked(model_->IsTabBlocked(index)); |
1072 } | 1075 } |
1073 | 1076 |
1074 //////////////////////////////////////////////////////////////////////////////// | 1077 //////////////////////////////////////////////////////////////////////////////// |
1075 // TabStripGtk, TabGtk::TabDelegate implementation: | 1078 // TabStripGtk, TabGtk::TabDelegate implementation: |
1076 | 1079 |
1077 bool TabStripGtk::IsTabSelected(const TabGtk* tab) const { | 1080 bool TabStripGtk::IsTabSelected(const TabGtk* tab) const { |
1078 if (tab->closing()) | 1081 if (tab->closing()) |
1079 return false; | 1082 return false; |
1080 | 1083 |
(...skipping 887 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1968 case 1: | 1971 case 1: |
1969 model_->delegate()->AddBlankTab(true); | 1972 model_->delegate()->AddBlankTab(true); |
1970 break; | 1973 break; |
1971 case 2: { | 1974 case 2: { |
1972 // On middle-click, try to parse the PRIMARY selection as a URL and load | 1975 // On middle-click, try to parse the PRIMARY selection as a URL and load |
1973 // it instead of creating a blank page. | 1976 // it instead of creating a blank page. |
1974 GURL url; | 1977 GURL url; |
1975 if (!gtk_util::URLFromPrimarySelection(model_->profile(), &url)) | 1978 if (!gtk_util::URLFromPrimarySelection(model_->profile(), &url)) |
1976 return; | 1979 return; |
1977 | 1980 |
| 1981 <<<<<<< .mine |
| 1982 TabContentsWrapper* contents = |
| 1983 model_->delegate()->CreateTabContentsForURL( |
| 1984 url, |
| 1985 GURL(), // referrer |
| 1986 model_->profile(), |
| 1987 PageTransition::TYPED, |
| 1988 false, // defer_load |
| 1989 NULL); // instance |
| 1990 model_->AddTabContents( |
| 1991 contents, |
| 1992 -1, // index |
| 1993 PageTransition::TYPED, |
| 1994 TabStripModel::ADD_SELECTED); |
| 1995 ======= |
1978 Browser* browser = window_->browser(); | 1996 Browser* browser = window_->browser(); |
1979 DCHECK(browser); | 1997 DCHECK(browser); |
1980 browser->AddSelectedTabWithURL(url, PageTransition::TYPED); | 1998 browser->AddSelectedTabWithURL(url, PageTransition::TYPED); |
| 1999 >>>>>>> .r66288 |
1981 break; | 2000 break; |
1982 } | 2001 } |
1983 default: | 2002 default: |
1984 NOTREACHED() << "Got click on new tab button with unhandled mouse " | 2003 NOTREACHED() << "Got click on new tab button with unhandled mouse " |
1985 << "button " << mouse_button; | 2004 << "button " << mouse_button; |
1986 } | 2005 } |
1987 } | 2006 } |
1988 | 2007 |
1989 void TabStripGtk::SetTabBounds(TabGtk* tab, const gfx::Rect& bounds) { | 2008 void TabStripGtk::SetTabBounds(TabGtk* tab, const gfx::Rect& bounds) { |
1990 gfx::Rect bds = bounds; | 2009 gfx::Rect bds = bounds; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2026 | 2045 |
2027 // Let the middle mouse button initiate clicks as well. | 2046 // Let the middle mouse button initiate clicks as well. |
2028 gtk_util::SetButtonTriggersNavigation(button->widget()); | 2047 gtk_util::SetButtonTriggersNavigation(button->widget()); |
2029 g_signal_connect(button->widget(), "clicked", | 2048 g_signal_connect(button->widget(), "clicked", |
2030 G_CALLBACK(OnNewTabClickedThunk), this); | 2049 G_CALLBACK(OnNewTabClickedThunk), this); |
2031 GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS); | 2050 GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS); |
2032 gtk_fixed_put(GTK_FIXED(tabstrip_.get()), button->widget(), 0, 0); | 2051 gtk_fixed_put(GTK_FIXED(tabstrip_.get()), button->widget(), 0, 0); |
2033 | 2052 |
2034 return button; | 2053 return button; |
2035 } | 2054 } |
OLD | NEW |