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

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

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