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/tab_contents_container_gtk.h" | 5 #include "chrome/browser/ui/gtk/tab_contents_container_gtk.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/i18n/rtl.h" | 9 #include "base/i18n/rtl.h" |
10 #include "chrome/browser/ui/gtk/status_bubble_gtk.h" | 10 #include "chrome/browser/ui/gtk/status_bubble_gtk.h" |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 G_CALLBACK(OnSetFloatingPosition), this); | 58 G_CALLBACK(OnSetFloatingPosition), this); |
59 } | 59 } |
60 | 60 |
61 gtk_widget_show(expanded_); | 61 gtk_widget_show(expanded_); |
62 gtk_widget_show(floating_.get()); | 62 gtk_widget_show(floating_.get()); |
63 | 63 |
64 ViewIDUtil::SetDelegateForWidget(widget(), this); | 64 ViewIDUtil::SetDelegateForWidget(widget(), this); |
65 } | 65 } |
66 | 66 |
67 void TabContentsContainerGtk::SetTab(TabContents* tab) { | 67 void TabContentsContainerGtk::SetTab(TabContents* tab) { |
68 HideTab(tab_); | 68 if (tab_ == tab) |
69 if (tab_) { | 69 return; |
70 registrar_.Remove(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, | 70 |
71 content::Source<TabContents>(tab_)); | 71 if (tab_) |
72 } | 72 HideTab(tab_); |
73 | 73 |
74 tab_ = tab; | 74 tab_ = tab; |
75 | 75 |
76 if (tab_ == preview_) { | 76 if (tab_) { |
77 // If the preview contents is becoming the new permanent tab contents, we | 77 // If the preview is becoming the new permanent tab, we just reassign some |
78 // just reassign some pointers. | 78 // pointers. Otherwise, we have to actually add it to the widget hierarchy. |
79 preview_ = NULL; | 79 if (tab_ == preview_) |
80 } else if (tab_) { | 80 preview_ = NULL; |
81 // Otherwise we actually have to add it to the widget hierarchy. | 81 else |
82 PackTab(tab); | 82 PackTab(tab_); |
83 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, | 83 |
84 content::Source<TabContents>(tab_)); | 84 // Make sure that the tab is below the find bar. Sometimes the content |
| 85 // native view will be null. |
| 86 GtkWidget* widget = tab_->web_contents()->GetContentNativeView(); |
| 87 if (widget) { |
| 88 GdkWindow* content_gdk_window = gtk_widget_get_window(widget); |
| 89 if (content_gdk_window) |
| 90 gdk_window_lower(content_gdk_window); |
| 91 } |
85 } | 92 } |
86 } | 93 } |
87 | 94 |
88 TabContents* TabContentsContainerGtk::GetVisibleTab() { | 95 void TabContentsContainerGtk::SetPreview(TabContents* preview) { |
89 return preview_ ? preview_ : tab_; | 96 if (preview_ == preview) |
90 } | 97 return; |
91 | 98 |
92 void TabContentsContainerGtk::SetPreview(TabContents* preview) { | 99 if (preview_) { |
93 if (preview_) | 100 HideTab(preview_); |
94 RemovePreview(); | 101 GtkWidget* preview_widget = preview_->web_contents()->GetNativeView(); |
95 else | 102 if (preview_widget) |
96 HideTab(tab_); | 103 gtk_container_remove(GTK_CONTAINER(expanded_), preview_widget); |
| 104 } |
97 | 105 |
98 preview_ = preview; | 106 preview_ = preview; |
99 | 107 |
100 PackTab(preview); | 108 if (preview_) |
101 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, | 109 PackTab(preview_); |
102 content::Source<TabContents>(preview_)); | |
103 } | |
104 | |
105 void TabContentsContainerGtk::RemovePreview() { | |
106 if (!preview_) | |
107 return; | |
108 | |
109 HideTab(preview_); | |
110 | |
111 GtkWidget* preview_widget = preview_->web_contents()->GetNativeView(); | |
112 if (preview_widget) | |
113 gtk_container_remove(GTK_CONTAINER(expanded_), preview_widget); | |
114 | |
115 registrar_.Remove(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, | |
116 content::Source<TabContents>(preview_)); | |
117 preview_ = NULL; | |
118 } | |
119 | |
120 void TabContentsContainerGtk::PopPreview() { | |
121 if (!preview_) | |
122 return; | |
123 | |
124 RemovePreview(); | |
125 | |
126 PackTab(tab_); | |
127 } | 110 } |
128 | 111 |
129 void TabContentsContainerGtk::PackTab(TabContents* tab) { | 112 void TabContentsContainerGtk::PackTab(TabContents* tab) { |
130 if (!tab) | |
131 return; | |
132 | |
133 gfx::NativeView widget = tab->web_contents()->GetNativeView(); | 113 gfx::NativeView widget = tab->web_contents()->GetNativeView(); |
134 if (widget) { | 114 if (widget) { |
135 if (gtk_widget_get_parent(widget) != expanded_) | 115 if (gtk_widget_get_parent(widget) != expanded_) |
136 gtk_container_add(GTK_CONTAINER(expanded_), widget); | 116 gtk_container_add(GTK_CONTAINER(expanded_), widget); |
137 gtk_widget_show(widget); | 117 gtk_widget_show(widget); |
138 } | 118 } |
139 | 119 |
140 // We need to make sure that we are below the findbar. | |
141 // Sometimes the content native view will be null. | |
142 if (tab->web_contents()->GetContentNativeView()) { | |
143 GdkWindow* content_gdk_window = gtk_widget_get_window( | |
144 tab->web_contents()->GetContentNativeView()); | |
145 if (content_gdk_window) | |
146 gdk_window_lower(content_gdk_window); | |
147 } | |
148 | |
149 tab->web_contents()->WasShown(); | 120 tab->web_contents()->WasShown(); |
| 121 registrar_.Add(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, |
| 122 content::Source<TabContents>(tab)); |
150 } | 123 } |
151 | 124 |
152 void TabContentsContainerGtk::HideTab(TabContents* tab) { | 125 void TabContentsContainerGtk::HideTab(TabContents* tab) { |
153 if (!tab) | |
154 return; | |
155 | |
156 gfx::NativeView widget = tab->web_contents()->GetNativeView(); | 126 gfx::NativeView widget = tab->web_contents()->GetNativeView(); |
157 if (widget) | 127 if (widget) |
158 gtk_widget_hide(widget); | 128 gtk_widget_hide(widget); |
159 | 129 |
160 tab->web_contents()->WasHidden(); | 130 tab->web_contents()->WasHidden(); |
| 131 registrar_.Remove(this, chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, |
| 132 content::Source<TabContents>(tab)); |
161 } | 133 } |
162 | 134 |
163 void TabContentsContainerGtk::DetachTab(TabContents* tab) { | 135 void TabContentsContainerGtk::DetachTab(TabContents* tab) { |
164 gfx::NativeView widget = tab->web_contents()->GetNativeView(); | 136 gfx::NativeView widget = tab->web_contents()->GetNativeView(); |
165 | 137 |
166 // It is possible to detach an unrealized, unparented WebContents if you | 138 // It is possible to detach an unrealized, unparented WebContents if you |
167 // slow things down enough in valgrind. Might happen in the real world, too. | 139 // slow things down enough in valgrind. Might happen in the real world, too. |
168 if (widget) { | 140 if (widget) { |
169 GtkWidget* parent = gtk_widget_get_parent(widget); | 141 GtkWidget* parent = gtk_widget_get_parent(widget); |
170 if (parent) { | 142 if (parent) { |
171 DCHECK_EQ(parent, expanded_); | 143 DCHECK_EQ(parent, expanded_); |
172 gtk_container_remove(GTK_CONTAINER(expanded_), widget); | 144 gtk_container_remove(GTK_CONTAINER(expanded_), widget); |
173 } | 145 } |
174 } | 146 } |
175 } | 147 } |
176 | 148 |
177 void TabContentsContainerGtk::Observe( | 149 void TabContentsContainerGtk::Observe( |
178 int type, | 150 int type, |
179 const content::NotificationSource& source, | 151 const content::NotificationSource& source, |
180 const content::NotificationDetails& details) { | 152 const content::NotificationDetails& details) { |
181 DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, type); | 153 DCHECK_EQ(chrome::NOTIFICATION_TAB_CONTENTS_DESTROYED, type); |
182 WebContentsDestroyed( | 154 WebContentsDestroyed( |
183 content::Source<TabContents>(source)->web_contents()); | 155 content::Source<TabContents>(source)->web_contents()); |
184 } | 156 } |
185 | 157 |
186 void TabContentsContainerGtk::WebContentsDestroyed(WebContents* contents) { | 158 void TabContentsContainerGtk::WebContentsDestroyed(WebContents* contents) { |
187 // Sometimes, a WebContents is destroyed before we know about it. This allows | 159 // Sometimes, a WebContents is destroyed before we know about it. This allows |
188 // us to clean up our state in case this happens. | 160 // us to clean up our state in case this happens. |
189 if (preview_ && contents == preview_->web_contents()) | 161 if (preview_ && contents == preview_->web_contents()) |
190 PopPreview(); | 162 SetPreview(NULL); |
191 else if (tab_ && contents == tab_->web_contents()) | 163 else if (tab_ && contents == tab_->web_contents()) |
192 SetTab(NULL); | 164 SetTab(NULL); |
193 else | 165 else |
194 NOTREACHED(); | 166 NOTREACHED(); |
195 } | 167 } |
196 | 168 |
197 // Prevent |preview_| from getting focus via the tab key. If |tab_| exists, try | 169 // Prevent |preview_| from getting focus via the tab key. If |tab_| exists, try |
198 // to focus that. Otherwise, do nothing, but stop event propagation. See bug | 170 // to focus that. Otherwise, do nothing, but stop event propagation. See bug |
199 // http://crbug.com/63365 | 171 // http://crbug.com/63365 |
200 gboolean TabContentsContainerGtk::OnFocus(GtkWidget* widget, | 172 gboolean TabContentsContainerGtk::OnFocus(GtkWidget* widget, |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 g_value_set_int(&value, allocation->width - requisition.width); | 213 g_value_set_int(&value, allocation->width - requisition.width); |
242 gtk_container_child_set_property(GTK_CONTAINER(floating_container), | 214 gtk_container_child_set_property(GTK_CONTAINER(floating_container), |
243 status->widget(), "x", &value); | 215 status->widget(), "x", &value); |
244 | 216 |
245 int child_y = std::max(allocation->height - requisition.height, 0); | 217 int child_y = std::max(allocation->height - requisition.height, 0); |
246 g_value_set_int(&value, child_y + status->y_offset()); | 218 g_value_set_int(&value, child_y + status->y_offset()); |
247 gtk_container_child_set_property(GTK_CONTAINER(floating_container), | 219 gtk_container_child_set_property(GTK_CONTAINER(floating_container), |
248 status->widget(), "y", &value); | 220 status->widget(), "y", &value); |
249 g_value_unset(&value); | 221 g_value_unset(&value); |
250 } | 222 } |
OLD | NEW |