15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/browser_actions_toolbar_gtk.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gtk/gtk.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/rtl.h" 149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/commands/command_service.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_icon_factory.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_manager.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_context_menu_model.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/extension_service.h" 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_system.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sessions/session_tab_helper.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/browser_window_gtk.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/custom_button.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/extensions/extension_popup_gtk.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/gtk_chrome_button.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/gtk_chrome_shrinkable_hbox.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/gtk_theme_service.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/gtk_util.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/hover_controller_gtk.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/menu_gtk.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/gtk/view_id_util.h" 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension_manifest_constants.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_resources.h" 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/accelerators/platform_accelerator_gtk.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/gtk/gtk_compat.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas_skia_paint.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/gtk_util.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image_skia_operations.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::ExtensionActionManager; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The width of the browser action buttons. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kButtonWidth = 27; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The padding between browser action buttons. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kButtonPadding = 4; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The padding to the right of the browser action buttons (between the buttons 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and chevron if they are both showing). 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kButtonChevronPadding = 2; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The padding to the left, top and bottom of the browser actions toolbar 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// separator. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSeparatorPadding = 2; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Width of the invisible gripper for resizing the toolbar. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kResizeGripperWidth = 4; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDragTarget[] = "application/x-chrome-browseraction"; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GtkTargetEntry GetDragTargetEntry() { 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkTargetEntry drag_target; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_target.target = const_cast<char*>(kDragTarget); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_target.flags = GTK_TARGET_SAME_APP; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_target.info = 0; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return drag_target; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The minimum width in pixels of the button hbox if |icon_count| icons are 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// showing. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gint WidthForIconCount(gint icon_count) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::max((kButtonWidth + kButtonPadding) * icon_count - kButtonPadding, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using ui::SimpleMenuModel; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BrowserActionButton : public content::NotificationObserver, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public ExtensionActionIconFactory::Observer, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public ExtensionContextMenuModel::PopupDelegate, 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public MenuGtk::Delegate { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton(BrowserActionsToolbarGtk* toolbar, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkThemeService* theme_provider) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : toolbar_(toolbar), 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_(extension), 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_(NULL), 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icon_factory_(toolbar->browser()->profile(), extension, 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_action(), this), 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accel_group_(NULL) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button_.reset(new CustomDrawButton( 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) theme_provider, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTION, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTION_P, 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTION_H, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL)); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_size_request(button(), kButtonWidth, kButtonWidth); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alignment_.Own(gtk_alignment_new(0, 0, 1, 1)); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_container_add(GTK_CONTAINER(alignment_.get()), button()); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_show(button()); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(browser_action()); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateState(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(button(), "button-press-event", 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnButtonPress), this); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(button(), "clicked", 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnClicked), this); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(button(), "drag-begin", 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnDragBegin), this); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.ConnectAfter(widget(), "expose-event", 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnExposeEvent), this); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (toolbar_->browser()->window()) { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the window exists already, then the browser action button has been 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // recreated after the window was created, for example when the extension 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is reloaded. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConnectBrowserActionPopupAccelerator(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Window doesn't exist yet, wait for it. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(toolbar->widget(), "realize", 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnRealize), this); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<ExtensionAction>(browser_action())); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>( 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar->browser()->profile()->GetOriginalProfile())); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, chrome::NOTIFICATION_EXTENSION_COMMAND_ADDED, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>( 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar->browser()->profile()->GetOriginalProfile())); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, chrome::NOTIFICATION_EXTENSION_COMMAND_REMOVED, 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<Profile>( 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar->browser()->profile()->GetOriginalProfile())); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~BrowserActionButton() { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisconnectBrowserActionPopupAccelerator(); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) alignment_.Destroy(); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* button() { return button_->widget(); } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* widget() { return alignment_.get(); } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension() { return extension_; } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NotificationObserver implementation. 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void Observe(int type, 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::NotificationSource& source, 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::NotificationDetails& details) OVERRIDE { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (type) { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_EXTENSION_BROWSER_ACTION_UPDATED: 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateState(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_EXTENSION_UNLOADED: 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_WINDOW_CLOSED: 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisconnectBrowserActionPopupAccelerator(); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_EXTENSION_COMMAND_ADDED: 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case chrome::NOTIFICATION_EXTENSION_COMMAND_REMOVED: { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<const std::string, const std::string>* payload = 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Details<std::pair<const std::string, const std::string> >( 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) details).ptr(); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension_->id() == payload->first && 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) payload->second == 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_manifest_values::kBrowserActionCommandEvent) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == chrome::NOTIFICATION_EXTENSION_COMMAND_ADDED) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConnectBrowserActionPopupAccelerator(); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisconnectBrowserActionPopupAccelerator(); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExtensionActionIconFactory::Observer implementation. 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void OnIconUpdated() OVERRIDE { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateState(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Updates the button based on the latest state from the associated 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // browser action. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdateState() { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id = toolbar_->GetCurrentTabId(); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_id < 0) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string tooltip = browser_action()->GetTitle(tab_id); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tooltip.empty()) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_has_tooltip(button(), FALSE); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_tooltip_text(button(), tooltip.c_str()); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enabled_ = browser_action()->GetIsVisible(tab_id); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!enabled_) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button_->SetPaintOverride(GTK_STATE_INSENSITIVE); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button_->UnsetPaintOverride(); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Image image = icon_factory_.GetIcon(tab_id); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image.IsEmpty()) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enabled_) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetImage(image); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetImage(gfx::Image(gfx::ImageSkiaOperations::CreateTransparentImage( 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image.AsImageSkia(), .25))); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_queue_draw(button()); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Image GetIcon() { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return icon_factory_.GetIcon(toolbar_->GetCurrentTabId()); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuGtk* GetContextMenu() { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension_->ShowConfigureContextMenus()) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_menu_model_ = 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new ExtensionContextMenuModel(extension_, toolbar_->browser(), this); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_menu_.reset( 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new MenuGtk(this, context_menu_model_.get())); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context_menu_.get(); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Activate the browser action. 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Activate(GtkWidget* widget) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionToolbarModel* model = toolbar_->model(); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension = extension_; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Browser* browser = toolbar_->browser(); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL popup_url; 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (model->ExecuteBrowserAction(extension, browser, &popup_url)) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ExtensionToolbarModel::ACTION_NONE: 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ExtensionToolbarModel::ACTION_SHOW_POPUP: 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionPopupGtk::Show(popup_url, browser, widget, 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionPopupGtk::SHOW); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MenuGtk::Delegate implementation. 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void StoppedShowing() OVERRIDE { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enabled_) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button_->UnsetPaintOverride(); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button_->SetPaintOverride(GTK_STATE_INSENSITIVE); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the context menu was showing for the overflow menu, re-assert the 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // grab that was shadowed. 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (toolbar_->overflow_menu_.get()) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_util::GrabAllInput(toolbar_->overflow_menu_->widget()); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void CommandWillBeExecuted() OVERRIDE { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the context menu was showing for the overflow menu, and a command 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is executed, then stop showing the overflow menu. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (toolbar_->overflow_menu_.get()) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_->overflow_menu_->Cancel(); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ExtensionContextMenuModel::PopupDelegate implementation. 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void InspectPopup(ExtensionAction* action) OVERRIDE { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL popup_url = action->GetPopupUrl(toolbar_->GetCurrentTabId()); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionPopupGtk::Show(popup_url, toolbar_->browser(), widget(), 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionPopupGtk::SHOW_AND_INSPECT); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void SetImage(const gfx::Image& image) { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image_) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) image_ = gtk_image_new_from_pixbuf(image.ToGdkPixbuf()); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_button_set_image(GTK_BUTTON(button()), image_); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_image_set_from_pixbuf(GTK_IMAGE(image_), image.ToGdkPixbuf()); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static gboolean OnButtonPress(GtkWidget* widget, 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkEventButton* event, 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton* button) { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event->button != 3) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuGtk* menu = button->GetContextMenu(); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!menu) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button->button_->SetPaintOverride(GTK_STATE_ACTIVE); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->PopupForWidget(widget, event->button, event->time); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void OnClicked(GtkWidget* widget, BrowserActionButton* button) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (button->enabled_) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button->Activate(widget); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static gboolean OnExposeEvent(GtkWidget* widget, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkEventExpose* event, 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton* button) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tab_id = button->toolbar_->GetCurrentTabId(); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_id < 0) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionAction* action = button->browser_action(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (action->GetBadgeText(tab_id).empty()) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::CanvasSkiaPaint canvas(event, false); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkAllocation allocation; 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_get_allocation(widget, &allocation); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) action->PaintBadge(&canvas, gfx::Rect(allocation), tab_id); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void OnDragBegin(GtkWidget* widget, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkDragContext* drag_context, 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton* button) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Simply pass along the notification to the toolbar. The point of this 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function is to tell the toolbar which BrowserActionButton initiated the 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // drag. 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button->toolbar_->DragStarted(button, drag_context); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The accelerator handler for when the shortcuts to open the popup is struck. 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static gboolean OnGtkAccelerator(GtkAccelGroup* accel_group, 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GObject* acceleratable, 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) guint keyval, 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkModifierType modifier, 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton* button) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Open the popup for this extension. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* anchor = button->widget(); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The anchor might be in the overflow menu. Then we point to the chevron. 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gtk_widget_get_visible(anchor)) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) anchor = button->toolbar_->chevron(); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button->Activate(anchor); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The handler for when the browser action is realized. |user_data| contains a 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pointer to the BrowserAction shown. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void OnRealize(GtkWidget* widget, void* user_data) { 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton* button = static_cast<BrowserActionButton*>(user_data); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button->ConnectBrowserActionPopupAccelerator(); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Connect the accelerator for the browser action popup. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ConnectBrowserActionPopupAccelerator() { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::CommandService* command_service = 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::CommandService::Get(toolbar_->browser()->profile()); 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::Command command; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (command_service->GetBrowserActionCommand(extension_->id(), 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::CommandService::ACTIVE_ONLY, 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &command, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL)) { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Found the browser action shortcut command, register it. 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) keybinding_ = command.accelerator(); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::NativeWindow window = 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_->browser()->window()->GetNativeWindow(); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accel_group_ = gtk_accel_group_new(); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_window_add_accel_group(window, accel_group_); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_accel_group_connect( 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accel_group_, 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::GetGdkKeyCodeForAccelerator(keybinding_), 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::GetGdkModifierForAccelerator(keybinding_), 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkAccelFlags(0), 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_cclosure_new(G_CALLBACK(OnGtkAccelerator), this, NULL)); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we've added an accelerator, we'll need to unregister it before 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the window is closed, so we listen for the window being closed. 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_WINDOW_CLOSED, 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<GtkWindow>(window)); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disconnect the accelerator for the browser action popup and delete clean up 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the accelerator group registration. 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DisconnectBrowserActionPopupAccelerator() { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (accel_group_) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::NativeWindow window = 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toolbar_->browser()->window()->GetNativeWindow(); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_accel_group_disconnect_key( 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accel_group_, 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::GetGdkKeyCodeForAccelerator(keybinding_), 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetGdkModifierForAccelerator(keybinding_)); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_window_remove_accel_group(window, accel_group_); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_object_unref(accel_group_); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) accel_group_ = NULL; 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) keybinding_ = ui::Accelerator(); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We've removed the accelerator, so no need to listen to this anymore. 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Remove(this, 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_WINDOW_CLOSED, 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<GtkWindow>(window)); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionAction* browser_action() const { 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ExtensionActionManager::Get(toolbar_->browser()->profile())-> 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetBrowserAction(*extension_); 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The toolbar containing this button. 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionsToolbarGtk* toolbar_; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The extension that contains this browser action. 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension_; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The button for this browser action. 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<CustomDrawButton> button_; 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Whether the browser action is enabled (equivalent to whether a page action 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is visible). 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool enabled_; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The top level widget (parent of |button_|). 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::OwnedWidgetGtk alignment_; 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The one image subwidget in |button_|. We keep this out so we don't alter 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the widget hierarchy while changing the button image because changing the 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GTK widget hierarchy invalidates all tooltips and several popular 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extensions change browser action icon in a loop. 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* image_; 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The object that will be used to get the browser action icon for us. 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It may load the icon asynchronously (in which case the initial icon 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returned by the factory will be transparent), so we have to observe it for 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // updates to the icon. 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionActionIconFactory icon_factory_; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as |default_icon_|, but stored as SkBitmap. 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkBitmap default_skbitmap_; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::GtkSignalRegistrar signals_; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationRegistrar registrar_; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The accelerator group used to handle accelerators, owned by this object. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkAccelGroup* accel_group_; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The keybinding accelerator registered to show the browser action popup. 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::Accelerator keybinding_; 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The context menu view and model for this extension action. 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<MenuGtk> context_menu_; 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<ExtensionContextMenuModel> context_menu_model_; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class BrowserActionsToolbarGtk; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserActionsToolbarGtk ---------------------------------------------------- 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserActionsToolbarGtk::BrowserActionsToolbarGtk(Browser* browser) 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : browser_(browser), 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(browser->profile()), 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) theme_service_(GtkThemeService::GetFrom(browser->profile())), 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_(NULL), 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hbox_(gtk_hbox_new(FALSE, 0)), 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button_hbox_(gtk_chrome_shrinkable_hbox_new(TRUE, FALSE, kButtonPadding)), 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_button_(NULL), 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_index_(-1), 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_(this), 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_width_(0), 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_width_(0), 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_(this) { 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExtensionService* extension_service = 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)->extension_service(); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension_service) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_button_.reset(new CustomDrawButton( 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) theme_service_, 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTIONS_OVERFLOW, 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTIONS_OVERFLOW_P, 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTIONS_OVERFLOW_H, 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 0, 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE))); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* gripper = gtk_button_new(); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_size_request(gripper, kResizeGripperWidth, -1); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_can_focus(gripper, FALSE); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_add_events(gripper, GDK_POINTER_MOTION_MASK); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(gripper, "motion-notify-event", 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnGripperMotionNotifyThunk), this); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(gripper, "expose-event", 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnGripperExposeThunk), this); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(gripper, "enter-notify-event", 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnGripperEnterNotifyThunk), this); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(gripper, "leave-notify-event", 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnGripperLeaveNotifyThunk), this); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(gripper, "button-release-event", 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnGripperButtonReleaseThunk), this); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(gripper, "button-press-event", 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnGripperButtonPressThunk), this); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(chevron(), "button-press-event", 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnOverflowButtonPressThunk), this); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |overflow_alignment| adds padding to the right of the browser action 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // buttons, but only appears when the overflow menu is showing. 538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) overflow_alignment_.Own(gtk_alignment_new(0, 0, 1, 1)); 539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_container_add(GTK_CONTAINER(overflow_alignment_.get()), chevron()); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |overflow_area_| holds the overflow chevron and the separator, which 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is only shown in GTK+ theme mode. 543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) overflow_area_.Own(gtk_hbox_new(FALSE, 0)); 544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_box_pack_start(GTK_BOX(overflow_area_.get()), overflow_alignment_.get(), 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FALSE, FALSE, 0); 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) separator_.Own(gtk_vseparator_new()); 548c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_box_pack_start(GTK_BOX(overflow_area_.get()), separator_.get(), 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FALSE, FALSE, 0); 550c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_widget_set_no_show_all(separator_.get(), TRUE); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 552c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_widget_show_all(overflow_area_.get()); 553c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_widget_set_no_show_all(overflow_area_.get(), TRUE); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(hbox_.get()), gripper, FALSE, FALSE, 0); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_pack_start(GTK_BOX(hbox_.get()), button_hbox_.get(), TRUE, TRUE, 0); 557c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_box_pack_start(GTK_BOX(hbox_.get()), overflow_area_.get(), FALSE, FALSE, 558c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_ = extension_service->toolbar_model(); 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->AddObserver(this); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetupDrags(); 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_->extensions_initialized()) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateAllButtons(); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetContainerWidth(); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We want to connect to "set-focus" on the toplevel window; we have to wait 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // until we are added to a toplevel window to do so. 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(widget(), "hierarchy-changed", 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnHierarchyChangedThunk), this); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ViewIDUtil::SetID(button_hbox_.get(), VIEW_ID_BROWSER_ACTION_TOOLBAR); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add(this, 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_BROWSER_THEME_CHANGED, 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<ThemeService>(theme_service_)); 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) theme_service_->InitThemesFor(this); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserActionsToolbarGtk::~BrowserActionsToolbarGtk() { 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->RemoveObserver(this); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button_hbox_.Destroy(); 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hbox_.Destroy(); 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsToolbarGtk::GetCurrentTabId() const { 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::WebContents* active_tab = 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_->tab_strip_model()->GetActiveWebContents(); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!active_tab) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SessionTabHelper::FromWebContents(active_tab)->session_id().id(); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::Update() { 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExtensionButtonMap::iterator iter = extension_button_map_.begin(); 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != extension_button_map_.end(); ++iter) { 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second->UpdateState(); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::Observe( 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(chrome::NOTIFICATION_BROWSER_THEME_CHANGED == type); 610c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_widget_set_visible(separator_.get(), theme_service_->UsingNativeTheme()); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::SetupDrags() { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkTargetEntry drag_target = GetDragTargetEntry(); 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_drag_dest_set(button_hbox_.get(), GTK_DEST_DEFAULT_DROP, &drag_target, 1, 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GDK_ACTION_MOVE); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(button_hbox_.get(), "drag-motion", 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnDragMotionThunk), this); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::CreateAllButtons() { 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_button_map_.clear(); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0; 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::ExtensionList& toolbar_items = model_->toolbar_items(); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (extensions::ExtensionList::const_iterator iter = toolbar_items.begin(); 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter != toolbar_items.end(); ++iter) { 629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CreateButtonForExtension(iter->get(), i++); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::SetContainerWidth() { 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int showing_actions = model_->GetVisibleIconCount(); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (showing_actions >= 0) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetButtonHBoxWidth(WidthForIconCount(showing_actions)); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::CreateButtonForExtension( 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension, int index) { 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ShouldDisplayBrowserAction(extension)) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = model_->OriginalIndexToIncognito(index); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveButtonForExtension(extension); 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) linked_ptr<BrowserActionButton> button( 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new BrowserActionButton(this, extension, theme_service_)); 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_chrome_shrinkable_hbox_pack_start( 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get()), button->widget(), 0); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button->widget(), index); 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension_button_map_[extension->id()] = button; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkTargetEntry drag_target = GetDragTargetEntry(); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_drag_source_set(button->button(), GDK_BUTTON1_MASK, &drag_target, 1, 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GDK_ACTION_MOVE); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We ignore whether the drag was a "success" or "failure" in Gtk's opinion. 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(button->button(), "drag-end", 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(&OnDragEndThunk), this); 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(button->button(), "drag-failed", 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(&OnDragFailedThunk), this); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Any time a browser action button is shown or hidden we have to update 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the chevron state. 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(button->widget(), "show", 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(&OnButtonShowOrHideThunk), this); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(button->widget(), "hide", 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(&OnButtonShowOrHideThunk), this); 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_show(button->widget()); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisibility(); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GtkWidget* BrowserActionsToolbarGtk::GetBrowserActionWidget( 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionButtonMap::iterator it = extension_button_map_.find( 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extension->id()); 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == extension_button_map_.end()) 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it->second.get()->widget(); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::RemoveButtonForExtension( 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (extension_button_map_.erase(extension->id())) 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateVisibility(); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChevronVisibility(); 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::UpdateVisibility() { 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_visible(widget(), button_count() != 0); 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsToolbarGtk::ShouldDisplayBrowserAction( 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only display incognito-enabled extensions while in incognito mode. 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (!profile_->IsOffTheRecord() || 7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ExtensionSystem::Get(profile_)->extension_service()-> 7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsIncognitoEnabled(extension->id())); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::HidePopup() { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup(); 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (popup) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) popup->DestroyPopup(); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::AnimateToShowNIcons(int count) { 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) desired_width_ = WidthForIconCount(count); 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkAllocation allocation; 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_get_allocation(button_hbox_.get(), &allocation); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_width_ = allocation.width; 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_.Reset(); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_.Show(); 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::BrowserActionAdded(const Extension* extension, 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_.reset(); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateButtonForExtension(extension, index); 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are still initializing the container, don't bother animating. 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!model_->extensions_initialized()) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Animate the addition if we are showing all browser action buttons. 733c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!gtk_widget_get_visible(overflow_area_.get())) { 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnimateToShowNIcons(button_count()); 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetVisibleIconCount(button_count()); 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::BrowserActionRemoved( 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Extension* extension) { 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_.reset(); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_button_ != NULL) { 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Break the current drag. 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_grab_remove(button_hbox_.get()); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RemoveButtonForExtension(extension); 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 750c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!gtk_widget_get_visible(overflow_area_.get())) { 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnimateToShowNIcons(button_count()); 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetVisibleIconCount(button_count()); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::BrowserActionMoved(const Extension* extension, 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index) { 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We initiated this move action, and have already moved the button. 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_button_ != NULL) 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* button_widget = GetBrowserActionWidget(extension); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!button_widget) { 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldDisplayBrowserAction(extension)) 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = model_->OriginalIndexToIncognito(index); 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), button_widget, index); 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::ModelLoaded() { 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetContainerWidth(); 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::AnimationProgressed( 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::Animation* animation) { 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int width = start_width_ + (desired_width_ - start_width_) * 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation->GetCurrentValue(); 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_size_request(button_hbox_.get(), width, -1); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (width == desired_width_) 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_.Reset(); 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::AnimationEnded(const ui::Animation* animation) { 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_size_request(button_hbox_.get(), desired_width_, -1); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChevronVisibility(); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsToolbarGtk::IsCommandIdChecked(int command_id) const { 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsToolbarGtk::IsCommandIdEnabled(int command_id) const { 799868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const Extension* extension = model_->toolbar_items()[command_id].get(); 800868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return ExtensionActionManager::Get(profile_)->GetBrowserAction(*extension) 801868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->GetIsVisible(GetCurrentTabId()); 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsToolbarGtk::GetAcceleratorForCommandId( 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int command_id, 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::Accelerator* accelerator) { 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void BrowserActionsToolbarGtk::ExecuteCommand(int command_id, int event_flags) { 811868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const Extension* extension = model_->toolbar_items()[command_id].get(); 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GURL popup_url; 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (model_->ExecuteBrowserAction(extension, browser(), &popup_url)) { 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ExtensionToolbarModel::ACTION_NONE: 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ExtensionToolbarModel::ACTION_SHOW_POPUP: 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionPopupGtk::Show(popup_url, browser(), chevron(), 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionPopupGtk::SHOW); 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::StoppedShowing() { 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_button_->UnsetPaintOverride(); 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsToolbarGtk::AlwaysShowIconForCmd(int command_id) const { 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::DragStarted(BrowserActionButton* button, 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkDragContext* drag_context) { 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No representation of the widget following the cursor. 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 1, 1); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_drag_set_icon_pixbuf(drag_context, pixbuf, 0, 0); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_object_unref(pixbuf); 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!drag_button_); 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_button_ = button; 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::SetButtonHBoxWidth(int new_width) { 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gint max_width = WidthForIconCount(button_count()); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_width = std::min(max_width, new_width); 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_width = std::max(new_width, 0); 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_size_request(button_hbox_.get(), new_width, -1); 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::UpdateChevronVisibility() { 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int showing_icon_count = 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_chrome_shrinkable_hbox_get_visible_child_count( 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get())); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (showing_icon_count == 0) { 855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_.get()), 856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, 0, 0, 0); 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 858c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_alignment_set_padding(GTK_ALIGNMENT(overflow_alignment_.get()), 859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, 0, kButtonChevronPadding, 0); 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (button_count() > showing_icon_count) { 863c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!gtk_widget_get_visible(overflow_area_.get())) { 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_button_) { 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // During drags, when the overflow chevron shows for the first time, 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // take that much space away from |button_hbox_| to make the drag look 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // smoother. 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkRequisition req; 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_size_request(chevron(), &req); 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gint overflow_width = req.width; 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_size_request(button_hbox_.get(), &req); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gint button_hbox_width = req.width; 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button_hbox_width = std::max(button_hbox_width - overflow_width, 0); 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_set_size_request(button_hbox_.get(), button_hbox_width, -1); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_widget_show(overflow_area_.get()); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gtk_widget_hide(overflow_area_.get()); 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean BrowserActionsToolbarGtk::OnDragMotion(GtkWidget* widget, 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkDragContext* drag_context, 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gint x, gint y, guint time) { 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only handle drags we initiated. 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drag_button_) 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::i18n::IsRTL()) { 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkAllocation allocation; 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_get_allocation(widget, &allocation); 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x = allocation.width - x; 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_index_ = x < kButtonWidth ? 0 : x / (kButtonWidth + kButtonPadding); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will go ahead and reorder the child in order to provide visual feedback 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to the user. We don't inform the model that it has moved until the drag 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ends. 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_box_reorder_child(GTK_BOX(button_hbox_.get()), drag_button_->widget(), 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_index_); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_drag_status(drag_context, GDK_ACTION_MOVE, time); 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::OnDragEnd(GtkWidget* button, 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkDragContext* drag_context) { 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drop_index_ != -1) { 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_index_ = model_->IncognitoIndexToOriginal(drop_index_); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->MoveBrowserAction(drag_button_->extension(), drop_index_); 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_button_ = NULL; 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drop_index_ = -1; 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean BrowserActionsToolbarGtk::OnDragFailed(GtkWidget* widget, 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkDragContext* drag_context, 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkDragResult result) { 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We connect to this signal and return TRUE so that the default failure 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // animation (wherein the drag widget floats back to the start of the drag) 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // does not show, and the drag-end signal is emitted immediately instead of 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // several seconds later. 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::OnHierarchyChanged( 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* widget, GtkWidget* previous_toplevel) { 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* toplevel = gtk_widget_get_toplevel(widget); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gtk_widget_is_toplevel(toplevel)) 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(toplevel, "set-focus", G_CALLBACK(OnSetFocusThunk), this); 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::OnSetFocus(GtkWidget* widget, 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* focus_widget) { 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionPopupGtk* popup = ExtensionPopupGtk::get_current_extension_popup(); 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The focus of the parent window has changed. Close the popup. Delay the hide 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because it will destroy the RenderViewHost, which may still be on the 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // call stack. 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!popup || popup->being_inspected()) 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 949b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::MessageLoop::current()->PostTask( 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BrowserActionsToolbarGtk::HidePopup, 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) weak_factory_.GetWeakPtr())); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean BrowserActionsToolbarGtk::OnGripperMotionNotify( 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* widget, GdkEventMotion* event) { 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(event->state & GDK_BUTTON1_MASK)) 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calculate how much the user dragged the gripper and subtract that off the 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // button container's width. 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int distance_dragged; 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base::i18n::IsRTL()) { 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) distance_dragged = -event->x; 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkAllocation widget_allocation; 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_get_allocation(widget, &widget_allocation); 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) distance_dragged = event->x - widget_allocation.width; 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkAllocation button_hbox_allocation; 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_get_allocation(button_hbox_.get(), &button_hbox_allocation); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gint new_width = button_hbox_allocation.width - distance_dragged; 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetButtonHBoxWidth(new_width); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean BrowserActionsToolbarGtk::OnGripperExpose(GtkWidget* gripper, 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GdkEventExpose* expose) { 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These three signal handlers (EnterNotify, LeaveNotify, and ButtonRelease) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are used to give the gripper the resize cursor. Since it doesn't have its 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// own window, we have to set the cursor whenever the pointer moves into the 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// button or leaves the button, and be sure to leave it on when the user is 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dragging. 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean BrowserActionsToolbarGtk::OnGripperEnterNotify( 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* gripper, GdkEventCrossing* event) { 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_window_set_cursor(gtk_widget_get_window(gripper), 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::GetCursor(GDK_SB_H_DOUBLE_ARROW)); 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean BrowserActionsToolbarGtk::OnGripperLeaveNotify( 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* gripper, GdkEventCrossing* event) { 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(event->state & GDK_BUTTON1_MASK)) 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_window_set_cursor(gtk_widget_get_window(gripper), NULL); 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean BrowserActionsToolbarGtk::OnGripperButtonRelease( 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* gripper, GdkEventButton* event) { 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkAllocation allocation; 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_widget_get_allocation(gripper, &allocation); 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect gripper_rect(0, 0, allocation.width, allocation.height); 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Point release_point(event->x, event->y); 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gripper_rect.Contains(release_point)) 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gdk_window_set_cursor(gtk_widget_get_window(gripper), NULL); 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // After the user resizes the toolbar, we want to smartly resize it to be 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the perfect size to fit the buttons. 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int visible_icon_count = 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_chrome_shrinkable_hbox_get_visible_child_count( 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get())); 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnimateToShowNIcons(visible_icon_count); 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetVisibleIconCount(visible_icon_count); 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean BrowserActionsToolbarGtk::OnGripperButtonPress( 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* gripper, GdkEventButton* event) { 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_.Reset(); 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean BrowserActionsToolbarGtk::OnOverflowButtonPress( 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* overflow, GdkEventButton* event) { 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_model_.reset(new SimpleMenuModel(this)); 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int visible_icon_count = 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gtk_chrome_shrinkable_hbox_get_visible_child_count( 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get())); 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = visible_icon_count; i < button_count(); ++i) { 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int model_index = i; 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_index = model_->IncognitoIndexToOriginal(i); 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1043868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const Extension* extension = model_->toolbar_items()[model_index].get(); 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionButton* button = extension_button_map_[extension->id()].get(); 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_model_->AddItem(model_index, UTF8ToUTF16(extension->name())); 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_model_->SetIcon(overflow_menu_model_->GetItemCount() - 1, 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button->GetIcon()); 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(estade): set the menu item's tooltip. 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_.reset(new MenuGtk(this, overflow_menu_model_.get())); 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signals_.Connect(overflow_menu_->widget(), "button-press-event", 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) G_CALLBACK(OnOverflowMenuButtonPressThunk), this); 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_button_->SetPaintOverride(GTK_STATE_ACTIVE); 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->PopupAsFromKeyEvent(chevron()); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)gboolean BrowserActionsToolbarGtk::OnOverflowMenuButtonPress( 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* overflow, GdkEventButton* event) { 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (event->button != 3) 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GtkWidget* menu_item = GTK_MENU_SHELL(overflow)->active_menu_item; 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!menu_item) 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int item_index = g_list_index(GTK_MENU_SHELL(overflow)->children, menu_item); 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item_index == -1) { 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item_index += gtk_chrome_shrinkable_hbox_get_visible_child_count( 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GTK_CHROME_SHRINKABLE_HBOX(button_hbox_.get())); 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) item_index = model_->IncognitoIndexToOriginal(item_index); 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1083868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const Extension* extension = model_->toolbar_items()[item_index].get(); 1084868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ExtensionButtonMap::iterator it = extension_button_map_.find(extension->id()); 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == extension_button_map_.end()) { 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MenuGtk* menu = it->second.get()->GetContextMenu(); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!menu) 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return FALSE; 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) menu->PopupAsContext(gfx::Point(event->x_root, event->y_root), 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event->time); 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return TRUE; 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsToolbarGtk::OnButtonShowOrHide(GtkWidget* sender) { 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!resize_animation_.is_animating()) 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateChevronVisibility(); 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1103