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/accelerators_gtk.h" 6 7 #include <gdk/gdk.h> 8 #include <gdk/gdkkeysyms.h> 9 #include <X11/XF86keysym.h> 10 11 #include "base/memory/singleton.h" 12 #include "chrome/app/chrome_command_ids.h" 13 #include "ui/base/accelerators/platform_accelerator_gtk.h" 14 #include "ui/base/events/event_conversion_gtk.h" 15 #include "ui/base/keycodes/keyboard_code_conversion_gtk.h" 16 17 namespace { 18 19 // A mostly complete list of chrome's accelerators. When one command has 20 // multiple shortcuts, the first one in this list is considered "primary", 21 // meaning that it will be displayed in context menus. 22 const struct AcceleratorMapping { 23 guint keyval; 24 int command_id; 25 GdkModifierType modifier_type; 26 } kAcceleratorMap[] = { 27 // Focus. 28 { GDK_k, IDC_FOCUS_SEARCH, GDK_CONTROL_MASK }, 29 { GDK_e, IDC_FOCUS_SEARCH, GDK_CONTROL_MASK }, 30 { XF86XK_Search, IDC_FOCUS_SEARCH, GdkModifierType(0) }, 31 { GDK_l, IDC_FOCUS_LOCATION, GDK_CONTROL_MASK }, 32 { GDK_d, IDC_FOCUS_LOCATION, GDK_MOD1_MASK }, 33 { GDK_F6, IDC_FOCUS_LOCATION, GdkModifierType(0) }, 34 { XF86XK_OpenURL, IDC_FOCUS_LOCATION, GdkModifierType(0) }, 35 { XF86XK_Go, IDC_FOCUS_LOCATION, GdkModifierType(0) }, 36 37 // Tab/window controls. 38 { GDK_Page_Down, IDC_SELECT_NEXT_TAB, GDK_CONTROL_MASK }, 39 { GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK }, 40 { GDK_Page_Down, IDC_MOVE_TAB_NEXT, 41 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 42 { GDK_Page_Up, IDC_MOVE_TAB_PREVIOUS, 43 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 44 { GDK_Page_Up, IDC_SELECT_PREVIOUS_TAB, GDK_CONTROL_MASK }, 45 { GDK_w, IDC_CLOSE_TAB, GDK_CONTROL_MASK }, 46 { GDK_t, IDC_RESTORE_TAB, 47 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 48 { GDK_t, IDC_NEW_TAB, GDK_CONTROL_MASK }, 49 { GDK_n, IDC_NEW_WINDOW, GDK_CONTROL_MASK }, 50 { GDK_n, IDC_NEW_INCOGNITO_WINDOW, 51 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 52 { GDK_w, IDC_CLOSE_WINDOW, 53 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 54 55 { GDK_1, IDC_SELECT_TAB_0, GDK_CONTROL_MASK }, 56 { GDK_2, IDC_SELECT_TAB_1, GDK_CONTROL_MASK }, 57 { GDK_3, IDC_SELECT_TAB_2, GDK_CONTROL_MASK }, 58 { GDK_4, IDC_SELECT_TAB_3, GDK_CONTROL_MASK }, 59 { GDK_5, IDC_SELECT_TAB_4, GDK_CONTROL_MASK }, 60 { GDK_6, IDC_SELECT_TAB_5, GDK_CONTROL_MASK }, 61 { GDK_7, IDC_SELECT_TAB_6, GDK_CONTROL_MASK }, 62 { GDK_8, IDC_SELECT_TAB_7, GDK_CONTROL_MASK }, 63 { GDK_9, IDC_SELECT_LAST_TAB, GDK_CONTROL_MASK }, 64 65 { GDK_1, IDC_SELECT_TAB_0, GDK_MOD1_MASK }, 66 { GDK_2, IDC_SELECT_TAB_1, GDK_MOD1_MASK }, 67 { GDK_3, IDC_SELECT_TAB_2, GDK_MOD1_MASK }, 68 { GDK_4, IDC_SELECT_TAB_3, GDK_MOD1_MASK }, 69 { GDK_5, IDC_SELECT_TAB_4, GDK_MOD1_MASK }, 70 { GDK_6, IDC_SELECT_TAB_5, GDK_MOD1_MASK }, 71 { GDK_7, IDC_SELECT_TAB_6, GDK_MOD1_MASK }, 72 { GDK_8, IDC_SELECT_TAB_7, GDK_MOD1_MASK }, 73 { GDK_9, IDC_SELECT_LAST_TAB, GDK_MOD1_MASK }, 74 75 { GDK_KP_1, IDC_SELECT_TAB_0, GDK_CONTROL_MASK }, 76 { GDK_KP_2, IDC_SELECT_TAB_1, GDK_CONTROL_MASK }, 77 { GDK_KP_3, IDC_SELECT_TAB_2, GDK_CONTROL_MASK }, 78 { GDK_KP_4, IDC_SELECT_TAB_3, GDK_CONTROL_MASK }, 79 { GDK_KP_5, IDC_SELECT_TAB_4, GDK_CONTROL_MASK }, 80 { GDK_KP_6, IDC_SELECT_TAB_5, GDK_CONTROL_MASK }, 81 { GDK_KP_7, IDC_SELECT_TAB_6, GDK_CONTROL_MASK }, 82 { GDK_KP_8, IDC_SELECT_TAB_7, GDK_CONTROL_MASK }, 83 { GDK_KP_9, IDC_SELECT_LAST_TAB, GDK_CONTROL_MASK }, 84 85 { GDK_KP_1, IDC_SELECT_TAB_0, GDK_MOD1_MASK }, 86 { GDK_KP_2, IDC_SELECT_TAB_1, GDK_MOD1_MASK }, 87 { GDK_KP_3, IDC_SELECT_TAB_2, GDK_MOD1_MASK }, 88 { GDK_KP_4, IDC_SELECT_TAB_3, GDK_MOD1_MASK }, 89 { GDK_KP_5, IDC_SELECT_TAB_4, GDK_MOD1_MASK }, 90 { GDK_KP_6, IDC_SELECT_TAB_5, GDK_MOD1_MASK }, 91 { GDK_KP_7, IDC_SELECT_TAB_6, GDK_MOD1_MASK }, 92 { GDK_KP_8, IDC_SELECT_TAB_7, GDK_MOD1_MASK }, 93 { GDK_KP_9, IDC_SELECT_LAST_TAB, GDK_MOD1_MASK }, 94 95 { GDK_F4, IDC_CLOSE_TAB, GDK_CONTROL_MASK }, 96 { GDK_F4, IDC_CLOSE_WINDOW, GDK_MOD1_MASK }, 97 98 // Zoom level. 99 { GDK_KP_Add, IDC_ZOOM_PLUS, GDK_CONTROL_MASK }, 100 { GDK_plus, IDC_ZOOM_PLUS, 101 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 102 { GDK_equal, IDC_ZOOM_PLUS, GDK_CONTROL_MASK }, 103 { XF86XK_ZoomIn, IDC_ZOOM_PLUS, GdkModifierType(0) }, 104 { GDK_KP_0, IDC_ZOOM_NORMAL, GDK_CONTROL_MASK }, 105 { GDK_0, IDC_ZOOM_NORMAL, GDK_CONTROL_MASK }, 106 { GDK_KP_Subtract, IDC_ZOOM_MINUS, GDK_CONTROL_MASK }, 107 { GDK_minus, IDC_ZOOM_MINUS, GDK_CONTROL_MASK }, 108 { GDK_underscore, IDC_ZOOM_MINUS, 109 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 110 { XF86XK_ZoomOut, IDC_ZOOM_MINUS, GdkModifierType(0) }, 111 112 // Find in page. 113 { GDK_g, IDC_FIND_NEXT, GDK_CONTROL_MASK }, 114 { GDK_F3, IDC_FIND_NEXT, GdkModifierType(0) }, 115 { GDK_g, IDC_FIND_PREVIOUS, 116 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 117 { GDK_F3, IDC_FIND_PREVIOUS, GDK_SHIFT_MASK }, 118 119 // Navigation / toolbar buttons. 120 { GDK_Home, IDC_HOME, GDK_MOD1_MASK }, 121 { XF86XK_HomePage, IDC_HOME, GdkModifierType(0) }, 122 { GDK_Escape, IDC_STOP, GdkModifierType(0) }, 123 { XF86XK_Stop, IDC_STOP, GdkModifierType(0) }, 124 { GDK_Left, IDC_BACK, GDK_MOD1_MASK }, 125 { XF86XK_Back, IDC_BACK, GdkModifierType(0) }, 126 { GDK_Right, IDC_FORWARD, GDK_MOD1_MASK }, 127 { XF86XK_Forward, IDC_FORWARD, GdkModifierType(0) }, 128 { GDK_r, IDC_RELOAD, GDK_CONTROL_MASK }, 129 { GDK_r, IDC_RELOAD_IGNORING_CACHE, 130 GdkModifierType(GDK_CONTROL_MASK|GDK_SHIFT_MASK) }, 131 { GDK_F5, IDC_RELOAD, GdkModifierType(0) }, 132 { GDK_F5, IDC_RELOAD_IGNORING_CACHE, GDK_CONTROL_MASK }, 133 { GDK_F5, IDC_RELOAD_IGNORING_CACHE, GDK_SHIFT_MASK }, 134 { XF86XK_Reload, IDC_RELOAD, GdkModifierType(0) }, 135 { XF86XK_Refresh, IDC_RELOAD, GdkModifierType(0) }, 136 137 // Dev tools. 138 { GDK_u, IDC_VIEW_SOURCE, GDK_CONTROL_MASK }, 139 { GDK_i, IDC_DEV_TOOLS, 140 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 141 { GDK_F12, IDC_DEV_TOOLS_TOGGLE, GdkModifierType(0) }, 142 { GDK_j, IDC_DEV_TOOLS_CONSOLE, 143 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 144 { GDK_c, IDC_DEV_TOOLS_INSPECT, 145 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 146 { GDK_Escape, IDC_TASK_MANAGER, GDK_SHIFT_MASK }, 147 148 // Editing. 149 { GDK_c, IDC_COPY, GDK_CONTROL_MASK }, 150 { GDK_x, IDC_CUT, GDK_CONTROL_MASK }, 151 { GDK_v, IDC_PASTE, GDK_CONTROL_MASK }, 152 153 // Miscellany. 154 { GDK_d, IDC_BOOKMARK_ALL_TABS, 155 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 156 { GDK_d, IDC_BOOKMARK_PAGE, GDK_CONTROL_MASK }, 157 { GDK_o, IDC_OPEN_FILE, GDK_CONTROL_MASK }, 158 { GDK_f, IDC_FIND, GDK_CONTROL_MASK }, 159 { GDK_p, IDC_PRINT, GDK_CONTROL_MASK }, 160 { GDK_p, IDC_ADVANCED_PRINT, 161 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 162 { GDK_b, IDC_SHOW_BOOKMARK_BAR, 163 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 164 { GDK_o, IDC_SHOW_BOOKMARK_MANAGER, 165 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 166 { GDK_F11, IDC_FULLSCREEN, GdkModifierType(0) }, 167 { GDK_Delete, IDC_CLEAR_BROWSING_DATA, 168 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 169 { GDK_h, IDC_SHOW_HISTORY, GDK_CONTROL_MASK }, 170 { GDK_j, IDC_SHOW_DOWNLOADS, GDK_CONTROL_MASK }, 171 { GDK_F1, IDC_HELP_PAGE_VIA_KEYBOARD, GdkModifierType(0) }, 172 { XF86XK_AddFavorite, IDC_BOOKMARK_PAGE, GdkModifierType(0) }, 173 { XF86XK_Favorites, IDC_SHOW_BOOKMARK_BAR, GdkModifierType(0) }, 174 { XF86XK_History, IDC_SHOW_HISTORY, GdkModifierType(0) }, 175 { GDK_q, IDC_EXIT, GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 176 { GDK_s, IDC_SAVE_PAGE, GDK_CONTROL_MASK }, 177 { GDK_e, IDC_SHOW_APP_MENU, GDK_MOD1_MASK }, 178 { GDK_f, IDC_SHOW_APP_MENU, GDK_MOD1_MASK }, 179 { GDK_m, IDC_SHOW_AVATAR_MENU, 180 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK)}, 181 { GDK_greater, IDC_TOGGLE_SPEECH_INPUT, 182 GdkModifierType(GDK_CONTROL_MASK | GDK_SHIFT_MASK) }, 183 }; 184 185 } // namespace 186 187 // static 188 AcceleratorsGtk* AcceleratorsGtk::GetInstance() { 189 return Singleton<AcceleratorsGtk>::get(); 190 } 191 192 const ui::Accelerator* AcceleratorsGtk::GetPrimaryAcceleratorForCommand( 193 int command_id) { 194 AcceleratorMap::const_iterator i(primary_accelerators_.find(command_id)); 195 return i != primary_accelerators_.end() ? &i->second : NULL; 196 } 197 198 AcceleratorsGtk::AcceleratorsGtk() { 199 for (size_t i = 0; i < arraysize(kAcceleratorMap); ++i) { 200 const AcceleratorMapping& entry = kAcceleratorMap[i]; 201 202 ui::Accelerator accelerator = ui::AcceleratorForGdkKeyCodeAndModifier( 203 entry.keyval, entry.modifier_type); 204 205 all_accelerators_.push_back(std::make_pair(entry.command_id, accelerator)); 206 if (primary_accelerators_.find(entry.command_id) == 207 primary_accelerators_.end()) { 208 primary_accelerators_[entry.command_id] = accelerator; 209 } 210 } 211 } 212 213 AcceleratorsGtk::~AcceleratorsGtk() {} 214