Upstream version 7.35.144.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / gtk / extensions / extension_keybinding_registry_gtk.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/ui/gtk/extensions/extension_keybinding_registry_gtk.h"
6
7 #include <gtk/gtk.h>
8
9 #include "chrome/browser/extensions/api/commands/command_service.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "extensions/common/extension.h"
13 #include "ui/base/accelerators/platform_accelerator_gtk.h"
14
15 // static
16 void extensions::ExtensionKeybindingRegistry::SetShortcutHandlingSuspended(
17     bool suspended) {
18   ExtensionKeybindingRegistryGtk::set_shortcut_handling_suspended(suspended);
19 }
20
21 bool ExtensionKeybindingRegistryGtk::shortcut_handling_suspended_ = false;
22
23 ExtensionKeybindingRegistryGtk::ExtensionKeybindingRegistryGtk(
24     Profile* profile,
25     gfx::NativeWindow window,
26     ExtensionFilter extension_filter,
27     Delegate* delegate)
28     : ExtensionKeybindingRegistry(profile, extension_filter, delegate),
29       profile_(profile),
30       window_(window),
31       accel_group_(NULL) {
32   Init();
33 }
34
35 ExtensionKeybindingRegistryGtk::~ExtensionKeybindingRegistryGtk() {
36   if (accel_group_) {
37     gtk_accel_group_disconnect(accel_group_,
38                                NULL);  // Remove all closures.
39
40     gtk_window_remove_accel_group(window_, accel_group_);
41     g_object_unref(accel_group_);
42     accel_group_ = NULL;
43   }
44 }
45
46 gboolean ExtensionKeybindingRegistryGtk::HasPriorityHandler(
47     const GdkEventKey* event) const {
48   if (shortcut_handling_suspended_)
49     return FALSE;
50
51   ui::Accelerator accelerator = ui::AcceleratorForGdkKeyCodeAndModifier(
52       event->keyval, static_cast<GdkModifierType>(event->state));
53
54   return IsAcceleratorRegistered(accelerator);
55 }
56
57 void ExtensionKeybindingRegistryGtk::AddExtensionKeybinding(
58     const extensions::Extension* extension,
59     const std::string& command_name) {
60   extensions::CommandService* command_service =
61       extensions::CommandService::Get(profile_);
62   extensions::CommandMap commands;
63   command_service->GetNamedCommands(
64           extension->id(),
65           extensions::CommandService::ACTIVE_ONLY,
66           extensions::CommandService::REGULAR,
67           &commands);
68
69   for (extensions::CommandMap::const_iterator iter = commands.begin();
70        iter != commands.end(); ++iter) {
71     if (!command_name.empty() && (iter->second.command_name() != command_name))
72       continue;
73
74     ui::Accelerator accelerator(iter->second.accelerator());
75     AddEventTarget(accelerator, extension->id(), iter->second.command_name());
76
77     if (!accel_group_) {
78       accel_group_ = gtk_accel_group_new();
79       gtk_window_add_accel_group(window_, accel_group_);
80     }
81
82     gtk_accel_group_connect(
83         accel_group_,
84         ui::GetGdkKeyCodeForAccelerator(accelerator),
85         ui::GetGdkModifierForAccelerator(accelerator),
86         GtkAccelFlags(0),
87         g_cclosure_new(G_CALLBACK(OnGtkAcceleratorThunk), this, NULL));
88   }
89
90   // Unlike on Windows, we need to explicitly add the browser action and page
91   // action to the event_targets_, even though we don't register them as
92   // handlers. See http://crbug.com/124873.
93   extensions::Command browser_action;
94   if (command_service->GetBrowserActionCommand(
95           extension->id(),
96           extensions::CommandService::ACTIVE_ONLY,
97           &browser_action,
98           NULL)) {
99     AddEventTarget(browser_action.accelerator(),
100                    extension->id(),
101                    browser_action.command_name());
102   }
103
104   // Add the Page Action (if any).
105   extensions::Command page_action;
106   if (command_service->GetPageActionCommand(
107           extension->id(),
108           extensions::CommandService::ACTIVE_ONLY,
109           &page_action,
110           NULL)) {
111     AddEventTarget(
112         page_action.accelerator(), extension->id(), page_action.command_name());
113   }
114 }
115
116 void ExtensionKeybindingRegistryGtk::RemoveExtensionKeybindingImpl(
117     const ui::Accelerator& accelerator,
118     const std::string& command_name) {
119   // On GTK, unlike Windows, the Event Targets contain all events but we must
120   // only unregister the ones we registered targets for.
121   if (!ShouldIgnoreCommand(command_name)) {
122     gtk_accel_group_disconnect_key(
123         accel_group_,
124         ui::GetGdkKeyCodeForAccelerator(accelerator),
125         ui::GetGdkModifierForAccelerator(accelerator));
126   }
127 }
128
129 gboolean ExtensionKeybindingRegistryGtk::OnGtkAccelerator(
130     GtkAccelGroup* group,
131     GObject* acceleratable,
132     guint keyval,
133     GdkModifierType modifier) {
134   ui::Accelerator accelerator = ui::AcceleratorForGdkKeyCodeAndModifier(
135       keyval, modifier);
136
137   return ExtensionKeybindingRegistry::NotifyEventTargets(accelerator);
138 }