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 <gdk/gdk.h> | |
6 #include <gdk/gdkx.h> | |
5 #include <gtk/gtk.h> | 7 #include <gtk/gtk.h> |
6 #include <map> | 8 #include <map> |
7 #include <set> | 9 #include <set> |
8 #include <vector> | 10 #include <vector> |
9 | 11 |
12 // Xlib defines RootWindow | |
13 #undef RootWindow | |
14 | |
10 #include "base/file_util.h" | 15 #include "base/file_util.h" |
11 #include "base/logging.h" | 16 #include "base/logging.h" |
12 #include "base/message_loop.h" | 17 #include "base/message_loop.h" |
13 #include "base/string_util.h" | 18 #include "base/string_util.h" |
14 #include "base/sys_string_conversions.h" | 19 #include "base/sys_string_conversions.h" |
15 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
16 #include "base/threading/thread_restrictions.h" | 21 #include "base/threading/thread_restrictions.h" |
17 #include "base/utf_string_conversions.h" | 22 #include "base/utf_string_conversions.h" |
18 //#include "chrome/browser/ui/gtk/select_file_dialog_impl.h" | 23 #include "chrome/browser/ui/libgtk2ui/gtk2_signal.h" |
19 #include "chrome/browser/ui/select_file_dialog.h" | 24 #include "chrome/browser/ui/libgtk2ui/select_file_dialog_impl.h" |
20 #include "grit/generated_resources.h" | 25 #include "grit/ui_strings.h" |
21 //#include "ui/base/gtk/gtk_signal.h" | 26 #include "ui/aura/root_window.h" |
27 #include "ui/aura/window_observer.h" | |
28 #include "ui/base/dialogs/select_file_dialog.h" | |
22 #include "ui/base/l10n/l10n_util.h" | 29 #include "ui/base/l10n/l10n_util.h" |
23 | 30 |
31 namespace { | |
32 | |
33 const char* kAuraTransientParent = "aura-transient-parent"; | |
Daniel Erat
2012/07/27 17:21:56
nit: const char kAuraTransientParent[]
| |
34 | |
35 // Set |dialog| as transient for |parent|, which will keep it on top and center | |
36 // it above |parent|. | |
37 void SetGtkTransientForAura(GtkWidget* dialog, aura::Window* parent) { | |
38 gtk_widget_realize(dialog); | |
39 GdkWindow* gdk_window = gtk_widget_get_window(dialog); | |
40 | |
41 // TODO(erg): Check to make sure we're using X11 if wayland or some other | |
42 // display server ever happens. Otherwise, this will crash. | |
43 XSetTransientForHint(GDK_WINDOW_XDISPLAY(gdk_window), | |
44 GDK_WINDOW_XID(gdk_window), | |
45 parent->GetRootWindow()->GetAcceleratedWidget()); | |
46 | |
47 // We also set the |parent| as a property of |dialog|, so that we can unlink | |
48 // the two later. | |
49 g_object_set_data(G_OBJECT(dialog), kAuraTransientParent, parent); | |
50 } | |
51 | |
52 } // namespace | |
53 | |
54 namespace libgtk2ui { | |
55 | |
56 | |
57 // TODO(erg): This needs to be a window listener that listens to the parent | |
Daniel Erat
2012/07/27 17:21:56
nit: should this TODO be moved to OnWindowDestroyi
| |
58 // aura::Windows for close events and then closes the gtk windows on close. | |
59 | |
24 // Implementation of SelectFileDialog that shows a Gtk common dialog for | 60 // Implementation of SelectFileDialog that shows a Gtk common dialog for |
25 // choosing a file or folder. This acts as a modal dialog. | 61 // choosing a file or folder. This acts as a modal dialog. |
26 class SelectFileDialogImplGTK : public SelectFileDialogImpl { | 62 class SelectFileDialogImplGTK : public SelectFileDialogImpl, |
63 public aura::WindowObserver { | |
27 public: | 64 public: |
28 explicit SelectFileDialogImplGTK(Listener* listener, | 65 explicit SelectFileDialogImplGTK(Listener* listener, |
29 ui::SelectFilePolicy* policy); | 66 ui::SelectFilePolicy* policy); |
30 | 67 |
31 protected: | 68 protected: |
32 virtual ~SelectFileDialogImplGTK(); | 69 virtual ~SelectFileDialogImplGTK(); |
33 | 70 |
34 // SelectFileDialog implementation. | 71 // SelectFileDialog implementation. |
35 // |params| is user data we pass back via the Listener interface. | 72 // |params| is user data we pass back via the Listener interface. |
36 virtual void SelectFileImpl(Type type, | 73 virtual void SelectFileImpl(Type type, |
37 const string16& title, | 74 const string16& title, |
38 const FilePath& default_path, | 75 const FilePath& default_path, |
39 const FileTypeInfo* file_types, | 76 const FileTypeInfo* file_types, |
40 int file_type_index, | 77 int file_type_index, |
41 const FilePath::StringType& default_extension, | 78 const FilePath::StringType& default_extension, |
42 gfx::NativeWindow owning_window, | 79 gfx::NativeWindow owning_window, |
43 void* params) OVERRIDE; | 80 void* params) OVERRIDE; |
44 | 81 |
45 private: | 82 private: |
46 virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE; | 83 virtual bool HasMultipleFileTypeChoicesImpl() OVERRIDE; |
47 | 84 |
85 // Overridden from aura::WindowObserver: | |
86 virtual void OnWindowDestroying(aura::Window* window) OVERRIDE; | |
87 | |
48 // Add the filters from |file_types_| to |chooser|. | 88 // Add the filters from |file_types_| to |chooser|. |
49 void AddFilters(GtkFileChooser* chooser); | 89 void AddFilters(GtkFileChooser* chooser); |
50 | 90 |
51 // Notifies the listener that a single file was chosen. | 91 // Notifies the listener that a single file was chosen. |
52 void FileSelected(GtkWidget* dialog, const FilePath& path); | 92 void FileSelected(GtkWidget* dialog, const FilePath& path); |
53 | 93 |
54 // Notifies the listener that multiple files were chosen. | 94 // Notifies the listener that multiple files were chosen. |
55 void MultiFilesSelected(GtkWidget* dialog, | 95 void MultiFilesSelected(GtkWidget* dialog, |
56 const std::vector<FilePath>& files); | 96 const std::vector<FilePath>& files); |
57 | 97 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
146 SelectFileDialogImplGTK::~SelectFileDialogImplGTK() { | 186 SelectFileDialogImplGTK::~SelectFileDialogImplGTK() { |
147 while (dialogs_.begin() != dialogs_.end()) { | 187 while (dialogs_.begin() != dialogs_.end()) { |
148 gtk_widget_destroy(*(dialogs_.begin())); | 188 gtk_widget_destroy(*(dialogs_.begin())); |
149 } | 189 } |
150 } | 190 } |
151 | 191 |
152 bool SelectFileDialogImplGTK::HasMultipleFileTypeChoicesImpl() { | 192 bool SelectFileDialogImplGTK::HasMultipleFileTypeChoicesImpl() { |
153 return file_types_.extensions.size() > 1; | 193 return file_types_.extensions.size() > 1; |
154 } | 194 } |
155 | 195 |
196 void SelectFileDialogImplGTK::OnWindowDestroying(aura::Window* window) { | |
197 std::set<aura::Window*>::iterator iter = parents_.find(window); | |
198 if (iter != parents_.end()) { | |
199 (*iter)->RemoveObserver(this); | |
200 parents_.erase(iter); | |
201 } | |
202 } | |
203 | |
156 // We ignore |default_extension|. | 204 // We ignore |default_extension|. |
157 void SelectFileDialogImplGTK::SelectFileImpl( | 205 void SelectFileDialogImplGTK::SelectFileImpl( |
158 Type type, | 206 Type type, |
159 const string16& title, | 207 const string16& title, |
160 const FilePath& default_path, | 208 const FilePath& default_path, |
161 const FileTypeInfo* file_types, | 209 const FileTypeInfo* file_types, |
162 int file_type_index, | 210 int file_type_index, |
163 const FilePath::StringType& default_extension, | 211 const FilePath::StringType& default_extension, |
164 gfx::NativeWindow owning_window, | 212 gfx::NativeWindow owning_window, |
165 void* params) { | 213 void* params) { |
166 type_ = type; | 214 type_ = type; |
167 // |owning_window| can be null when user right-clicks on a downloadable item | 215 // |owning_window| can be null when user right-clicks on a downloadable item |
168 // and chooses 'Open Link in New Tab' when 'Ask where to save each file | 216 // and chooses 'Open Link in New Tab' when 'Ask where to save each file |
169 // before downloading.' preference is turned on. (http://crbug.com/29213) | 217 // before downloading.' preference is turned on. (http://crbug.com/29213) |
170 if (owning_window) | 218 if (owning_window) { |
219 owning_window->AddObserver(this); | |
171 parents_.insert(owning_window); | 220 parents_.insert(owning_window); |
221 } | |
172 | 222 |
173 std::string title_string = UTF16ToUTF8(title); | 223 std::string title_string = UTF16ToUTF8(title); |
174 | 224 |
175 file_type_index_ = file_type_index; | 225 file_type_index_ = file_type_index; |
176 if (file_types) | 226 if (file_types) |
177 file_types_ = *file_types; | 227 file_types_ = *file_types; |
178 else | 228 else |
179 file_types_.include_all_files = true; | 229 file_types_.include_all_files = true; |
180 | 230 |
181 GtkWidget* dialog = NULL; | 231 GtkWidget* dialog = NULL; |
(...skipping 22 matching lines...) Expand all Loading... | |
204 | 254 |
205 preview_ = gtk_image_new(); | 255 preview_ = gtk_image_new(); |
206 g_signal_connect(dialog, "destroy", | 256 g_signal_connect(dialog, "destroy", |
207 G_CALLBACK(OnFileChooserDestroyThunk), this); | 257 G_CALLBACK(OnFileChooserDestroyThunk), this); |
208 g_signal_connect(dialog, "update-preview", | 258 g_signal_connect(dialog, "update-preview", |
209 G_CALLBACK(OnUpdatePreviewThunk), this); | 259 G_CALLBACK(OnUpdatePreviewThunk), this); |
210 gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_); | 260 gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_); |
211 | 261 |
212 params_map_[dialog] = params; | 262 params_map_[dialog] = params; |
213 | 263 |
214 // Set window-to-parent modality by adding the dialog to the same window | 264 // TODO(erg): Figure out how to fake GTK window-to-parent modality without |
215 // group as the parent. | 265 // having the parent be a real GtkWindow. |
216 gtk_window_group_add_window(gtk_window_get_group(owning_window), | |
217 GTK_WINDOW(dialog)); | |
218 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); | 266 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); |
219 | 267 |
220 gtk_widget_show_all(dialog); | 268 gtk_widget_show_all(dialog); |
221 } | 269 } |
222 | 270 |
223 void SelectFileDialogImplGTK::AddFilters(GtkFileChooser* chooser) { | 271 void SelectFileDialogImplGTK::AddFilters(GtkFileChooser* chooser) { |
224 for (size_t i = 0; i < file_types_.extensions.size(); ++i) { | 272 for (size_t i = 0; i < file_types_.extensions.size(); ++i) { |
225 GtkFileFilter* filter = NULL; | 273 GtkFileFilter* filter = NULL; |
226 std::set<std::string> fallback_labels; | 274 std::set<std::string> fallback_labels; |
227 | 275 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
303 if (listener_) | 351 if (listener_) |
304 listener_->FileSelectionCanceled(params); | 352 listener_->FileSelectionCanceled(params); |
305 gtk_widget_destroy(dialog); | 353 gtk_widget_destroy(dialog); |
306 } | 354 } |
307 | 355 |
308 GtkWidget* SelectFileDialogImplGTK::CreateFileOpenHelper( | 356 GtkWidget* SelectFileDialogImplGTK::CreateFileOpenHelper( |
309 const std::string& title, | 357 const std::string& title, |
310 const FilePath& default_path, | 358 const FilePath& default_path, |
311 gfx::NativeWindow parent) { | 359 gfx::NativeWindow parent) { |
312 GtkWidget* dialog = | 360 GtkWidget* dialog = |
313 gtk_file_chooser_dialog_new(title.c_str(), parent, | 361 gtk_file_chooser_dialog_new(title.c_str(), NULL, |
314 GTK_FILE_CHOOSER_ACTION_OPEN, | 362 GTK_FILE_CHOOSER_ACTION_OPEN, |
315 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | 363 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
316 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, | 364 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, |
317 NULL); | 365 NULL); |
366 SetGtkTransientForAura(dialog, parent); | |
318 AddFilters(GTK_FILE_CHOOSER(dialog)); | 367 AddFilters(GTK_FILE_CHOOSER(dialog)); |
319 | 368 |
320 if (!default_path.empty()) { | 369 if (!default_path.empty()) { |
321 if (CallDirectoryExistsOnUIThread(default_path)) { | 370 if (CallDirectoryExistsOnUIThread(default_path)) { |
322 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 371 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
323 default_path.value().c_str()); | 372 default_path.value().c_str()); |
324 } else { | 373 } else { |
325 // If the file doesn't exist, this will just switch to the correct | 374 // If the file doesn't exist, this will just switch to the correct |
326 // directory. That's good enough. | 375 // directory. That's good enough. |
327 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), | 376 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), |
328 default_path.value().c_str()); | 377 default_path.value().c_str()); |
329 } | 378 } |
330 } else if (!last_opened_path_->empty()) { | 379 } else if (!last_opened_path_->empty()) { |
331 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 380 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
332 last_opened_path_->value().c_str()); | 381 last_opened_path_->value().c_str()); |
333 } | 382 } |
334 return dialog; | 383 return dialog; |
335 } | 384 } |
336 | 385 |
337 GtkWidget* SelectFileDialogImplGTK::CreateSelectFolderDialog( | 386 GtkWidget* SelectFileDialogImplGTK::CreateSelectFolderDialog( |
338 const std::string& title, | 387 const std::string& title, |
339 const FilePath& default_path, | 388 const FilePath& default_path, |
340 gfx::NativeWindow parent) { | 389 gfx::NativeWindow parent) { |
341 std::string title_string = !title.empty() ? title : | 390 std::string title_string = !title.empty() ? title : |
342 l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE); | 391 l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE); |
343 | 392 |
344 GtkWidget* dialog = | 393 GtkWidget* dialog = |
345 gtk_file_chooser_dialog_new(title_string.c_str(), parent, | 394 gtk_file_chooser_dialog_new(title_string.c_str(), NULL, |
346 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, | 395 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, |
347 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | 396 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
348 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, | 397 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, |
349 NULL); | 398 NULL); |
399 SetGtkTransientForAura(dialog, parent); | |
350 | 400 |
351 if (!default_path.empty()) { | 401 if (!default_path.empty()) { |
352 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), | 402 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), |
353 default_path.value().c_str()); | 403 default_path.value().c_str()); |
354 } else if (!last_opened_path_->empty()) { | 404 } else if (!last_opened_path_->empty()) { |
355 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 405 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
356 last_opened_path_->value().c_str()); | 406 last_opened_path_->value().c_str()); |
357 } | 407 } |
358 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); | 408 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); |
359 g_signal_connect(dialog, "response", | 409 g_signal_connect(dialog, "response", |
(...skipping 28 matching lines...) Expand all Loading... | |
388 G_CALLBACK(OnSelectMultiFileDialogResponseThunk), this); | 438 G_CALLBACK(OnSelectMultiFileDialogResponseThunk), this); |
389 return dialog; | 439 return dialog; |
390 } | 440 } |
391 | 441 |
392 GtkWidget* SelectFileDialogImplGTK::CreateSaveAsDialog(const std::string& title, | 442 GtkWidget* SelectFileDialogImplGTK::CreateSaveAsDialog(const std::string& title, |
393 const FilePath& default_path, gfx::NativeWindow parent) { | 443 const FilePath& default_path, gfx::NativeWindow parent) { |
394 std::string title_string = !title.empty() ? title : | 444 std::string title_string = !title.empty() ? title : |
395 l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE); | 445 l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE); |
396 | 446 |
397 GtkWidget* dialog = | 447 GtkWidget* dialog = |
398 gtk_file_chooser_dialog_new(title_string.c_str(), parent, | 448 gtk_file_chooser_dialog_new(title_string.c_str(), NULL, |
399 GTK_FILE_CHOOSER_ACTION_SAVE, | 449 GTK_FILE_CHOOSER_ACTION_SAVE, |
400 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | 450 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
401 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, | 451 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, |
402 NULL); | 452 NULL); |
453 SetGtkTransientForAura(dialog, parent); | |
403 | 454 |
404 AddFilters(GTK_FILE_CHOOSER(dialog)); | 455 AddFilters(GTK_FILE_CHOOSER(dialog)); |
405 if (!default_path.empty()) { | 456 if (!default_path.empty()) { |
406 // Since the file may not already exist, we use | 457 // Since the file may not already exist, we use |
407 // set_current_folder() followed by set_current_name(), as per the | 458 // set_current_folder() followed by set_current_name(), as per the |
408 // recommendation of the GTK docs. | 459 // recommendation of the GTK docs. |
409 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 460 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
410 default_path.DirName().value().c_str()); | 461 default_path.DirName().value().c_str()); |
411 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), | 462 gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), |
412 default_path.BaseName().value().c_str()); | 463 default_path.BaseName().value().c_str()); |
(...skipping 18 matching lines...) Expand all Loading... | |
431 } | 482 } |
432 | 483 |
433 void SelectFileDialogImplGTK::FileDialogDestroyed(GtkWidget* dialog) { | 484 void SelectFileDialogImplGTK::FileDialogDestroyed(GtkWidget* dialog) { |
434 dialogs_.erase(dialog); | 485 dialogs_.erase(dialog); |
435 | 486 |
436 // Parent may be NULL in a few cases: 1) on shutdown when | 487 // Parent may be NULL in a few cases: 1) on shutdown when |
437 // AllBrowsersClosed() trigger this handler after all the browser | 488 // AllBrowsersClosed() trigger this handler after all the browser |
438 // windows got destroyed, or 2) when the parent tab has been opened by | 489 // windows got destroyed, or 2) when the parent tab has been opened by |
439 // 'Open Link in New Tab' context menu on a downloadable item and | 490 // 'Open Link in New Tab' context menu on a downloadable item and |
440 // the tab has no content (see the comment in SelectFile as well). | 491 // the tab has no content (see the comment in SelectFile as well). |
441 GtkWindow* parent = gtk_window_get_transient_for(GTK_WINDOW(dialog)); | 492 aura::Window* parent = reinterpret_cast<aura::Window*>( |
493 g_object_get_data(G_OBJECT(dialog), kAuraTransientParent)); | |
442 if (!parent) | 494 if (!parent) |
443 return; | 495 return; |
444 std::set<GtkWindow*>::iterator iter = parents_.find(parent); | 496 std::set<aura::Window*>::iterator iter = parents_.find(parent); |
445 if (iter != parents_.end()) | 497 if (iter != parents_.end()) { |
498 (*iter)->RemoveObserver(this); | |
446 parents_.erase(iter); | 499 parents_.erase(iter); |
447 else | 500 } else { |
448 NOTREACHED(); | 501 NOTREACHED(); |
502 } | |
449 } | 503 } |
450 | 504 |
451 bool SelectFileDialogImplGTK::IsCancelResponse(gint response_id) { | 505 bool SelectFileDialogImplGTK::IsCancelResponse(gint response_id) { |
452 bool is_cancel = response_id == GTK_RESPONSE_CANCEL || | 506 bool is_cancel = response_id == GTK_RESPONSE_CANCEL || |
453 response_id == GTK_RESPONSE_DELETE_EVENT; | 507 response_id == GTK_RESPONSE_DELETE_EVENT; |
454 if (is_cancel) | 508 if (is_cancel) |
455 return true; | 509 return true; |
456 | 510 |
457 DCHECK(response_id == GTK_RESPONSE_ACCEPT); | 511 DCHECK(response_id == GTK_RESPONSE_ACCEPT); |
458 return false; | 512 return false; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
539 GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, | 593 GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, |
540 kPreviewHeight, NULL); | 594 kPreviewHeight, NULL); |
541 g_free(filename); | 595 g_free(filename); |
542 if (pixbuf) { | 596 if (pixbuf) { |
543 gtk_image_set_from_pixbuf(GTK_IMAGE(preview_), pixbuf); | 597 gtk_image_set_from_pixbuf(GTK_IMAGE(preview_), pixbuf); |
544 g_object_unref(pixbuf); | 598 g_object_unref(pixbuf); |
545 } | 599 } |
546 gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), | 600 gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), |
547 pixbuf ? TRUE : FALSE); | 601 pixbuf ? TRUE : FALSE); |
548 } | 602 } |
603 | |
604 } // namespace libgtk2ui | |
OLD | NEW |