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

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: Null out host_widget_ after removing it 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
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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 } // namespace 88 } // namespace
89 89
90 //////////////////////////////////////////////////////////////////////////////// 90 ////////////////////////////////////////////////////////////////////////////////
91 // NativeViewHostGtk, public: 91 // NativeViewHostGtk, public:
92 92
93 NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host) 93 NativeViewHostGtk::NativeViewHostGtk(NativeViewHost* host)
94 : host_(host), 94 : host_(host),
95 installed_clip_(false), 95 installed_clip_(false),
96 destroy_signal_id_(0), 96 destroy_signal_id_(0),
97 focus_signal_id_(0), 97 focus_signal_id_(0),
98 fixed_(NULL) { 98 fixed_(NULL),
99 host_widget_(NULL) {
99 CreateFixed(false); 100 CreateFixed(false);
100 } 101 }
101 102
102 NativeViewHostGtk::~NativeViewHostGtk() { 103 NativeViewHostGtk::~NativeViewHostGtk() {
103 if (fixed_) 104 if (fixed_) {
105 if (host_widget_ &&
106 GTK_IS_WIDGET(host_widget_) &&
107 gtk_widget_get_parent(host_widget_) == fixed_)
108 gtk_container_remove(GTK_CONTAINER(fixed_), host_widget_);
sky 2011/07/01 20:00:38 Does this mean the host_widget_ is leaked if someo
DaveMoore 2011/07/01 20:13:34 If we don't remove it here it will get destroyed w
104 gtk_widget_destroy(fixed_); 109 gtk_widget_destroy(fixed_);
110 }
105 } 111 }
106 112
107 //////////////////////////////////////////////////////////////////////////////// 113 ////////////////////////////////////////////////////////////////////////////////
108 // NativeViewHostGtk, NativeViewHostWrapper implementation: 114 // NativeViewHostGtk, NativeViewHostWrapper implementation:
109 115
110 void NativeViewHostGtk::NativeViewAttached() { 116 void NativeViewHostGtk::NativeViewAttached() {
111 DCHECK(host_->native_view()); 117 host_widget_ = host_->native_view();
112 if (gtk_widget_get_parent(host_->native_view())) 118 DCHECK(host_widget_);
113 gtk_widget_reparent(host_->native_view(), fixed_); 119
114 else 120 GtkWidget* host_parent = gtk_widget_get_parent(host_widget_);
115 gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view()); 121 if (host_parent) {
122 if (host_parent != fixed_)
123 gtk_widget_reparent(host_widget_, fixed_);
124 } else {
125 gtk_container_add(GTK_CONTAINER(fixed_), host_widget_);
126 }
127
128 // We need to clear the background so we don't get flicker on tab switching.
129 // To do that we must realize the widget if it's not already.
130 if (!GTK_WIDGET_REALIZED(host_widget_))
131 gtk_widget_realize(host_widget_);
132 gdk_window_set_back_pixmap(host_widget_->window, NULL, false);
116 133
117 // Let the widget know that the native component has been painted. 134 // Let the widget know that the native component has been painted.
118 views::NativeWidgetGtk::RegisterChildExposeHandler(host_->native_view()); 135 views::NativeWidgetGtk::RegisterChildExposeHandler(host_widget_);
119 136
120 if (!destroy_signal_id_) { 137 if (!destroy_signal_id_) {
121 destroy_signal_id_ = g_signal_connect(host_->native_view(), 138 destroy_signal_id_ = g_signal_connect(host_widget_,
122 "destroy", G_CALLBACK(CallDestroy), 139 "destroy", G_CALLBACK(CallDestroy),
123 this); 140 this);
124 } 141 }
125 142
126 if (!focus_signal_id_) { 143 if (!focus_signal_id_) {
127 focus_signal_id_ = g_signal_connect(host_->native_view(), 144 focus_signal_id_ = g_signal_connect(host_widget_,
128 "focus-in-event", 145 "focus-in-event",
129 G_CALLBACK(CallFocusIn), this); 146 G_CALLBACK(CallFocusIn), this);
130 } 147 }
131 148
132 // Always layout though. 149 // Always layout though.
133 host_->Layout(); 150 host_->Layout();
134 151
135 // We own the native view as long as it's attached, so that we can safely 152 // We own the native view as long as it's attached, so that we can safely
136 // reparent it in multiple passes. 153 // reparent it in multiple passes.
137 gtk_widget_ref(host_->native_view()); 154 gtk_widget_ref(host_widget_);
138 155
139 // TODO(port): figure out focus. 156 // TODO(port): figure out focus.
140 } 157 }
141 158
142 void NativeViewHostGtk::NativeViewDetaching(bool destroyed) { 159 void NativeViewHostGtk::NativeViewDetaching(bool destroyed) {
143 DCHECK(host_->native_view()); 160 DCHECK(host_widget_);
144 161
145 g_signal_handler_disconnect(G_OBJECT(host_->native_view()), 162 g_signal_handler_disconnect(G_OBJECT(host_widget_), destroy_signal_id_);
146 destroy_signal_id_);
147 destroy_signal_id_ = 0; 163 destroy_signal_id_ = 0;
148 164
149 g_signal_handler_disconnect(G_OBJECT(host_->native_view()), 165 g_signal_handler_disconnect(G_OBJECT(host_widget_), focus_signal_id_);
150 focus_signal_id_);
151 focus_signal_id_ = 0; 166 focus_signal_id_ = 0;
152 167
153 installed_clip_ = false; 168 installed_clip_ = false;
154 169
155 if (fixed_ && !destroyed) { 170 g_object_unref(G_OBJECT(host_widget_));
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 } 171 }
165 172
166 void NativeViewHostGtk::AddedToWidget() { 173 void NativeViewHostGtk::AddedToWidget() {
167 if (!fixed_) 174 if (!fixed_)
168 CreateFixed(false); 175 CreateFixed(false);
169 if (gtk_widget_get_parent(fixed_)) 176 if (gtk_widget_get_parent(fixed_))
170 GetHostWidget()->ReparentChild(fixed_); 177 GetHostWidget()->ReparentChild(fixed_);
171 else 178 else
172 GetHostWidget()->AddChild(fixed_); 179 GetHostWidget()->AddChild(fixed_);
173 180
174 if (!host_->native_view()) 181 if (!host_->native_view())
175 return; 182 return;
176 183
177 if (gtk_widget_get_parent(host_->native_view())) 184 host_widget_ = host_->native_view();
178 gtk_widget_reparent(host_->native_view(), fixed_); 185 if (gtk_widget_get_parent(host_widget_))
186 gtk_widget_reparent(host_widget_, fixed_);
179 else 187 else
180 gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view()); 188 gtk_container_add(GTK_CONTAINER(fixed_), host_widget_);
181 189
182 if (host_->IsVisibleInRootView()) 190 if (host_->IsVisibleInRootView()) {
191 gtk_widget_show(host_widget_);
183 gtk_widget_show(fixed_); 192 gtk_widget_show(fixed_);
184 else 193 } else {
185 gtk_widget_hide(fixed_); 194 gtk_widget_hide(fixed_);
195 }
186 host_->Layout(); 196 host_->Layout();
187 } 197 }
188 198
189 void NativeViewHostGtk::RemovedFromWidget() { 199 void NativeViewHostGtk::RemovedFromWidget() {
190 if (!host_->native_view()) 200 if (!host_->native_view())
191 return; 201 return;
192 DestroyFixed(); 202 DestroyFixed();
193 } 203 }
194 204
195 void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) { 205 void NativeViewHostGtk::InstallClip(int x, int y, int w, int h) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 fixed_x += -child_x; 242 fixed_x += -child_x;
233 fixed_y += -child_y; 243 fixed_y += -child_y;
234 fixed_w = std::min(installed_clip_bounds_.width(), w); 244 fixed_w = std::min(installed_clip_bounds_.width(), w);
235 fixed_h = std::min(installed_clip_bounds_.height(), h); 245 fixed_h = std::min(installed_clip_bounds_.height(), h);
236 } 246 }
237 247
238 // Don't call gtk_widget_size_allocate now, as we're possibly in the 248 // 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 249 // 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 250 // get flashing. Instead, we'll set the desired size as properties
241 // on the widget and queue the re-size. 251 // on the widget and queue the re-size.
242 gtk_views_fixed_set_widget_size(host_->native_view(), child_w, child_h); 252 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); 253 gtk_fixed_move(GTK_FIXED(fixed_), host_widget_, child_x, child_y);
244 254
245 // Size and place the fixed_. 255 // Size and place the fixed_.
246 GetHostWidget()->PositionChild(fixed_, fixed_x, fixed_y, fixed_w, fixed_h); 256 GetHostWidget()->PositionChild(fixed_, fixed_x, fixed_y, fixed_w, fixed_h);
247 257
258 gtk_widget_show(host_widget_);
248 gtk_widget_show(fixed_); 259 gtk_widget_show(fixed_);
249 gtk_widget_show(host_->native_view());
250 } 260 }
251 261
252 void NativeViewHostGtk::HideWidget() { 262 void NativeViewHostGtk::HideWidget() {
253 if (fixed_) 263 if (fixed_)
254 gtk_widget_hide(fixed_); 264 gtk_widget_hide(fixed_);
255 } 265 }
256 266
257 void NativeViewHostGtk::SetFocus() { 267 void NativeViewHostGtk::SetFocus() {
258 DCHECK(host_->native_view()); 268 DCHECK(host_widget_);
259 gtk_widget_grab_focus(host_->native_view()); 269 gtk_widget_grab_focus(host_widget_);
260 } 270 }
261 271
262 gfx::NativeViewAccessible NativeViewHostGtk::GetNativeViewAccessible() { 272 gfx::NativeViewAccessible NativeViewHostGtk::GetNativeViewAccessible() {
263 return NULL; 273 return NULL;
264 } 274 }
265 275
266 //////////////////////////////////////////////////////////////////////////////// 276 ////////////////////////////////////////////////////////////////////////////////
267 // NativeViewHostGtk, private: 277 // NativeViewHostGtk, private:
268 278
269 void NativeViewHostGtk::CreateFixed(bool needs_window) { 279 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 293 // restore focus after we create the new fixed_. This way focus hasn't
284 // really moved. 294 // really moved.
285 gtk_widget_grab_focus(GetHostWidget()->GetNativeView()); 295 gtk_widget_grab_focus(GetHostWidget()->GetNativeView());
286 } 296 }
287 297
288 DestroyFixed(); 298 DestroyFixed();
289 299
290 fixed_ = gtk_views_fixed_new(); 300 fixed_ = gtk_views_fixed_new();
291 gtk_widget_set_name(fixed_, "views-native-view-host-fixed"); 301 gtk_widget_set_name(fixed_, "views-native-view-host-fixed");
292 gtk_fixed_set_has_window(GTK_FIXED(fixed_), needs_window); 302 gtk_fixed_set_has_window(GTK_FIXED(fixed_), needs_window);
303
293 // Defeat refcounting. We need to own the fixed. 304 // Defeat refcounting. We need to own the fixed.
294 gtk_widget_ref(fixed_); 305 gtk_widget_ref(fixed_);
295 306
296 NativeWidgetGtk* widget_gtk = GetHostWidget(); 307 NativeWidgetGtk* widget_gtk = GetHostWidget();
297 if (widget_gtk) 308 if (widget_gtk) {
298 widget_gtk->AddChild(fixed_); 309 widget_gtk->AddChild(fixed_);
310 // Clear the background so we don't get flicker.
311 gtk_widget_realize(fixed_);
312 gdk_window_set_back_pixmap(fixed_->window, NULL, false);
313 }
299 314
300 if (host_->native_view()) 315 if (host_->native_view()) {
301 gtk_container_add(GTK_CONTAINER(fixed_), host_->native_view()); 316 host_widget_ = host_->native_view();
317 gtk_container_add(GTK_CONTAINER(fixed_), host_widget_);
318 }
302 319
303 if (widget_gtk && host_->native_view() && focused_widget) { 320 if (widget_gtk && host_widget_ && focused_widget)
304 gtk_widget_grab_focus(focused_widget); 321 gtk_widget_grab_focus(focused_widget);
305 } 322
306 if (focus_event_blocked) { 323 if (focus_event_blocked) {
307 // Unblocking a signal handler that is not blocked fails. 324 // Unblocking a signal handler that is not blocked fails.
308 // Unblock only when it's unblocked. 325 // Unblock only when it's unblocked.
309 UnblockFocusSignals(GetHostWidget()->GetNativeView(), NULL); 326 UnblockFocusSignals(GetHostWidget()->GetNativeView(), NULL);
310 } 327 }
311 } 328 }
312 329
313 void NativeViewHostGtk::DestroyFixed() { 330 void NativeViewHostGtk::DestroyFixed() {
314 if (!fixed_) 331 if (!fixed_)
315 return; 332 return;
316 333
317 gtk_widget_hide(fixed_); 334 gtk_widget_hide(fixed_);
335 if (host_widget_) {
336 // We can safely remove the widget from its container since we own the
337 // widget from the moment it is attached.
338 gtk_container_remove(GTK_CONTAINER(fixed_), host_widget_);
339 host_widget_ = NULL;
340 }
318 GetHostWidget()->RemoveChild(fixed_); 341 GetHostWidget()->RemoveChild(fixed_);
319 342
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. 343 // fixed_ should not have any children this point.
326 DCHECK_EQ(0U, 344 DCHECK_EQ(0U,
327 g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_)))); 345 g_list_length(gtk_container_get_children(GTK_CONTAINER(fixed_))));
328 gtk_widget_destroy(fixed_); 346 gtk_widget_destroy(fixed_);
329 fixed_ = NULL; 347 fixed_ = NULL;
330 } 348 }
331 349
332 NativeWidgetGtk* NativeViewHostGtk::GetHostWidget() const { 350 NativeWidgetGtk* NativeViewHostGtk::GetHostWidget() const {
333 return static_cast<NativeWidgetGtk*>(host_->GetWidget()->native_widget()); 351 return static_cast<NativeWidgetGtk*>(host_->GetWidget()->native_widget());
334 } 352 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 // static 396 // static
379 NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper( 397 NativeViewHostWrapper* NativeViewHostWrapper::CreateWrapper(
380 NativeViewHost* host) { 398 NativeViewHost* host) {
381 if (Widget::IsPureViews() && 399 if (Widget::IsPureViews() &&
382 views::ViewsDelegate::views_delegate->GetDefaultParentView()) 400 views::ViewsDelegate::views_delegate->GetDefaultParentView())
383 return new NativeViewHostViews(host); 401 return new NativeViewHostViews(host);
384 return new NativeViewHostGtk(host); 402 return new NativeViewHostGtk(host);
385 } 403 }
386 404
387 } // namespace views 405 } // namespace views
OLDNEW
« views/controls/native/native_view_host_gtk.h ('K') | « 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