ShortcutKeys.cpp (3403B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "ShortcutKeys.h" 8 9 #include "mozilla/KeyEventHandler.h" 10 #include "mozilla/TextEvents.h" 11 #include "nsAtom.h" 12 #include "nsContentUtils.h" 13 14 namespace mozilla { 15 16 NS_IMPL_ISUPPORTS(ShortcutKeys, nsIObserver); 17 18 StaticRefPtr<ShortcutKeys> ShortcutKeys::sInstance; 19 20 ShortcutKeys::ShortcutKeys() 21 : mBrowserHandlers(nullptr), 22 mEditorHandlers(nullptr), 23 mInputHandlers(nullptr), 24 mTextAreaHandlers(nullptr) { 25 MOZ_ASSERT(!sInstance, "Attempt to instantiate a second ShortcutKeys."); 26 nsContentUtils::RegisterShutdownObserver(this); 27 } 28 29 ShortcutKeys::~ShortcutKeys() { 30 delete mBrowserHandlers; 31 delete mEditorHandlers; 32 delete mInputHandlers; 33 delete mTextAreaHandlers; 34 } 35 36 nsresult ShortcutKeys::Observe(nsISupports* aSubject, const char* aTopic, 37 const char16_t* aData) { 38 // Clear our strong reference so we can clean up. 39 ShortcutKeys::Shutdown(); 40 return NS_OK; 41 } 42 43 void ShortcutKeys::Shutdown() { sInstance = nullptr; } 44 45 /* static */ 46 KeyEventHandler* ShortcutKeys::GetHandlers(HandlerType aType) { 47 if (!sInstance) { 48 sInstance = new ShortcutKeys(); 49 } 50 51 return sInstance->EnsureHandlers(aType); 52 } 53 54 /* static */ 55 nsAtom* ShortcutKeys::ConvertEventToDOMEventType( 56 const WidgetKeyboardEvent* aWidgetKeyboardEvent) { 57 switch (aWidgetKeyboardEvent->mMessage) { 58 case eKeyDown: 59 return nsGkAtoms::keydown; 60 case eKeyUp: 61 return nsGkAtoms::keyup; 62 // eAccessKeyNotFound event is always created from eKeyPress event and 63 // the original eKeyPress event has stopped its propagation before 64 // dispatched into the DOM tree in this process and not matched with remote 65 // content's access keys. So, we should treat it as an eKeyPress event and 66 // execute a command if it's registered as a shortcut key. 67 case eKeyPress: 68 case eAccessKeyNotFound: 69 return nsGkAtoms::keypress; 70 default: 71 MOZ_ASSERT_UNREACHABLE( 72 "All event messages relating to shortcut keys should be handled"); 73 return nullptr; 74 } 75 } 76 77 KeyEventHandler* ShortcutKeys::EnsureHandlers(HandlerType aType) { 78 ShortcutKeyData* keyData; 79 KeyEventHandler** cache; 80 81 switch (aType) { 82 case HandlerType::eBrowser: 83 keyData = &sBrowserHandlers[0]; 84 cache = &mBrowserHandlers; 85 break; 86 case HandlerType::eEditor: 87 keyData = &sEditorHandlers[0]; 88 cache = &mEditorHandlers; 89 break; 90 case HandlerType::eInput: 91 keyData = &sInputHandlers[0]; 92 cache = &mInputHandlers; 93 break; 94 case HandlerType::eTextArea: 95 keyData = &sTextAreaHandlers[0]; 96 cache = &mTextAreaHandlers; 97 break; 98 default: 99 MOZ_ASSERT(false, "Unknown handler type requested."); 100 } 101 102 if (*cache) { 103 return *cache; 104 } 105 106 KeyEventHandler* lastHandler = nullptr; 107 while (keyData->event) { 108 KeyEventHandler* handler = new KeyEventHandler(keyData); 109 if (lastHandler) { 110 lastHandler->SetNextHandler(handler); 111 } else { 112 *cache = handler; 113 } 114 lastHandler = handler; 115 keyData++; 116 } 117 118 return *cache; 119 } 120 121 } // namespace mozilla