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

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

Issue 7312027: Revert 91710 - Fix flicker on tab switch on chromeos. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: 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
93 } // namespace 88 } // namespace
94 89
95 //////////////////////////////////////////////////////////////////////////////// 90 ////////////////////////////////////////////////////////////////////////////////
96 // NativeViewHostGtk, public: 91 // NativeViewHostGtk, public:
97 92
98 NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host) 93 NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host)
99 : host_(host), 94 : host_(host),
100 installed_clip_(false), 95 installed_clip_(false),
101 destroy_signal_id_(0), 96 destroy_signal_id_(0),
102 focus_signal_id_(0), 97 focus_signal_id_(0),
103 fixed_(NULL) { 98 fixed_(NULL) {
104 CreateFixed(false); 99 CreateFixed(false);
105 } 100 }
106 101
107 NativeViewHostGtk::~NativeViewHostGtk() { 102 NativeViewHostGtk::~NativeViewHostGtk() {
108 if (fixed_) { 103 if (fixed_)
109 gtk_container_foreach(GTK_CONTAINER(fixed_), RemoveFromParent, fixed_);
110 gtk_widget_destroy(fixed_); 104 gtk_widget_destroy(fixed_);
111 }
112 } 105 }
113 106
114 //////////////////////////////////////////////////////////////////////////////// 107 ////////////////////////////////////////////////////////////////////////////////
115 // NativeViewHostGtk, NativeViewHostWrapper implementation: 108 // NativeViewHostGtk, NativeViewHostWrapper implementation:
116 109
117 void NativeViewHostGtk::NativeViewAttached() { 110 void NativeViewHostGtk::NativeViewAttached() {
118 AttachHostWidget(); 111 DCHECK(host_->native_view());
119 112 if (gtk_widget_get_parent(host_->native_view()))
120 GtkWidget* host_widget = host_->native_view(); 113 gtk_widget_reparent(host_->native_view(), fixed_);
114 else
115 gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());
121 116
122 // Let the widget know that the native component has been painted. 117 // Let the widget know that the native component has been painted.
123 views::NativeWidgetGtk::RegisterChildExposeHandler(host_widget); 118 views::NativeWidgetGtk::RegisterChildExposeHandler(host_->native_view());
124 119
125 if (!destroy_signal_id_) { 120 if (!destroy_signal_id_) {
126 destroy_signal_id_ = g_signal_connect(host_widget, 121 destroy_signal_id_ = g_signal_connect(host_->native_view(),
127 "destroy", G_CALLBACK(CallDestroy), 122 "destroy", G_CALLBACK(CallDestroy),
128 this); 123 this);
129 } 124 }
130 125
131 if (!focus_signal_id_) { 126 if (!focus_signal_id_) {
132 focus_signal_id_ = g_signal_connect(host_widget, 127 focus_signal_id_ = g_signal_connect(host_->native_view(),
133 "focus-in-event", 128 "focus-in-event",
134 G_CALLBACK(CallFocusIn), this); 129 G_CALLBACK(CallFocusIn), this);
135 } 130 }
136 131
137 // Always layout though. 132 // Always layout though.
138 host_->Layout(); 133 host_->Layout();
139 134
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
140 // TODO(port): figure out focus. 139 // TODO(port): figure out focus.
141 } 140 }
142 141
143 void NativeViewHostGtk::NativeViewDetaching(bool destroyed) { 142 void NativeViewHostGtk::NativeViewDetaching(bool destroyed) {
144 GtkWidget* host_widget = host_->native_view(); 143 DCHECK(host_->native_view());
145 DCHECK(host_widget);
146 144
147 g_signal_handler_disconnect(G_OBJECT(host_widget), destroy_signal_id_); 145 g_signal_handler_disconnect(G_OBJECT(host_->native_view()),
146 destroy_signal_id_);
148 destroy_signal_id_ = 0; 147 destroy_signal_id_ = 0;
149 148
150 g_signal_handler_disconnect(G_OBJECT(host_widget), focus_signal_id_); 149 g_signal_handler_disconnect(G_OBJECT(host_->native_view()),
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()));
154 } 164 }
155 165
156 void NativeViewHostGtk::AddedToWidget() { 166 void NativeViewHostGtk::AddedToWidget() {
157 if (!fixed_) 167 if (!fixed_)
158 CreateFixed(false); 168 CreateFixed(false);
159 if (gtk_widget_get_parent(fixed_)) 169 if (gtk_widget_get_parent(fixed_))
160 GetHostWidget()->ReparentChild(fixed_); 170 GetHostWidget()->ReparentChild(fixed_);
161 else 171 else
162 GetHostWidget()->AddChild(fixed_); 172 GetHostWidget()->AddChild(fixed_);
163 173
164 if (!host_->native_view()) 174 if (!host_->native_view())
165 return; 175 return;
166 176
167 AttachHostWidget(); 177 if (gtk_widget_get_parent(host_->native_view()))
178 gtk_widget_reparent(host_->native_view(), fixed_);
179 else
180 gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());
168 181
169 if (host_->IsVisibleInRootView()) { 182 if (host_->IsVisibleInRootView())
170 gtk_widget_show(host_->native_view());
171 gtk_widget_show(fixed_); 183 gtk_widget_show(fixed_);
172 } else { 184 else
173 gtk_widget_hide(fixed_); 185 gtk_widget_hide(fixed_);
174 }
175 host_->Layout(); 186 host_->Layout();
176 } 187 }
177 188
178 void NativeViewHostGtk::RemovedFromWidget() { 189 void NativeViewHostGtk::RemovedFromWidget() {
179 if (!host_->native_view()) 190 if (!host_->native_view())
180 return; 191 return;
181 DestroyFixed(); 192 DestroyFixed();
182 } 193 }
183 194
184 void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) { 195 void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 int child_h = h; 228 int child_h = h;
218 if (installed_clip_) { 229 if (installed_clip_) {
219 child_x = -installed_clip_bounds_.x(); 230 child_x = -installed_clip_bounds_.x();
220 child_y = -installed_clip_bounds_.y(); 231 child_y = -installed_clip_bounds_.y();
221 fixed_x += -child_x; 232 fixed_x += -child_x;
222 fixed_y += -child_y; 233 fixed_y += -child_y;
223 fixed_w = std::min(installed_clip_bounds_.width(), w); 234 fixed_w = std::min(installed_clip_bounds_.width(), w);
224 fixed_h = std::min(installed_clip_bounds_.height(), h); 235 fixed_h = std::min(installed_clip_bounds_.height(), h);
225 } 236 }
226 237
227 GtkWidget* host_widget = host_->native_view();
228 // Don't call gtk_widget_size_allocate now, as we're possibly in the 238 // Don't call gtk_widget_size_allocate now, as we're possibly in the
229 // middle of a re-size, and it kicks off another re-size, and you 239 // middle of a re-size, and it kicks off another re-size, and you
230 // get flashing. Instead, we'll set the desired size as properties 240 // get flashing. Instead, we'll set the desired size as properties
231 // on the widget and queue the re-size. 241 // on the widget and queue the re-size.
232 gtk_views_fixed_set_widget_size(host_widget, child_w, child_h); 242 gtk_views_fixed_set_widget_size(host_->native_view(), child_w, child_h);
233 gtk_fixed_move(GTK_FIXED(fixed_), host_widget, child_x, child_y); 243 gtk_fixed_move(GTK_FIXED(fixed_), host_->native_view(), child_x, child_y);
234 244
235 // Size and place the fixed_. 245 // Size and place the fixed_.
236 GetHostWidget()->PositionChild(fixed_, fixed_x, fixed_y, fixed_w, fixed_h); 246 GetHostWidget()->PositionChild(fixed_, fixed_x, fixed_y, fixed_w, fixed_h);
237 247
238 gtk_widget_show(host_widget);
239 gtk_widget_show(fixed_); 248 gtk_widget_show(fixed_);
249 gtk_widget_show(host_->native_view());
240 } 250 }
241 251
242 void NativeViewHostGtk::HideWidget() { 252 void NativeViewHostGtk::HideWidget() {
243 if (fixed_) 253 if (fixed_)
244 gtk_widget_hide(fixed_); 254 gtk_widget_hide(fixed_);
245 } 255 }
246 256
247 void NativeViewHostGtk::SetFocus() { 257 void NativeViewHostGtk::SetFocus() {
248 GtkWidget* host_widget = host_->native_view(); 258 DCHECK(host_->native_view());
249 DCHECK(host_widget); 259 gtk_widget_grab_focus(host_->native_view());
250 gtk_widget_grab_focus(host_widget);
251 } 260 }
252 261
253 gfx::NativeViewAccessible NativeViewHostGtk::GetNativeViewAccessible() { 262 gfx::NativeViewAccessible NativeViewHostGtk::GetNativeViewAccessible() {
254 return NULL; 263 return NULL;
255 } 264 }
256 265
257 //////////////////////////////////////////////////////////////////////////////// 266 ////////////////////////////////////////////////////////////////////////////////
258 // NativeViewHostGtk, private: 267 // NativeViewHostGtk, private:
259 268
260 void NativeViewHostGtk::CreateFixed(bool needs_window) { 269 void NativeViewHostGtk::CreateFixed(bool needs_window) {
(...skipping 13 matching lines...) Expand all
274 // restore focus after we create the new fixed_. This way focus hasn't 283 // restore focus after we create the new fixed_. This way focus hasn't
275 // really moved. 284 // really moved.
276 gtk_widget_grab_focus(GetHostWidget()->GetNativeView()); 285 gtk_widget_grab_focus(GetHostWidget()->GetNativeView());
277 } 286 }
278 287
279 DestroyFixed(); 288 DestroyFixed();
280 289
281 fixed_ = gtk_views_fixed_new(); 290 fixed_ = gtk_views_fixed_new();
282 gtk_widget_set_name(fixed_, "views-native-view-host-fixed"); 291 gtk_widget_set_name(fixed_, "views-native-view-host-fixed");
283 gtk_fixed_set_has_window(GTK_FIXED(fixed_), needs_window); 292 gtk_fixed_set_has_window(GTK_FIXED(fixed_), needs_window);
284
285 // Defeat refcounting. We need to own the fixed. 293 // Defeat refcounting. We need to own the fixed.
286 gtk_widget_ref(fixed_); 294 gtk_widget_ref(fixed_);
287 295
288 NativeWidgetGtk* widget_gtk = GetHostWidget(); 296 NativeWidgetGtk* widget_gtk = GetHostWidget();
289 if (widget_gtk) { 297 if (widget_gtk)
290 widget_gtk->AddChild(fixed_); 298 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 }
295 299
296 if (host_->native_view()) 300 if (host_->native_view())
297 AttachHostWidget(); 301 gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view());
298 302
299 if (widget_gtk && host_->native_view() && focused_widget) 303 if (widget_gtk && host_->native_view() && focused_widget) {
300 gtk_widget_grab_focus(focused_widget); 304 gtk_widget_grab_focus(focused_widget);
301 305 }
302 if (focus_event_blocked) { 306 if (focus_event_blocked) {
303 // Unblocking a signal handler that is not blocked fails. 307 // Unblocking a signal handler that is not blocked fails.
304 // Unblock only when it's unblocked. 308 // Unblock only when it's unblocked.
305 UnblockFocusSignals(GetHostWidget()->GetNativeView(), NULL); 309 UnblockFocusSignals(GetHostWidget()->GetNativeView(), NULL);
306 } 310 }
307 } 311 }
308 312
309 void NativeViewHostGtk::DestroyFixed() { 313 void NativeViewHostGtk::DestroyFixed() {
310 if (!fixed_) 314 if (!fixed_)
311 return; 315 return;
312 316
313 gtk_widget_hide(fixed_); 317 gtk_widget_hide(fixed_);
314 gtk_container_foreach(GTK_CONTAINER(fixed_), RemoveFromParent, fixed_);
315 GetHostWidget()->RemoveChild(fixed_); 318 GetHostWidget()->RemoveChild(fixed_);
316 319
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 }
317 // fixed_ should not have any children this point. 325 // fixed_ should not have any children this point.
318 DCHECK_EQ(0U, 326 DCHECK_EQ(0U,
319 g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_)))); 327 g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_))));
320 gtk_widget_destroy(fixed_); 328 gtk_widget_destroy(fixed_);
321 fixed_ = NULL; 329 fixed_ = NULL;
322 } 330 }
323 331
324 NativeWidgetGtk* NativeViewHostGtk::GetHostWidget() const { 332 NativeWidgetGtk* NativeViewHostGtk::GetHostWidget() const {
325 return static_cast<NativeWidgetGtk*>(host_->GetWidget()->native_widget()); 333 return static_cast<NativeWidgetGtk*>(host_->GetWidget()->native_widget());
326 } 334 }
327 335
328 GtkWidget* NativeViewHostGtk::GetFocusedDescendant() { 336 GtkWidget* NativeViewHostGtk::GetFocusedDescendant() {
329 if (!fixed_) 337 if (!fixed_)
330 return NULL; 338 return NULL;
331 NativeWidgetGtk* host = GetHostWidget(); 339 NativeWidgetGtk* host = GetHostWidget();
332 if (!host) 340 if (!host)
333 return NULL; 341 return NULL;
334 GtkWidget* top_level = gtk_widget_get_toplevel(host->GetNativeView()); 342 GtkWidget* top_level = gtk_widget_get_toplevel(host->GetNativeView());
335 if (!top_level || !GTK_IS_WINDOW(top_level)) 343 if (!top_level || !GTK_IS_WINDOW(top_level))
336 return NULL; 344 return NULL;
337 GtkWidget* focused = gtk_window_get_focus(GTK_WINDOW(top_level)); 345 GtkWidget* focused = gtk_window_get_focus(GTK_WINDOW(top_level));
338 if (!focused) 346 if (!focused)
339 return NULL; 347 return NULL;
340 return (focused == fixed_ || gtk_widget_is_ancestor(focused, fixed_)) ? 348 return (focused == fixed_ || gtk_widget_is_ancestor(focused, fixed_)) ?
341 focused : NULL; 349 focused : NULL;
342 } 350 }
343 351
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
368 // static 352 // static
369 void NativeViewHostGtk::CallDestroy(GtkObject* object, 353 void NativeViewHostGtk::CallDestroy(GtkObject* object,
370 NativeViewHostGtk* host) { 354 NativeViewHostGtk* host) {
371 host->host_->NativeViewDestroyed(); 355 host->host_->NativeViewDestroyed();
372 } 356 }
373 357
374 // static 358 // static
375 gboolean NativeViewHostGtk::CallFocusIn(GtkWidget* widget, 359 gboolean NativeViewHostGtk::CallFocusIn(GtkWidget* widget,
376 GdkEventFocus* event, 360 GdkEventFocus* event,
377 NativeViewHostGtk* host) { 361 NativeViewHostGtk* host) {
(...skipping 16 matching lines...) Expand all
394 // static 378 // static
395 NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper( 379 NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
396 NativeViewHost* host) { 380 NativeViewHost* host) {
397 if (Widget::IsPureViews() && 381 if (Widget::IsPureViews() &&
398 views::ViewsDelegate::views_delegate->GetDefaultParentView()) 382 views::ViewsDelegate::views_delegate->GetDefaultParentView())
399 return new NativeViewHostViews(host); 383 return new NativeViewHostViews(host);
400 return new NativeViewHostGtk(host); 384 return new NativeViewHostGtk(host);
401 } 385 }
402 386
403 } // namespace views 387 } // 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