Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(453)

Side by Side Diff: views/controls/native/native_view_host_gtk.cc

Issue 7171025: Fix flicker on tab switch on chromeos. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove all children instead of stashing last one Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « views/controls/native/native_view_host_gtk.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "views/controls/native/native_view_host_gtk.h" 5 #include "views/controls/native/native_view_host_gtk.h"
6 6
7 #include <gtk/gtk.h> 7 #include <gtk/gtk.h>
8 #include <algorithm> 8 #include <algorithm>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 void UnblockFocusSignals(GtkWidget* widget, gpointer data) { 78 void UnblockFocusSignals(GtkWidget* widget, gpointer data) {
79 if (!widget) 79 if (!widget)
80 return; 80 return;
81 InitSignalIds(); 81 InitSignalIds();
82 UnblockSignal(widget, focus_in_event_signal_id_); 82 UnblockSignal(widget, focus_in_event_signal_id_);
83 UnblockSignal(widget, focus_out_event_signal_id_); 83 UnblockSignal(widget, focus_out_event_signal_id_);
84 if (GTK_IS_CONTAINER(widget)) 84 if (GTK_IS_CONTAINER(widget))
85 gtk_container_foreach(GTK_CONTAINER(widget), UnblockFocusSignals, data); 85 gtk_container_foreach(GTK_CONTAINER(widget), UnblockFocusSignals, data);
86 } 86 }
87 87
88 // Removes |child| from |parent|.
89 void RemoveFromParent(GtkWidget* child, gpointer parent) {
90 gtk_container_remove(GTK_CONTAINER(parent), child);
91 }
92
88 } // namespace 93 } // namespace
89 94
90 //////////////////////////////////////////////////////////////////////////////// 95 ////////////////////////////////////////////////////////////////////////////////
91 // NativeViewHostGtk, public: 96 // NativeViewHostGtk, public:
92 97
93 NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host) 98 NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host)
94 : host_(host), 99 : host_(host),
95 installed_clip_(false), 100 installed_clip_(false),
96 destroy_signal_id_(0), 101 destroy_signal_id_(0),
97 focus_signal_id_(0), 102 focus_signal_id_(0),
98 fixed_(NULL) { 103 fixed_(NULL) {
99 CreateFixed(false); 104 CreateFixed(false);
100 } 105 }
101 106
102 NativeViewHostGtk::~NativeViewHostGtk() { 107 NativeViewHostGtk::~NativeViewHostGtk() {
103 if (fixed_) 108 if (fixed_) {
109 gtk_container_foreach(GTK_CONTAINER(fixed_), RemoveFromParent, fixed_);
104 gtk_widget_destroy(fixed_); 110 gtk_widget_destroy(fixed_);
111 }
105 } 112 }
106 113
107 //////////////////////////////////////////////////////////////////////////////// 114 ////////////////////////////////////////////////////////////////////////////////
108 // NativeViewHostGtk, NativeViewHostWrapper implementation: 115 // NativeViewHostGtk, NativeViewHostWrapper implementation:
109 116
110 void NativeViewHostGtk::NativeViewAttached() { 117 void NativeViewHostGtk::NativeViewAttached() {
111 DCHECK(host_->native_view()); 118 AttachHostWidget();
112 if (gtk_widget_get_parent(host_->native_view())) 119
113 gtk_widget_reparent(host_->native_view(), fixed_); 120 GtkWidget* host_widget = host_->native_view();
114 else
115 gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());
116 121
117 // Let the widget know that the native component has been painted. 122 // Let the widget know that the native component has been painted.
118 views::NativeWidgetGtk::RegisterChildExposeHandler(host_->native_view()); 123 views::NativeWidgetGtk::RegisterChildExposeHandler(host_widget);
119 124
120 if (!destroy_signal_id_) { 125 if (!destroy_signal_id_) {
121 destroy_signal_id_ = g_signal_connect(host_->native_view(), 126 destroy_signal_id_ = g_signal_connect(host_widget,
122 "destroy", G_CALLBACK(CallDestroy), 127 "destroy", G_CALLBACK(CallDestroy),
123 this); 128 this);
124 } 129 }
125 130
126 if (!focus_signal_id_) { 131 if (!focus_signal_id_) {
127 focus_signal_id_ = g_signal_connect(host_->native_view(), 132 focus_signal_id_ = g_signal_connect(host_widget,
128 "focus-in-event", 133 "focus-in-event",
129 G_CALLBACK(CallFocusIn), this); 134 G_CALLBACK(CallFocusIn), this);
130 } 135 }
131 136
132 // Always layout though. 137 // Always layout though.
133 host_->Layout(); 138 host_->Layout();
134 139
135 // We own the native view as long as it's attached, so that we can safely
136 // reparent it in multiple passes.
137 gtk_widget_ref(host_->native_view());
138
139 // TODO(port): figure out focus. 140 // TODO(port): figure out focus.
140 } 141 }
141 142
142 void NativeViewHostGtk::NativeViewDetaching(bool destroyed) { 143 void NativeViewHostGtk::NativeViewDetaching(bool destroyed) {
143 DCHECK(host_->native_view()); 144 GtkWidget* host_widget = host_->native_view();
145 DCHECK(host_widget);
144 146
145 g_signal_handler_disconnect(G_OBJECT(host_->native_view()), 147 g_signal_handler_disconnect(G_OBJECT(host_widget), destroy_signal_id_);
146 destroy_signal_id_);
147 destroy_signal_id_ = 0; 148 destroy_signal_id_ = 0;
148 149
149 g_signal_handler_disconnect(G_OBJECT(host_->native_view()), 150 g_signal_handler_disconnect(G_OBJECT(host_widget), focus_signal_id_);
150 focus_signal_id_);
151 focus_signal_id_ = 0; 151 focus_signal_id_ = 0;
152 152
153 installed_clip_ = false; 153 installed_clip_ = false;
154
155 if (fixed_ && !destroyed) {
156 DCHECK_NE(static_cast<gfx::NativeView>(NULL),
157 gtk_widget_get_parent(host_->native_view()));
158 gtk_container_remove(GTK_CONTAINER(fixed_), host_->native_view());
159 DCHECK_EQ(
160 0U, g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_))));
161 }
162
163 g_object_unref(G_OBJECT(host_->native_view()));
164 } 154 }
165 155
166 void NativeViewHostGtk::AddedToWidget() { 156 void NativeViewHostGtk::AddedToWidget() {
167 if (!fixed_) 157 if (!fixed_)
168 CreateFixed(false); 158 CreateFixed(false);
169 if (gtk_widget_get_parent(fixed_)) 159 if (gtk_widget_get_parent(fixed_))
170 GetHostWidget()->ReparentChild(fixed_); 160 GetHostWidget()->ReparentChild(fixed_);
171 else 161 else
172 GetHostWidget()->AddChild(fixed_); 162 GetHostWidget()->AddChild(fixed_);
173 163
174 if (!host_->native_view()) 164 if (!host_->native_view())
175 return; 165 return;
176 166
177 if (gtk_widget_get_parent(host_->native_view())) 167 AttachHostWidget();
178 gtk_widget_reparent(host_->native_view(), fixed_);
179 else
180 gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());
181 168
182 if (host_->IsVisibleInRootView()) 169 if (host_->IsVisibleInRootView()) {
170 gtk_widget_show(host_->native_view());
183 gtk_widget_show(fixed_); 171 gtk_widget_show(fixed_);
184 else 172 } else {
185 gtk_widget_hide(fixed_); 173 gtk_widget_hide(fixed_);
174 }
186 host_->Layout(); 175 host_->Layout();
187 } 176 }
188 177
189 void NativeViewHostGtk::RemovedFromWidget() { 178 void NativeViewHostGtk::RemovedFromWidget() {
190 if (!host_->native_view()) 179 if (!host_->native_view())
191 return; 180 return;
192 DestroyFixed(); 181 DestroyFixed();
193 } 182 }
194 183
195 void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) { 184 void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 int child_h = h; 217 int child_h = h;
229 if (installed_clip_) { 218 if (installed_clip_) {
230 child_x = -installed_clip_bounds_.x(); 219 child_x = -installed_clip_bounds_.x();
231 child_y = -installed_clip_bounds_.y(); 220 child_y = -installed_clip_bounds_.y();
232 fixed_x += -child_x; 221 fixed_x += -child_x;
233 fixed_y += -child_y; 222 fixed_y += -child_y;
234 fixed_w = std::min(installed_clip_bounds_.width(), w); 223 fixed_w = std::min(installed_clip_bounds_.width(), w);
235 fixed_h = std::min(installed_clip_bounds_.height(), h); 224 fixed_h = std::min(installed_clip_bounds_.height(), h);
236 } 225 }
237 226
227 GtkWidget* host_widget = host_->native_view();
238 // Don't call gtk_widget_size_allocate now, as we're possibly in the 228 // Don't call gtk_widget_size_allocate now, as we're possibly in the
239 // middle of a re-size, and it kicks off another re-size, and you 229 // middle of a re-size, and it kicks off another re-size, and you
240 // get flashing. Instead, we'll set the desired size as properties 230 // get flashing. Instead, we'll set the desired size as properties
241 // on the widget and queue the re-size. 231 // on the widget and queue the re-size.
242 gtk_views_fixed_set_widget_size(host_->native_view(), child_w, child_h); 232 gtk_views_fixed_set_widget_size(host_widget, child_w, child_h);
243 gtk_fixed_move(GTK_FIXED(fixed_), host_->native_view(), child_x, child_y); 233 gtk_fixed_move(GTK_FIXED(fixed_), host_widget, child_x, child_y);
244 234
245 // Size and place the fixed_. 235 // Size and place the fixed_.
246 GetHostWidget()->PositionChild(fixed_, fixed_x, fixed_y, fixed_w, fixed_h); 236 GetHostWidget()->PositionChild(fixed_, fixed_x, fixed_y, fixed_w, fixed_h);
247 237
238 gtk_widget_show(host_widget);
248 gtk_widget_show(fixed_); 239 gtk_widget_show(fixed_);
249 gtk_widget_show(host_->native_view());
250 } 240 }
251 241
252 void NativeViewHostGtk::HideWidget() { 242 void NativeViewHostGtk::HideWidget() {
253 if (fixed_) 243 if (fixed_)
254 gtk_widget_hide(fixed_); 244 gtk_widget_hide(fixed_);
255 } 245 }
256 246
257 void NativeViewHostGtk::SetFocus() { 247 void NativeViewHostGtk::SetFocus() {
258 DCHECK(host_->native_view()); 248 GtkWidget* host_widget = host_->native_view();
259 gtk_widget_grab_focus(host_->native_view()); 249 DCHECK(host_widget);
250 gtk_widget_grab_focus(host_widget);
260 } 251 }
261 252
262 gfx::NativeViewAccessible NativeViewHostGtk::GetNativeViewAccessible() { 253 gfx::NativeViewAccessible NativeViewHostGtk::GetNativeViewAccessible() {
263 return NULL; 254 return NULL;
264 } 255 }
265 256
266 //////////////////////////////////////////////////////////////////////////////// 257 ////////////////////////////////////////////////////////////////////////////////
267 // NativeViewHostGtk, private: 258 // NativeViewHostGtk, private:
268 259
269 void NativeViewHostGtk::CreateFixed(bool needs_window) { 260 void NativeViewHostGtk::CreateFixed(bool needs_window) {
(...skipping 13 matching lines...) Expand all
283 // restore focus after we create the new fixed_. This way focus hasn't 274 // restore focus after we create the new fixed_. This way focus hasn't
284 // really moved. 275 // really moved.
285 gtk_widget_grab_focus(GetHostWidget()->GetNativeView()); 276 gtk_widget_grab_focus(GetHostWidget()->GetNativeView());
286 } 277 }
287 278
288 DestroyFixed(); 279 DestroyFixed();
289 280
290 fixed_ = gtk_views_fixed_new(); 281 fixed_ = gtk_views_fixed_new();
291 gtk_widget_set_name(fixed_, "views-native-view-host-fixed"); 282 gtk_widget_set_name(fixed_, "views-native-view-host-fixed");
292 gtk_fixed_set_has_window(GTK_FIXED(fixed_), needs_window); 283 gtk_fixed_set_has_window(GTK_FIXED(fixed_), needs_window);
284
293 // Defeat refcounting. We need to own the fixed. 285 // Defeat refcounting. We need to own the fixed.
294 gtk_widget_ref(fixed_); 286 gtk_widget_ref(fixed_);
295 287
296 NativeWidgetGtk* widget_gtk = GetHostWidget(); 288 NativeWidgetGtk* widget_gtk = GetHostWidget();
297 if (widget_gtk) 289 if (widget_gtk) {
298 widget_gtk->AddChild(fixed_); 290 widget_gtk->AddChild(fixed_);
291 // Clear the background so we don't get flicker.
292 gtk_widget_realize(fixed_);
293 gdk_window_set_back_pixmap(fixed_->window, NULL, false);
294 }
299 295
300 if (host_->native_view()) 296 if (host_->native_view())
301 gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view()); 297 AttachHostWidget();
302 298
303 if (widget_gtk && host_->native_view() && focused_widget) { 299 if (widget_gtk && host_->native_view() && focused_widget)
304 gtk_widget_grab_focus(focused_widget); 300 gtk_widget_grab_focus(focused_widget);
305 } 301
306 if (focus_event_blocked) { 302 if (focus_event_blocked) {
307 // Unblocking a signal handler that is not blocked fails. 303 // Unblocking a signal handler that is not blocked fails.
308 // Unblock only when it's unblocked. 304 // Unblock only when it's unblocked.
309 UnblockFocusSignals(GetHostWidget()->GetNativeView(), NULL); 305 UnblockFocusSignals(GetHostWidget()->GetNativeView(), NULL);
310 } 306 }
311 } 307 }
312 308
313 void NativeViewHostGtk::DestroyFixed() { 309 void NativeViewHostGtk::DestroyFixed() {
314 if (!fixed_) 310 if (!fixed_)
315 return; 311 return;
316 312
317 gtk_widget_hide(fixed_); 313 gtk_widget_hide(fixed_);
314 gtk_container_foreach(GTK_CONTAINER(fixed_), RemoveFromParent, fixed_);
318 GetHostWidget()->RemoveChild(fixed_); 315 GetHostWidget()->RemoveChild(fixed_);
319 316
320 if (host_->native_view()) {
321 // We can safely remove the widget from its container since we own the
322 // widget from the moment it is attached.
323 gtk_container_remove(GTK_CONTAINER(fixed_), host_->native_view());
324 }
325 // fixed_ should not have any children this point. 317 // fixed_ should not have any children this point.
326 DCHECK_EQ(0U, 318 DCHECK_EQ(0U,
327 g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_)))); 319 g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_))));
328 gtk_widget_destroy(fixed_); 320 gtk_widget_destroy(fixed_);
329 fixed_ = NULL; 321 fixed_ = NULL;
330 } 322 }
331 323
332 NativeWidgetGtk* NativeViewHostGtk::GetHostWidget() const { 324 NativeWidgetGtk* NativeViewHostGtk::GetHostWidget() const {
333 return static_cast<NativeWidgetGtk*>(host_->GetWidget()->native_widget()); 325 return static_cast<NativeWidgetGtk*>(host_->GetWidget()->native_widget());
334 } 326 }
335 327
336 GtkWidget* NativeViewHostGtk::GetFocusedDescendant() { 328 GtkWidget* NativeViewHostGtk::GetFocusedDescendant() {
337 if (!fixed_) 329 if (!fixed_)
338 return NULL; 330 return NULL;
339 NativeWidgetGtk* host = GetHostWidget(); 331 NativeWidgetGtk* host = GetHostWidget();
340 if (!host) 332 if (!host)
341 return NULL; 333 return NULL;
342 GtkWidget* top_level = gtk_widget_get_toplevel(host->GetNativeView()); 334 GtkWidget* top_level = gtk_widget_get_toplevel(host->GetNativeView());
343 if (!top_level || !GTK_IS_WINDOW(top_level)) 335 if (!top_level || !GTK_IS_WINDOW(top_level))
344 return NULL; 336 return NULL;
345 GtkWidget* focused = gtk_window_get_focus(GTK_WINDOW(top_level)); 337 GtkWidget* focused = gtk_window_get_focus(GTK_WINDOW(top_level));
346 if (!focused) 338 if (!focused)
347 return NULL; 339 return NULL;
348 return (focused == fixed_ || gtk_widget_is_ancestor(focused, fixed_)) ? 340 return (focused == fixed_ || gtk_widget_is_ancestor(focused, fixed_)) ?
349 focused : NULL; 341 focused : NULL;
350 } 342 }
351 343
344 void NativeViewHostGtk::AttachHostWidget() {
345 GtkWidget* host_widget = host_->native_view();
346 DCHECK(host_widget);
347
348 GtkWidget* host_parent = gtk_widget_get_parent(host_widget);
349 bool parent_changed = true;
350 if (host_parent) {
351 if (host_parent != fixed_)
352 gtk_widget_reparent(host_widget, fixed_);
353 else
354 parent_changed = false;
355 } else {
356 gtk_container_add(GTK_CONTAINER(fixed_), host_widget);
357 }
358
359 if (parent_changed) {
360 // We need to clear the background so we don't get flicker on tab switching.
361 // To do that we must realize the widget if it's not already.
362 if (!GTK_WIDGET_REALIZED(host_widget))
363 gtk_widget_realize(host_widget);
364 gdk_window_set_back_pixmap(host_widget->window, NULL, false);
365 }
366 }
367
352 // static 368 // static
353 void NativeViewHostGtk::CallDestroy(GtkObject* object, 369 void NativeViewHostGtk::CallDestroy(GtkObject* object,
354 NativeViewHostGtk* host) { 370 NativeViewHostGtk* host) {
355 host->host_->NativeViewDestroyed(); 371 host->host_->NativeViewDestroyed();
356 } 372 }
357 373
358 // static 374 // static
359 gboolean NativeViewHostGtk::CallFocusIn(GtkWidget* widget, 375 gboolean NativeViewHostGtk::CallFocusIn(GtkWidget* widget,
360 GdkEventFocus* event, 376 GdkEventFocus* event,
361 NativeViewHostGtk* host) { 377 NativeViewHostGtk* host) {
(...skipping 16 matching lines...) Expand all
378 // static 394 // static
379 NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper( 395 NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
380 NativeViewHost* host) { 396 NativeViewHost* host) {
381 if (Widget::IsPureViews() && 397 if (Widget::IsPureViews() &&
382 views::ViewsDelegate::views_delegate->GetDefaultParentView()) 398 views::ViewsDelegate::views_delegate->GetDefaultParentView())
383 return new NativeViewHostViews(host); 399 return new NativeViewHostViews(host);
384 return new NativeViewHostGtk(host); 400 return new NativeViewHostGtk(host);
385 } 401 }
386 402
387 } // namespace views 403 } // namespace views
OLDNEW
« no previous file with comments | « views/controls/native/native_view_host_gtk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698