OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "chrome/browser/gtk/browser_actions_toolbar_gtk.h" | 5 #include "chrome/browser/gtk/browser_actions_toolbar_gtk.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "chrome/browser/browser.h" | 9 #include "chrome/browser/browser.h" |
10 #include "chrome/browser/extensions/extension_browser_event_router.h" | 10 #include "chrome/browser/extensions/extension_browser_event_router.h" |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 // The Browser Action API does not allow the default icon path to be | 93 // The Browser Action API does not allow the default icon path to be |
94 // changed at runtime, so we can load this now and cache it. | 94 // changed at runtime, so we can load this now and cache it. |
95 std::string path = extension_->browser_action()->default_icon_path(); | 95 std::string path = extension_->browser_action()->default_icon_path(); |
96 if (!path.empty()) { | 96 if (!path.empty()) { |
97 tracker_.LoadImage(extension_, extension_->GetResource(path), | 97 tracker_.LoadImage(extension_, extension_->GetResource(path), |
98 gfx::Size(Extension::kBrowserActionIconMaxSize, | 98 gfx::Size(Extension::kBrowserActionIconMaxSize, |
99 Extension::kBrowserActionIconMaxSize), | 99 Extension::kBrowserActionIconMaxSize), |
100 ImageLoadingTracker::DONT_CACHE); | 100 ImageLoadingTracker::DONT_CACHE); |
101 } | 101 } |
102 | 102 |
103 g_signal_connect(button_.get(), "button-press-event", | 103 signals_.Connect(button_.get(), "button-press-event", |
104 G_CALLBACK(OnButtonPress), this); | 104 G_CALLBACK(OnButtonPress), this); |
105 g_signal_connect(button_.get(), "clicked", | 105 signals_.Connect(button_.get(), "clicked", |
106 G_CALLBACK(OnClicked), this); | 106 G_CALLBACK(OnClicked), this); |
107 g_signal_connect_after(button_.get(), "expose-event", | 107 signals_.ConnectAfter(button_.get(), "expose-event", |
108 G_CALLBACK(OnExposeEvent), this); | 108 G_CALLBACK(OnExposeEvent), this); |
109 g_signal_connect(button_.get(), "drag-begin", | 109 signals_.Connect(button_.get(), "drag-begin", |
110 G_CALLBACK(&OnDragBegin), this); | 110 G_CALLBACK(&OnDragBegin), this); |
111 | 111 |
112 registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, | 112 registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, |
113 Source<ExtensionAction>(extension->browser_action())); | 113 Source<ExtensionAction>(extension->browser_action())); |
114 } | 114 } |
115 | 115 |
116 ~BrowserActionButton() { | 116 ~BrowserActionButton() { |
117 if (tab_specific_icon_) | 117 if (tab_specific_icon_) |
118 g_object_unref(tab_specific_icon_); | 118 g_object_unref(tab_specific_icon_); |
119 | 119 |
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 | 311 |
312 // If we are displaying a tab-specific icon, it will be here. | 312 // If we are displaying a tab-specific icon, it will be here. |
313 GdkPixbuf* tab_specific_icon_; | 313 GdkPixbuf* tab_specific_icon_; |
314 | 314 |
315 // If the browser action has a default icon, it will be here. | 315 // If the browser action has a default icon, it will be here. |
316 GdkPixbuf* default_icon_; | 316 GdkPixbuf* default_icon_; |
317 | 317 |
318 // Same as |default_icon_|, but stored as SkBitmap. | 318 // Same as |default_icon_|, but stored as SkBitmap. |
319 SkBitmap default_skbitmap_; | 319 SkBitmap default_skbitmap_; |
320 | 320 |
| 321 GtkSignalRegistrar signals_; |
321 NotificationRegistrar registrar_; | 322 NotificationRegistrar registrar_; |
322 | 323 |
323 // The context menu view and model for this extension action. | 324 // The context menu view and model for this extension action. |
324 scoped_ptr<MenuGtk> context_menu_; | 325 scoped_ptr<MenuGtk> context_menu_; |
325 scoped_refptr<ExtensionContextMenuModel> context_menu_model_; | 326 scoped_refptr<ExtensionContextMenuModel> context_menu_model_; |
326 | 327 |
327 friend class BrowserActionsToolbarGtk; | 328 friend class BrowserActionsToolbarGtk; |
328 }; | 329 }; |
329 | 330 |
330 // BrowserActionsToolbarGtk ---------------------------------------------------- | 331 // BrowserActionsToolbarGtk ---------------------------------------------------- |
(...skipping 14 matching lines...) Expand all Loading... |
345 start_width_(0), | 346 start_width_(0), |
346 method_factory_(this) { | 347 method_factory_(this) { |
347 ExtensionsService* extension_service = profile_->GetExtensionsService(); | 348 ExtensionsService* extension_service = profile_->GetExtensionsService(); |
348 // The |extension_service| can be NULL in Incognito. | 349 // The |extension_service| can be NULL in Incognito. |
349 if (!extension_service) | 350 if (!extension_service) |
350 return; | 351 return; |
351 | 352 |
352 GtkWidget* gripper = gtk_button_new(); | 353 GtkWidget* gripper = gtk_button_new(); |
353 GTK_WIDGET_UNSET_FLAGS(gripper, GTK_CAN_FOCUS); | 354 GTK_WIDGET_UNSET_FLAGS(gripper, GTK_CAN_FOCUS); |
354 gtk_widget_add_events(gripper, GDK_POINTER_MOTION_MASK); | 355 gtk_widget_add_events(gripper, GDK_POINTER_MOTION_MASK); |
355 g_signal_connect(gripper, "motion-notify-event", | 356 signals_.Connect(gripper, "motion-notify-event", |
356 G_CALLBACK(OnGripperMotionNotifyThunk), this); | 357 G_CALLBACK(OnGripperMotionNotifyThunk), this); |
357 g_signal_connect(gripper, "expose-event", | 358 signals_.Connect(gripper, "expose-event", |
358 G_CALLBACK(OnGripperExposeThunk), this); | 359 G_CALLBACK(OnGripperExposeThunk), this); |
359 g_signal_connect(gripper, "enter-notify-event", | 360 signals_.Connect(gripper, "enter-notify-event", |
360 G_CALLBACK(OnGripperEnterNotifyThunk), this); | 361 G_CALLBACK(OnGripperEnterNotifyThunk), this); |
361 g_signal_connect(gripper, "leave-notify-event", | 362 signals_.Connect(gripper, "leave-notify-event", |
362 G_CALLBACK(OnGripperLeaveNotifyThunk), this); | 363 G_CALLBACK(OnGripperLeaveNotifyThunk), this); |
363 g_signal_connect(gripper, "button-release-event", | 364 signals_.Connect(gripper, "button-release-event", |
364 G_CALLBACK(OnGripperButtonReleaseThunk), this); | 365 G_CALLBACK(OnGripperButtonReleaseThunk), this); |
365 g_signal_connect(gripper, "button-press-event", | 366 signals_.Connect(gripper, "button-press-event", |
366 G_CALLBACK(OnGripperButtonPressThunk), this); | 367 G_CALLBACK(OnGripperButtonPressThunk), this); |
367 g_signal_connect(overflow_button_.widget(), "button-press-event", | 368 signals_.Connect(overflow_button_.widget(), "button-press-event", |
368 G_CALLBACK(OnOverflowButtonPressThunk), this); | 369 G_CALLBACK(OnOverflowButtonPressThunk), this); |
369 | 370 |
370 gtk_box_pack_start(GTK_BOX(hbox_.get()), gripper, FALSE, FALSE, 0); | 371 gtk_box_pack_start(GTK_BOX(hbox_.get()), gripper, FALSE, FALSE, 0); |
371 gtk_box_pack_start(GTK_BOX(hbox_.get()), button_hbox_.get(), TRUE, TRUE, 0); | 372 gtk_box_pack_start(GTK_BOX(hbox_.get()), button_hbox_.get(), TRUE, TRUE, 0); |
372 gtk_box_pack_start(GTK_BOX(hbox_.get()), overflow_button_.widget(), | 373 gtk_box_pack_start(GTK_BOX(hbox_.get()), overflow_button_.widget(), |
373 FALSE, FALSE, 0); | 374 FALSE, FALSE, 0); |
374 gtk_box_pack_start(GTK_BOX(hbox_.get()), separator_, FALSE, FALSE, 0); | 375 gtk_box_pack_start(GTK_BOX(hbox_.get()), separator_, FALSE, FALSE, 0); |
375 | 376 |
376 model_ = extension_service->toolbar_model(); | 377 model_ = extension_service->toolbar_model(); |
377 model_->AddObserver(this); | 378 model_->AddObserver(this); |
378 SetupDrags(); | 379 SetupDrags(); |
379 | 380 |
380 if (model_->extensions_initialized()) { | 381 if (model_->extensions_initialized()) { |
381 CreateAllButtons(); | 382 CreateAllButtons(); |
382 SetContainerWidth(); | 383 SetContainerWidth(); |
383 } | 384 } |
384 | 385 |
385 // We want to connect to "set-focus" on the toplevel window; we have to wait | 386 // We want to connect to "set-focus" on the toplevel window; we have to wait |
386 // until we are added to a toplevel window to do so. | 387 // until we are added to a toplevel window to do so. |
387 g_signal_connect(widget(), "hierarchy-changed", | 388 signals_.Connect(widget(), "hierarchy-changed", |
388 G_CALLBACK(OnHierarchyChangedThunk), this); | 389 G_CALLBACK(OnHierarchyChangedThunk), this); |
389 | 390 |
390 ViewIDUtil::SetID(button_hbox_.get(), VIEW_ID_BROWSER_ACTION_TOOLBAR); | 391 ViewIDUtil::SetID(button_hbox_.get(), VIEW_ID_BROWSER_ACTION_TOOLBAR); |
391 } | 392 } |
392 | 393 |
393 BrowserActionsToolbarGtk::~BrowserActionsToolbarGtk() { | 394 BrowserActionsToolbarGtk::~BrowserActionsToolbarGtk() { |
394 GtkWidget* toplevel = gtk_widget_get_toplevel(widget()); | |
395 if (toplevel) { | |
396 g_signal_handlers_disconnect_by_func( | |
397 toplevel, reinterpret_cast<gpointer>(OnSetFocusThunk), this); | |
398 } | |
399 | |
400 if (model_) | 395 if (model_) |
401 model_->RemoveObserver(this); | 396 model_->RemoveObserver(this); |
402 button_hbox_.Destroy(); | 397 button_hbox_.Destroy(); |
403 hbox_.Destroy(); | 398 hbox_.Destroy(); |
404 } | 399 } |
405 | 400 |
406 int BrowserActionsToolbarGtk::GetCurrentTabId() { | 401 int BrowserActionsToolbarGtk::GetCurrentTabId() { |
407 TabContents* selected_tab = browser_->GetSelectedTabContents(); | 402 TabContents* selected_tab = browser_->GetSelectedTabContents(); |
408 if (!selected_tab) | 403 if (!selected_tab) |
409 return -1; | 404 return -1; |
410 | 405 |
411 return selected_tab->controller().session_id().id(); | 406 return selected_tab->controller().session_id().id(); |
412 } | 407 } |
413 | 408 |
414 void BrowserActionsToolbarGtk::Update() { | 409 void BrowserActionsToolbarGtk::Update() { |
415 for (ExtensionButtonMap::iterator iter = extension_button_map_.begin(); | 410 for (ExtensionButtonMap::iterator iter = extension_button_map_.begin(); |
416 iter != extension_button_map_.end(); ++iter) { | 411 iter != extension_button_map_.end(); ++iter) { |
417 iter->second->UpdateState(); | 412 iter->second->UpdateState(); |
418 } | 413 } |
419 } | 414 } |
420 | 415 |
421 void BrowserActionsToolbarGtk::SetupDrags() { | 416 void BrowserActionsToolbarGtk::SetupDrags() { |
422 GtkTargetEntry drag_target = GetDragTargetEntry(); | 417 GtkTargetEntry drag_target = GetDragTargetEntry(); |
423 gtk_drag_dest_set(button_hbox_.get(), GTK_DEST_DEFAULT_DROP, &drag_target, 1, | 418 gtk_drag_dest_set(button_hbox_.get(), GTK_DEST_DEFAULT_DROP, &drag_target, 1, |
424 GDK_ACTION_MOVE); | 419 GDK_ACTION_MOVE); |
425 | 420 |
426 g_signal_connect(button_hbox_.get(), "drag-motion", | 421 signals_.Connect(button_hbox_.get(), "drag-motion", |
427 G_CALLBACK(OnDragMotionThunk), this); | 422 G_CALLBACK(OnDragMotionThunk), this); |
428 } | 423 } |
429 | 424 |
430 void BrowserActionsToolbarGtk::CreateAllButtons() { | 425 void BrowserActionsToolbarGtk::CreateAllButtons() { |
431 extension_button_map_.clear(); | 426 extension_button_map_.clear(); |
432 | 427 |
433 int i = 0; | 428 int i = 0; |
434 for (ExtensionList::iterator iter = model_->begin(); | 429 for (ExtensionList::iterator iter = model_->begin(); |
435 iter != model_->end(); ++iter) { | 430 iter != model_->end(); ++iter) { |
436 CreateButtonForExtension(*iter, i++); | 431 CreateButtonForExtension(*iter, i++); |
(...skipping 19 matching lines...) Expand all Loading... |
456 new BrowserActionButton(this, extension)); | 451 new BrowserActionButton(this, extension)); |
457 gtk_chrome_shrinkable_hbox_pack_start( | 452 gtk_chrome_shrinkable_hbox_pack_start( |
458 GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()), button->widget(), 0); | 453 GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()), button->widget(), 0); |
459 gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button->widget(), index); | 454 gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button->widget(), index); |
460 extension_button_map_[extension->id()] = button; | 455 extension_button_map_[extension->id()] = button; |
461 | 456 |
462 GtkTargetEntry drag_target = GetDragTargetEntry(); | 457 GtkTargetEntry drag_target = GetDragTargetEntry(); |
463 gtk_drag_source_set(button->widget(), GDK_BUTTON1_MASK, &drag_target, 1, | 458 gtk_drag_source_set(button->widget(), GDK_BUTTON1_MASK, &drag_target, 1, |
464 GDK_ACTION_MOVE); | 459 GDK_ACTION_MOVE); |
465 // We ignore whether the drag was a "success" or "failure" in Gtk's opinion. | 460 // We ignore whether the drag was a "success" or "failure" in Gtk's opinion. |
466 g_signal_connect(button->widget(), "drag-end", | 461 signals_.Connect(button->widget(), "drag-end", |
467 G_CALLBACK(&OnDragEndThunk), this); | 462 G_CALLBACK(&OnDragEndThunk), this); |
468 g_signal_connect(button->widget(), "drag-failed", | 463 signals_.Connect(button->widget(), "drag-failed", |
469 G_CALLBACK(&OnDragFailedThunk), this); | 464 G_CALLBACK(&OnDragFailedThunk), this); |
470 | 465 |
471 // Any time a browser action button is shown or hidden we have to update | 466 // Any time a browser action button is shown or hidden we have to update |
472 // the chevron state. | 467 // the chevron state. |
473 g_signal_connect(button->widget(), "show", | 468 signals_.Connect(button->widget(), "show", |
474 G_CALLBACK(&OnButtonShowOrHideThunk), this); | 469 G_CALLBACK(&OnButtonShowOrHideThunk), this); |
475 g_signal_connect(button->widget(), "hide", | 470 signals_.Connect(button->widget(), "hide", |
476 G_CALLBACK(&OnButtonShowOrHideThunk), this); | 471 G_CALLBACK(&OnButtonShowOrHideThunk), this); |
477 | 472 |
478 gtk_widget_show(button->widget()); | 473 gtk_widget_show(button->widget()); |
479 | 474 |
480 UpdateVisibility(); | 475 UpdateVisibility(); |
481 } | 476 } |
482 | 477 |
483 GtkWidget* BrowserActionsToolbarGtk::GetBrowserActionWidget( | 478 GtkWidget* BrowserActionsToolbarGtk::GetBrowserActionWidget( |
484 Extension* extension) { | 479 Extension* extension) { |
485 ExtensionButtonMap::iterator it = extension_button_map_.find( | 480 ExtensionButtonMap::iterator it = extension_button_map_.find( |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 // several seconds later. | 700 // several seconds later. |
706 return TRUE; | 701 return TRUE; |
707 } | 702 } |
708 | 703 |
709 void BrowserActionsToolbarGtk::OnHierarchyChanged( | 704 void BrowserActionsToolbarGtk::OnHierarchyChanged( |
710 GtkWidget* widget, GtkWidget* previous_toplevel) { | 705 GtkWidget* widget, GtkWidget* previous_toplevel) { |
711 GtkWidget* toplevel = gtk_widget_get_toplevel(widget); | 706 GtkWidget* toplevel = gtk_widget_get_toplevel(widget); |
712 if (!GTK_WIDGET_TOPLEVEL(toplevel)) | 707 if (!GTK_WIDGET_TOPLEVEL(toplevel)) |
713 return; | 708 return; |
714 | 709 |
715 g_signal_connect(toplevel, "set-focus", G_CALLBACK(OnSetFocusThunk), this); | 710 signals_.Connect(toplevel, "set-focus", G_CALLBACK(OnSetFocusThunk), this); |
716 } | 711 } |
717 | 712 |
718 void BrowserActionsToolbarGtk::OnSetFocus(GtkWidget* widget, | 713 void BrowserActionsToolbarGtk::OnSetFocus(GtkWidget* widget, |
719 GtkWidget* focus_widget) { | 714 GtkWidget* focus_widget) { |
720 ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup(); | 715 ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup(); |
721 // The focus of the parent window has changed. Close the popup. Delay the hide | 716 // The focus of the parent window has changed. Close the popup. Delay the hide |
722 // because it will destroy the RenderViewHost, which may still be on the | 717 // because it will destroy the RenderViewHost, which may still be on the |
723 // call stack. | 718 // call stack. |
724 if (!popup || popup->being_inspected()) | 719 if (!popup || popup->being_inspected()) |
725 return; | 720 return; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 GtkWidget* menu_item = overflow_menu_->AppendMenuItemWithIcon( | 814 GtkWidget* menu_item = overflow_menu_->AppendMenuItemWithIcon( |
820 model_index, | 815 model_index, |
821 extension->name(), | 816 extension->name(), |
822 button->GetIcon()); | 817 button->GetIcon()); |
823 | 818 |
824 g_object_set_data(G_OBJECT(menu_item), kMenuItemKey, button); | 819 g_object_set_data(G_OBJECT(menu_item), kMenuItemKey, button); |
825 | 820 |
826 // TODO(estade): set the menu item's tooltip. | 821 // TODO(estade): set the menu item's tooltip. |
827 } | 822 } |
828 | 823 |
829 g_signal_connect(overflow_menu_->widget(), "button-press-event", | 824 signals_.Connect(overflow_menu_->widget(), "button-press-event", |
830 G_CALLBACK(OnOverflowMenuButtonPressThunk), this); | 825 G_CALLBACK(OnOverflowMenuButtonPressThunk), this); |
831 | 826 |
832 gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(overflow), | 827 gtk_chrome_button_set_paint_state(GTK_CHROME_BUTTON(overflow), |
833 GTK_STATE_ACTIVE); | 828 GTK_STATE_ACTIVE); |
834 overflow_menu_->PopupAsFromKeyEvent(overflow); | 829 overflow_menu_->PopupAsFromKeyEvent(overflow); |
835 | 830 |
836 return FALSE; | 831 return FALSE; |
837 } | 832 } |
838 | 833 |
839 gboolean BrowserActionsToolbarGtk::OnOverflowMenuButtonPress( | 834 gboolean BrowserActionsToolbarGtk::OnOverflowMenuButtonPress( |
840 GtkWidget* overflow, GdkEventButton* event) { | 835 GtkWidget* overflow, GdkEventButton* event) { |
841 if (event->button != 3) | 836 if (event->button != 3) |
842 return FALSE; | 837 return FALSE; |
843 | 838 |
844 GtkWidget* menu_item = GTK_MENU_SHELL(overflow)->active_menu_item; | 839 GtkWidget* menu_item = GTK_MENU_SHELL(overflow)->active_menu_item; |
845 if (!menu_item) | 840 if (!menu_item) |
846 return FALSE; | 841 return FALSE; |
847 | 842 |
848 void* data = g_object_get_data(G_OBJECT(menu_item), kMenuItemKey); | 843 void* data = g_object_get_data(G_OBJECT(menu_item), kMenuItemKey); |
849 DCHECK(data); | 844 DCHECK(data); |
850 BrowserActionButton* button = static_cast<BrowserActionButton*>(data); | 845 BrowserActionButton* button = static_cast<BrowserActionButton*>(data); |
851 button->GetContextMenu()->PopupAsContext(event->time); | 846 button->GetContextMenu()->PopupAsContext(event->time); |
852 return TRUE; | 847 return TRUE; |
853 } | 848 } |
854 | 849 |
855 void BrowserActionsToolbarGtk::OnButtonShowOrHide(GtkWidget* sender) { | 850 void BrowserActionsToolbarGtk::OnButtonShowOrHide(GtkWidget* sender) { |
856 if (!resize_animation_.IsAnimating()) | 851 if (!resize_animation_.IsAnimating()) |
857 UpdateChevronVisibility(); | 852 UpdateChevronVisibility(); |
858 } | 853 } |
OLD | NEW |