зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1419091: Switch to a compiled C++ table for html key bindings for browser and editor. r=masayuki
Rather than loading an XBL binding for <browser> and <editor> elements this generates the handlers from static C arrays. Differential Revision: https://phabricator.services.mozilla.com/D6181 --HG-- extra : rebase_source : 690dee71ad81fad157052f342451047f10ef3811 extra : intermediate-source : ac56492b6ed6f03cd61389db83a73e0fdf970089 extra : source : a33e19d9f6d584e51153205efc7b5693119818cc
This commit is contained in:
Родитель
6ea60e6b82
Коммит
c8c2fa1025
|
@ -0,0 +1,94 @@
|
|||
#include "mozilla/ShortcutKeys.h"
|
||||
#include "../nsXBLPrototypeHandler.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
NS_IMPL_ISUPPORTS(ShortcutKeys, nsIObserver);
|
||||
|
||||
StaticRefPtr<ShortcutKeys> ShortcutKeys::sInstance;
|
||||
|
||||
ShortcutKeys::ShortcutKeys()
|
||||
: mBrowserHandlers(nullptr)
|
||||
, mEditorHandlers(nullptr)
|
||||
, mInputHandlers(nullptr)
|
||||
, mTextAreaHandlers(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(!sInstance, "Attempt to instantiate a second ShortcutKeys.");
|
||||
nsContentUtils::RegisterShutdownObserver(this);
|
||||
}
|
||||
|
||||
ShortcutKeys::~ShortcutKeys()
|
||||
{
|
||||
delete mBrowserHandlers;
|
||||
delete mEditorHandlers;
|
||||
delete mInputHandlers;
|
||||
delete mTextAreaHandlers;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ShortcutKeys::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData)
|
||||
{
|
||||
// Clear our strong reference so we can clean up.
|
||||
sInstance = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ nsXBLPrototypeHandler*
|
||||
ShortcutKeys::GetHandlers(HandlerType aType)
|
||||
{
|
||||
if (!sInstance) {
|
||||
sInstance = new ShortcutKeys();
|
||||
}
|
||||
|
||||
return sInstance->EnsureHandlers(aType);
|
||||
}
|
||||
|
||||
nsXBLPrototypeHandler*
|
||||
ShortcutKeys::EnsureHandlers(HandlerType aType)
|
||||
{
|
||||
ShortcutKeyData* keyData;
|
||||
nsXBLPrototypeHandler** cache;
|
||||
|
||||
switch (aType) {
|
||||
case HandlerType::eBrowser:
|
||||
keyData = &sBrowserHandlers[0];
|
||||
cache = &mBrowserHandlers;
|
||||
break;
|
||||
case HandlerType::eEditor:
|
||||
keyData = &sEditorHandlers[0];
|
||||
cache = &mEditorHandlers;
|
||||
break;
|
||||
case HandlerType::eInput:
|
||||
keyData = &sInputHandlers[0];
|
||||
cache = &mInputHandlers;
|
||||
break;
|
||||
case HandlerType::eTextArea:
|
||||
keyData = &sTextAreaHandlers[0];
|
||||
cache = &mTextAreaHandlers;
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSERT(false, "Unknown handler type requested.");
|
||||
}
|
||||
|
||||
if (*cache) {
|
||||
return *cache;
|
||||
}
|
||||
|
||||
nsXBLPrototypeHandler* lastHandler = nullptr;
|
||||
while (keyData->event) {
|
||||
nsXBLPrototypeHandler* handler =
|
||||
new nsXBLPrototypeHandler(keyData);
|
||||
if (lastHandler) {
|
||||
lastHandler->SetNextHandler(handler);
|
||||
} else {
|
||||
*cache = handler;
|
||||
}
|
||||
lastHandler = handler;
|
||||
keyData++;
|
||||
}
|
||||
|
||||
return *cache;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
|
@ -5,6 +5,10 @@
|
|||
#ifndef mozilla_dom_ShortcutKeys_h
|
||||
#define mozilla_dom_ShortcutKeys_h
|
||||
|
||||
#include "nsIObserver.h"
|
||||
|
||||
class nsXBLPrototypeHandler;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
typedef struct
|
||||
|
@ -16,13 +20,44 @@ typedef struct
|
|||
const char16_t* command;
|
||||
} ShortcutKeyData;
|
||||
|
||||
class ShortcutKeys
|
||||
enum class HandlerType
|
||||
{
|
||||
eInput,
|
||||
eTextArea,
|
||||
eBrowser,
|
||||
eEditor,
|
||||
};
|
||||
|
||||
class ShortcutKeys : public nsIObserver
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
// Returns a pointer to the first handler for the given type.
|
||||
static nsXBLPrototypeHandler* GetHandlers(HandlerType aType);
|
||||
|
||||
protected:
|
||||
ShortcutKeys();
|
||||
virtual ~ShortcutKeys();
|
||||
|
||||
// Returns a pointer to the first handler for the given type.
|
||||
nsXBLPrototypeHandler* EnsureHandlers(HandlerType aType);
|
||||
|
||||
// Maintains a strong reference to the only instance.
|
||||
static StaticRefPtr<ShortcutKeys> sInstance;
|
||||
|
||||
// Shortcut keys for different elements.
|
||||
static ShortcutKeyData sBrowserHandlers[];
|
||||
static ShortcutKeyData sEditorHandlers[];
|
||||
static ShortcutKeyData sInputHandlers[];
|
||||
static ShortcutKeyData sTextAreaHandlers[];
|
||||
|
||||
// Cached event handlers generated from the above data.
|
||||
nsXBLPrototypeHandler* mBrowserHandlers;
|
||||
nsXBLPrototypeHandler* mEditorHandlers;
|
||||
nsXBLPrototypeHandler* mInputHandlers;
|
||||
nsXBLPrototypeHandler* mTextAreaHandlers;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -15,3 +15,8 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
|
|||
else:
|
||||
DIRS += ['emacs']
|
||||
|
||||
EXPORTS.mozilla += ['ShortcutKeys.h']
|
||||
|
||||
SOURCES += ['ShortcutKeys.cpp']
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
|
|
@ -106,11 +106,11 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(const char16_t* aEvent,
|
|||
}
|
||||
|
||||
nsXBLPrototypeHandler::nsXBLPrototypeHandler(Element* aHandlerElement, XBLReservedKey aReserved)
|
||||
: mHandlerElement(nullptr),
|
||||
mLineNumber(0),
|
||||
mReserved(aReserved),
|
||||
mNextHandler(nullptr),
|
||||
mPrototypeBinding(nullptr)
|
||||
: mHandlerElement(nullptr)
|
||||
, mLineNumber(0)
|
||||
, mReserved(aReserved)
|
||||
, mNextHandler(nullptr)
|
||||
, mPrototypeBinding(nullptr)
|
||||
{
|
||||
Init();
|
||||
|
||||
|
@ -118,6 +118,21 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(Element* aHandlerElement, XBLReserv
|
|||
ConstructPrototype(aHandlerElement);
|
||||
}
|
||||
|
||||
nsXBLPrototypeHandler::nsXBLPrototypeHandler(ShortcutKeyData* aKeyData)
|
||||
: mHandlerText(nullptr),
|
||||
mLineNumber(0),
|
||||
mReserved(XBLReservedKey_False),
|
||||
mNextHandler(nullptr),
|
||||
mPrototypeBinding(nullptr)
|
||||
{
|
||||
Init();
|
||||
|
||||
ConstructPrototype(nullptr, aKeyData->event, nullptr, nullptr,
|
||||
aKeyData->command, aKeyData->keycode, aKeyData->key,
|
||||
aKeyData->modifiers, nullptr, nullptr, nullptr, nullptr,
|
||||
nullptr);
|
||||
}
|
||||
|
||||
nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding)
|
||||
: mHandlerText(nullptr),
|
||||
mLineNumber(0),
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "nsIWeakReference.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "mozilla/ShortcutKeys.h"
|
||||
|
||||
class nsIContent;
|
||||
class nsIObjectInputStream;
|
||||
|
@ -93,6 +94,10 @@ public:
|
|||
// This constructor is used only by XUL key handlers (e.g., <key>)
|
||||
explicit nsXBLPrototypeHandler(mozilla::dom::Element* aKeyElement, XBLReservedKey aReserved);
|
||||
|
||||
// This constructor is used for keyboard handlers for browser, editor, input
|
||||
// and textarea elements.
|
||||
explicit nsXBLPrototypeHandler(mozilla::ShortcutKeyData* aKeyData);
|
||||
|
||||
// This constructor is used for handlers loaded from the cache
|
||||
explicit nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding);
|
||||
|
||||
|
|
|
@ -34,119 +34,18 @@
|
|||
#include "mozilla/dom/EventBinding.h"
|
||||
#include "mozilla/dom/KeyboardEvent.h"
|
||||
#include "mozilla/layers/KeyboardMap.h"
|
||||
#include "mozilla/ShortcutKeys.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
class nsXBLSpecialDocInfo : public nsIObserver
|
||||
{
|
||||
public:
|
||||
RefPtr<nsXBLDocumentInfo> mHTMLBindings;
|
||||
|
||||
static const char sHTMLBindingStr[];
|
||||
static const char sUserHTMLBindingStr[];
|
||||
|
||||
bool mInitialized;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
void LoadDocInfo();
|
||||
void GetHandlers(const nsACString& aRef,
|
||||
nsXBLPrototypeHandler** handler);
|
||||
|
||||
nsXBLSpecialDocInfo() : mInitialized(false) {}
|
||||
|
||||
protected:
|
||||
virtual ~nsXBLSpecialDocInfo() {}
|
||||
|
||||
};
|
||||
|
||||
const char nsXBLSpecialDocInfo::sHTMLBindingStr[] =
|
||||
"chrome://global/content/platformHTMLBindings.xml";
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsXBLSpecialDocInfo, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXBLSpecialDocInfo::Observe(nsISupports* aSubject,
|
||||
const char* aTopic,
|
||||
const char16_t* aData)
|
||||
{
|
||||
MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"), "wrong topic");
|
||||
|
||||
// On shutdown, clear our fields to avoid an extra cycle collection.
|
||||
mHTMLBindings = nullptr;
|
||||
mInitialized = false;
|
||||
nsContentUtils::UnregisterShutdownObserver(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsXBLSpecialDocInfo::LoadDocInfo()
|
||||
{
|
||||
if (mInitialized)
|
||||
return;
|
||||
mInitialized = true;
|
||||
nsContentUtils::RegisterShutdownObserver(this);
|
||||
|
||||
nsXBLService* xblService = nsXBLService::GetInstance();
|
||||
if (!xblService)
|
||||
return;
|
||||
|
||||
// Obtain the platform doc info
|
||||
nsCOMPtr<nsIURI> bindingURI;
|
||||
NS_NewURI(getter_AddRefs(bindingURI), sHTMLBindingStr);
|
||||
if (!bindingURI) {
|
||||
return;
|
||||
}
|
||||
xblService->LoadBindingDocumentInfo(nullptr, nullptr,
|
||||
bindingURI,
|
||||
nullptr,
|
||||
true,
|
||||
getter_AddRefs(mHTMLBindings));
|
||||
}
|
||||
|
||||
//
|
||||
// GetHandlers
|
||||
//
|
||||
//
|
||||
void
|
||||
nsXBLSpecialDocInfo::GetHandlers(const nsACString& aRef,
|
||||
nsXBLPrototypeHandler** aHandler)
|
||||
{
|
||||
if (mHTMLBindings) {
|
||||
nsXBLPrototypeBinding* binding = mHTMLBindings->GetPrototypeBinding(aRef);
|
||||
|
||||
NS_ASSERTION(binding, "No binding found for the XBL window key handler.");
|
||||
if (!binding)
|
||||
return;
|
||||
|
||||
*aHandler = binding->GetPrototypeHandlers();
|
||||
}
|
||||
}
|
||||
|
||||
// Init statics
|
||||
static StaticRefPtr<nsXBLSpecialDocInfo> sXBLSpecialDocInfo;
|
||||
uint32_t nsXBLWindowKeyHandler::sRefCnt = 0;
|
||||
|
||||
/* static */ void
|
||||
nsXBLWindowKeyHandler::EnsureSpecialDocInfo()
|
||||
{
|
||||
if (!sXBLSpecialDocInfo) {
|
||||
sXBLSpecialDocInfo = new nsXBLSpecialDocInfo();
|
||||
}
|
||||
sXBLSpecialDocInfo->LoadDocInfo();
|
||||
}
|
||||
|
||||
nsXBLWindowKeyHandler::nsXBLWindowKeyHandler(Element* aElement,
|
||||
EventTarget* aTarget)
|
||||
: mTarget(aTarget),
|
||||
mHandler(nullptr)
|
||||
{
|
||||
mWeakPtrForElement = do_GetWeakReference(aElement);
|
||||
++sRefCnt;
|
||||
}
|
||||
|
||||
nsXBLWindowKeyHandler::~nsXBLWindowKeyHandler()
|
||||
|
@ -154,11 +53,6 @@ nsXBLWindowKeyHandler::~nsXBLWindowKeyHandler()
|
|||
// If mWeakPtrForElement is non-null, we created a prototype handler.
|
||||
if (mWeakPtrForElement)
|
||||
delete mHandler;
|
||||
|
||||
--sRefCnt;
|
||||
if (!sRefCnt) {
|
||||
sXBLSpecialDocInfo = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsXBLWindowKeyHandler,
|
||||
|
@ -230,14 +124,12 @@ nsXBLWindowKeyHandler::EnsureHandlers()
|
|||
|
||||
BuildHandlerChain(el, &mHandler);
|
||||
} else { // We are an XBL file of handlers.
|
||||
EnsureSpecialDocInfo();
|
||||
|
||||
// Now determine which handlers we should be using.
|
||||
if (IsHTMLEditableFieldFocused()) {
|
||||
sXBLSpecialDocInfo->GetHandlers(NS_LITERAL_CSTRING("editor"), &mHandler);
|
||||
mHandler = ShortcutKeys::GetHandlers(HandlerType::eEditor);
|
||||
}
|
||||
else {
|
||||
sXBLSpecialDocInfo->GetHandlers(NS_LITERAL_CSTRING("browser"), &mHandler);
|
||||
mHandler = ShortcutKeys::GetHandlers(HandlerType::eBrowser);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,11 +288,7 @@ nsXBLWindowKeyHandler::RemoveKeyboardEventListenersFrom(
|
|||
/* static */ KeyboardMap
|
||||
nsXBLWindowKeyHandler::CollectKeyboardShortcuts()
|
||||
{
|
||||
// Load the XBL handlers
|
||||
EnsureSpecialDocInfo();
|
||||
|
||||
nsXBLPrototypeHandler* handlers = nullptr;
|
||||
sXBLSpecialDocInfo->GetHandlers(NS_LITERAL_CSTRING("browser"), &handlers);
|
||||
nsXBLPrototypeHandler* handlers = ShortcutKeys::GetHandlers(HandlerType::eBrowser);
|
||||
|
||||
// Convert the handlers into keyboard shortcuts, using an AutoTArray with
|
||||
// the maximum amount of shortcuts used on any platform to minimize allocations
|
||||
|
|
|
@ -88,9 +88,6 @@ protected:
|
|||
nsAtom* ConvertEventToDOMEventType(
|
||||
const mozilla::WidgetKeyboardEvent& aWidgetKeyboardEvent) const;
|
||||
|
||||
// lazily load the special doc info for loading handlers
|
||||
static void EnsureSpecialDocInfo();
|
||||
|
||||
// lazily load the handlers. Overridden to handle being attached
|
||||
// to a particular element rather than the document
|
||||
nsresult EnsureHandlers();
|
||||
|
@ -126,12 +123,7 @@ protected:
|
|||
nsWeakPtr mWeakPtrForElement;
|
||||
mozilla::dom::EventTarget* mTarget; // weak ref
|
||||
|
||||
// these are not owning references; the prototype handlers are owned
|
||||
// by the prototype bindings which are owned by the docinfo.
|
||||
nsXBLPrototypeHandler* mHandler; // platform bindings
|
||||
|
||||
// holds reference count to document info about bindings
|
||||
static uint32_t sRefCnt;
|
||||
};
|
||||
|
||||
already_AddRefed<nsXBLWindowKeyHandler>
|
||||
|
|
Загрузка…
Ссылка в новой задаче