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