| 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 |