2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-05-21 04:12:37 -07:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#include "nsCOMPtr.h"
|
|
|
|
#include "nsXBLPrototypeHandler.h"
|
|
|
|
#include "nsXBLWindowKeyHandler.h"
|
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsIAtom.h"
|
|
|
|
#include "nsIDOMKeyEvent.h"
|
|
|
|
#include "nsXBLService.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsGkAtoms.h"
|
2010-07-14 18:53:11 -07:00
|
|
|
#include "nsXBLDocumentInfo.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIDOMElement.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
#include "nsFocusManager.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIURI.h"
|
|
|
|
#include "nsNetUtil.h"
|
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsXBLPrototypeBinding.h"
|
|
|
|
#include "nsPIDOMWindow.h"
|
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsISelectionController.h"
|
2011-05-28 00:03:00 -07:00
|
|
|
#include "mozilla/Preferences.h"
|
2013-09-25 04:21:19 -07:00
|
|
|
#include "mozilla/TextEvents.h"
|
2011-07-20 12:18:54 -07:00
|
|
|
#include "mozilla/dom/Element.h"
|
2013-01-24 08:38:59 -08:00
|
|
|
#include "nsEventStateManager.h"
|
2014-01-22 19:18:51 -08:00
|
|
|
#include "nsIEditor.h"
|
|
|
|
#include "nsIHTMLEditor.h"
|
2011-05-28 00:03:00 -07:00
|
|
|
|
|
|
|
using namespace mozilla;
|
2013-04-05 17:44:26 -07:00
|
|
|
using namespace mozilla::dom;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-10-14 09:15:12 -07:00
|
|
|
class nsXBLSpecialDocInfo : public nsIObserver
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
public:
|
2010-07-14 18:53:11 -07:00
|
|
|
nsRefPtr<nsXBLDocumentInfo> mHTMLBindings;
|
|
|
|
nsRefPtr<nsXBLDocumentInfo> mUserHTMLBindings;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
static const char sHTMLBindingStr[];
|
|
|
|
static const char sUserHTMLBindingStr[];
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool mInitialized;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
public:
|
2012-10-14 09:15:12 -07:00
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
NS_DECL_NSIOBSERVER
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void LoadDocInfo();
|
|
|
|
void GetAllHandlers(const char* aType,
|
|
|
|
nsXBLPrototypeHandler** handler,
|
|
|
|
nsXBLPrototypeHandler** userHandler);
|
2010-07-14 18:53:11 -07:00
|
|
|
void GetHandlers(nsXBLDocumentInfo* aInfo,
|
2007-03-22 10:30:00 -07:00
|
|
|
const nsACString& aRef,
|
|
|
|
nsXBLPrototypeHandler** aResult);
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
nsXBLSpecialDocInfo() : mInitialized(false) {}
|
2012-10-14 09:15:12 -07:00
|
|
|
|
|
|
|
virtual ~nsXBLSpecialDocInfo() {}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
const char nsXBLSpecialDocInfo::sHTMLBindingStr[] =
|
|
|
|
"chrome://global/content/platformHTMLBindings.xml";
|
|
|
|
|
2012-10-14 09:15:12 -07:00
|
|
|
NS_IMPL_ISUPPORTS1(nsXBLSpecialDocInfo, nsIObserver)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsXBLSpecialDocInfo::Observe(nsISupports* aSubject,
|
|
|
|
const char* aTopic,
|
2014-01-04 07:02:17 -08:00
|
|
|
const char16_t* aData)
|
2012-10-14 09:15:12 -07:00
|
|
|
{
|
|
|
|
MOZ_ASSERT(!strcmp(aTopic, "xpcom-shutdown"), "wrong topic");
|
|
|
|
|
|
|
|
// On shutdown, clear our fields to avoid an extra cycle collection.
|
|
|
|
mHTMLBindings = nullptr;
|
|
|
|
mUserHTMLBindings = nullptr;
|
|
|
|
mInitialized = false;
|
|
|
|
nsContentUtils::UnregisterShutdownObserver(this);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
void nsXBLSpecialDocInfo::LoadDocInfo()
|
|
|
|
{
|
|
|
|
if (mInitialized)
|
|
|
|
return;
|
2011-10-17 07:59:28 -07:00
|
|
|
mInitialized = true;
|
2012-10-14 09:15:12 -07:00
|
|
|
nsContentUtils::RegisterShutdownObserver(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2012-05-23 11:46:04 -07:00
|
|
|
nsXBLService* xblService = nsXBLService::GetInstance();
|
|
|
|
if (!xblService)
|
2007-03-22 10:30:00 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Obtain the platform doc info
|
|
|
|
nsCOMPtr<nsIURI> bindingURI;
|
|
|
|
NS_NewURI(getter_AddRefs(bindingURI), sHTMLBindingStr);
|
|
|
|
if (!bindingURI) {
|
|
|
|
return;
|
|
|
|
}
|
2012-07-30 07:20:58 -07:00
|
|
|
xblService->LoadBindingDocumentInfo(nullptr, nullptr,
|
2007-03-22 10:30:00 -07:00
|
|
|
bindingURI,
|
2012-07-30 07:20:58 -07:00
|
|
|
nullptr,
|
2011-10-17 07:59:28 -07:00
|
|
|
true,
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_AddRefs(mHTMLBindings));
|
|
|
|
|
|
|
|
const nsAdoptingCString& userHTMLBindingStr =
|
2011-05-28 00:03:00 -07:00
|
|
|
Preferences::GetCString("dom.userHTMLBindings.uri");
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!userHTMLBindingStr.IsEmpty()) {
|
|
|
|
NS_NewURI(getter_AddRefs(bindingURI), userHTMLBindingStr);
|
|
|
|
if (!bindingURI) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-30 07:20:58 -07:00
|
|
|
xblService->LoadBindingDocumentInfo(nullptr, nullptr,
|
2007-03-22 10:30:00 -07:00
|
|
|
bindingURI,
|
2012-07-30 07:20:58 -07:00
|
|
|
nullptr,
|
2011-10-17 07:59:28 -07:00
|
|
|
true,
|
2007-03-22 10:30:00 -07:00
|
|
|
getter_AddRefs(mUserHTMLBindings));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// GetHandlers
|
|
|
|
//
|
|
|
|
//
|
|
|
|
void
|
2010-07-14 18:53:11 -07:00
|
|
|
nsXBLSpecialDocInfo::GetHandlers(nsXBLDocumentInfo* aInfo,
|
2007-03-22 10:30:00 -07:00
|
|
|
const nsACString& aRef,
|
|
|
|
nsXBLPrototypeHandler** aResult)
|
|
|
|
{
|
2010-07-14 18:55:54 -07:00
|
|
|
nsXBLPrototypeBinding* binding = aInfo->GetPrototypeBinding(aRef);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
NS_ASSERTION(binding, "No binding found for the XBL window key handler.");
|
|
|
|
if (!binding)
|
|
|
|
return;
|
|
|
|
|
|
|
|
*aResult = binding->GetPrototypeHandlers();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsXBLSpecialDocInfo::GetAllHandlers(const char* aType,
|
|
|
|
nsXBLPrototypeHandler** aHandler,
|
|
|
|
nsXBLPrototypeHandler** aUserHandler)
|
|
|
|
{
|
|
|
|
if (mUserHTMLBindings) {
|
2012-09-01 19:35:17 -07:00
|
|
|
nsAutoCString type(aType);
|
2007-03-22 10:30:00 -07:00
|
|
|
type.Append("User");
|
|
|
|
GetHandlers(mUserHTMLBindings, type, aUserHandler);
|
|
|
|
}
|
|
|
|
if (mHTMLBindings) {
|
|
|
|
GetHandlers(mHTMLBindings, nsDependentCString(aType), aHandler);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Init statics
|
2012-07-30 07:20:58 -07:00
|
|
|
nsXBLSpecialDocInfo* nsXBLWindowKeyHandler::sXBLSpecialDocInfo = nullptr;
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t nsXBLWindowKeyHandler::sRefCnt = 0;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-05-14 02:11:38 -07:00
|
|
|
nsXBLWindowKeyHandler::nsXBLWindowKeyHandler(nsIDOMElement* aElement,
|
2013-04-14 11:27:33 -07:00
|
|
|
EventTarget* aTarget)
|
2007-05-14 02:11:38 -07:00
|
|
|
: mTarget(aTarget),
|
2012-07-30 07:20:58 -07:00
|
|
|
mHandler(nullptr),
|
|
|
|
mUserHandler(nullptr)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
mWeakPtrForElement = do_GetWeakReference(aElement);
|
|
|
|
++sRefCnt;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsXBLWindowKeyHandler::~nsXBLWindowKeyHandler()
|
|
|
|
{
|
|
|
|
// If mWeakPtrForElement is non-null, we created a prototype handler.
|
|
|
|
if (mWeakPtrForElement)
|
|
|
|
delete mHandler;
|
|
|
|
|
|
|
|
--sRefCnt;
|
|
|
|
if (!sRefCnt) {
|
2012-10-14 09:15:12 -07:00
|
|
|
NS_IF_RELEASE(sXBLSpecialDocInfo);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-24 16:12:34 -07:00
|
|
|
NS_IMPL_ISUPPORTS1(nsXBLWindowKeyHandler,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIDOMEventListener)
|
|
|
|
|
|
|
|
static void
|
|
|
|
BuildHandlerChain(nsIContent* aContent, nsXBLPrototypeHandler** aResult)
|
|
|
|
{
|
2012-07-30 07:20:58 -07:00
|
|
|
*aResult = nullptr;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Since we chain each handler onto the next handler,
|
|
|
|
// we'll enumerate them here in reverse so that when we
|
|
|
|
// walk the chain they'll come out in the original order
|
2011-09-27 00:54:58 -07:00
|
|
|
for (nsIContent* key = aContent->GetLastChild();
|
|
|
|
key;
|
|
|
|
key = key->GetPreviousSibling()) {
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (key->NodeInfo()->Equals(nsGkAtoms::key, kNameSpaceID_XUL)) {
|
2008-04-14 21:16:24 -07:00
|
|
|
// Check whether the key element has empty value at key/char attribute.
|
|
|
|
// Such element is used by localizers for alternative shortcut key
|
|
|
|
// definition on the locale. See bug 426501.
|
2008-04-23 01:04:08 -07:00
|
|
|
nsAutoString valKey, valCharCode, valKeyCode;
|
2011-09-28 23:19:26 -07:00
|
|
|
bool attrExists =
|
2008-04-23 01:04:08 -07:00
|
|
|
key->GetAttr(kNameSpaceID_None, nsGkAtoms::key, valKey) ||
|
|
|
|
key->GetAttr(kNameSpaceID_None, nsGkAtoms::charcode, valCharCode) ||
|
|
|
|
key->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, valKeyCode);
|
|
|
|
if (attrExists &&
|
|
|
|
valKey.IsEmpty() && valCharCode.IsEmpty() && valKeyCode.IsEmpty())
|
2008-04-14 21:16:24 -07:00
|
|
|
continue;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsXBLPrototypeHandler* handler = new nsXBLPrototypeHandler(key);
|
|
|
|
|
|
|
|
if (!handler)
|
|
|
|
return;
|
|
|
|
|
|
|
|
handler->SetNextHandler(*aResult);
|
|
|
|
*aResult = handler;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// EnsureHandlers
|
|
|
|
//
|
|
|
|
// Lazily load the XBL handlers. Overridden to handle being attached
|
|
|
|
// to a particular element rather than the document
|
|
|
|
//
|
|
|
|
nsresult
|
2014-01-22 19:18:51 -08:00
|
|
|
nsXBLWindowKeyHandler::EnsureHandlers()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2013-04-14 11:27:33 -07:00
|
|
|
nsCOMPtr<Element> el = GetElement();
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_STATE(!mWeakPtrForElement || el);
|
|
|
|
if (el) {
|
|
|
|
// We are actually a XUL <keyset>.
|
|
|
|
if (mHandler)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> content(do_QueryInterface(el));
|
|
|
|
BuildHandlerChain(content, &mHandler);
|
|
|
|
} else { // We are an XBL file of handlers.
|
|
|
|
if (!sXBLSpecialDocInfo) {
|
2012-10-14 09:15:12 -07:00
|
|
|
sXBLSpecialDocInfo = new nsXBLSpecialDocInfo();
|
|
|
|
NS_ADDREF(sXBLSpecialDocInfo);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
sXBLSpecialDocInfo->LoadDocInfo();
|
|
|
|
|
|
|
|
// Now determine which handlers we should be using.
|
2014-01-22 19:18:51 -08:00
|
|
|
if (IsHTMLEditableFieldFocused()) {
|
2007-03-22 10:30:00 -07:00
|
|
|
sXBLSpecialDocInfo->GetAllHandlers("editor", &mHandler, &mUserHandler);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sXBLSpecialDocInfo->GetAllHandlers("browser", &mHandler, &mUserHandler);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2008-09-15 18:37:13 -07:00
|
|
|
nsXBLWindowKeyHandler::WalkHandlers(nsIDOMKeyEvent* aKeyEvent, nsIAtom* aEventType)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2011-09-28 23:19:26 -07:00
|
|
|
bool prevent;
|
2013-05-25 14:05:36 -07:00
|
|
|
aKeyEvent->GetDefaultPrevented(&prevent);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (prevent)
|
|
|
|
return NS_OK;
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool trustedEvent = false;
|
2012-08-04 00:44:00 -07:00
|
|
|
// Don't process the event if it was not dispatched from a trusted source
|
|
|
|
aKeyEvent->GetIsTrusted(&trustedEvent);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (!trustedEvent)
|
|
|
|
return NS_OK;
|
|
|
|
|
2014-01-22 19:18:51 -08:00
|
|
|
nsresult rv = EnsureHandlers();
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2013-04-14 11:27:33 -07:00
|
|
|
|
|
|
|
nsCOMPtr<Element> el = GetElement();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!el) {
|
|
|
|
if (mUserHandler) {
|
|
|
|
WalkHandlersInternal(aKeyEvent, aEventType, mUserHandler);
|
2013-05-25 14:05:36 -07:00
|
|
|
aKeyEvent->GetDefaultPrevented(&prevent);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (prevent)
|
|
|
|
return NS_OK; // Handled by the user bindings. Our work here is done.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-08-06 07:32:09 -07:00
|
|
|
nsCOMPtr<nsIContent> content = do_QueryInterface(el);
|
|
|
|
// skip keysets that are disabled
|
|
|
|
if (content && content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
|
|
|
|
nsGkAtoms::_true, eCaseMatters)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
WalkHandlersInternal(aKeyEvent, aEventType, mHandler);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-06-24 16:12:34 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsXBLWindowKeyHandler::HandleEvent(nsIDOMEvent* aEvent)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-09-15 18:37:13 -07:00
|
|
|
nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aEvent));
|
|
|
|
NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2011-06-24 16:12:34 -07:00
|
|
|
nsAutoString eventType;
|
|
|
|
aEvent->GetType(eventType);
|
|
|
|
nsCOMPtr<nsIAtom> eventTypeAtom = do_GetAtom(eventType);
|
|
|
|
NS_ENSURE_TRUE(eventTypeAtom, NS_ERROR_OUT_OF_MEMORY);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2013-01-24 08:38:59 -08:00
|
|
|
if (!mWeakPtrForElement) {
|
|
|
|
nsCOMPtr<mozilla::dom::Element> originalTarget =
|
|
|
|
do_QueryInterface(aEvent->GetInternalNSEvent()->originalTarget);
|
|
|
|
if (nsEventStateManager::IsRemoteTarget(originalTarget)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-24 16:12:34 -07:00
|
|
|
return WalkHandlers(keyEvent, eventTypeAtom);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// EventMatched
|
|
|
|
//
|
|
|
|
// See if the given handler cares about this particular key event
|
|
|
|
//
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2007-03-22 10:30:00 -07:00
|
|
|
nsXBLWindowKeyHandler::EventMatched(nsXBLPrototypeHandler* inHandler,
|
2008-09-15 18:37:13 -07:00
|
|
|
nsIAtom* inEventType,
|
|
|
|
nsIDOMKeyEvent* inEvent,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aCharCode, bool aIgnoreShiftKey)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2008-09-15 18:37:13 -07:00
|
|
|
return inHandler->KeyEventMatched(inEventType, inEvent, aCharCode,
|
|
|
|
aIgnoreShiftKey);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2014-01-22 19:18:51 -08:00
|
|
|
nsXBLWindowKeyHandler::IsHTMLEditableFieldFocused()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
if (!fm)
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
nsCOMPtr<nsIDOMWindow> focusedWindow;
|
|
|
|
fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!focusedWindow)
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsPIDOMWindow> piwin(do_QueryInterface(focusedWindow));
|
|
|
|
nsIDocShell *docShell = piwin->GetDocShell();
|
2014-01-22 19:18:51 -08:00
|
|
|
if (!docShell) {
|
|
|
|
return false;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2014-01-22 19:18:51 -08:00
|
|
|
nsCOMPtr<nsIEditor> editor;
|
|
|
|
docShell->GetEditor(getter_AddRefs(editor));
|
|
|
|
nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(editor);
|
|
|
|
if (!htmlEditor) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMElement> focusedElement;
|
|
|
|
fm->GetFocusedElement(getter_AddRefs(focusedElement));
|
|
|
|
nsCOMPtr<nsINode> focusedNode = do_QueryInterface(focusedElement);
|
|
|
|
if (focusedNode) {
|
|
|
|
// If there is a focused element, make sure it's in the active editing host.
|
|
|
|
// Note that GetActiveEditingHost finds the current editing host based on
|
|
|
|
// the document's selection. Even though the document selection is usually
|
|
|
|
// collapsed to where the focus is, but the page may modify the selection
|
|
|
|
// without our knowledge, in which case this check will do something useful.
|
|
|
|
nsCOMPtr<Element> activeEditingHost = htmlEditor->GetActiveEditingHost();
|
|
|
|
if (!activeEditingHost) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return nsContentUtils::ContentIsDescendantOf(focusedNode, activeEditingHost);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//
|
2008-04-14 21:16:24 -07:00
|
|
|
// WalkHandlersInternal and WalkHandlersAndExecute
|
2007-03-22 10:30:00 -07:00
|
|
|
//
|
|
|
|
// Given a particular DOM event and a pointer to the first handler in the list,
|
|
|
|
// scan through the list to find something to handle the event and then make it
|
|
|
|
// so.
|
|
|
|
//
|
|
|
|
nsresult
|
2008-09-15 18:37:13 -07:00
|
|
|
nsXBLWindowKeyHandler::WalkHandlersInternal(nsIDOMKeyEvent* aKeyEvent,
|
2007-03-22 10:30:00 -07:00
|
|
|
nsIAtom* aEventType,
|
|
|
|
nsXBLPrototypeHandler* aHandler)
|
2008-04-14 21:16:24 -07:00
|
|
|
{
|
|
|
|
nsAutoTArray<nsShortcutCandidate, 10> accessKeys;
|
2008-09-15 18:37:13 -07:00
|
|
|
nsContentUtils::GetAccelKeyCandidates(aKeyEvent, accessKeys);
|
2008-04-14 21:16:24 -07:00
|
|
|
|
|
|
|
if (accessKeys.IsEmpty()) {
|
2011-10-17 07:59:28 -07:00
|
|
|
WalkHandlersAndExecute(aKeyEvent, aEventType, aHandler, 0, false);
|
2008-04-14 21:16:24 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-08-22 08:56:38 -07:00
|
|
|
for (uint32_t i = 0; i < accessKeys.Length(); ++i) {
|
2008-04-14 21:16:24 -07:00
|
|
|
nsShortcutCandidate &key = accessKeys[i];
|
2008-09-15 18:37:13 -07:00
|
|
|
if (WalkHandlersAndExecute(aKeyEvent, aEventType, aHandler,
|
2008-04-14 21:16:24 -07:00
|
|
|
key.mCharCode, key.mIgnoreShift))
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-28 23:19:26 -07:00
|
|
|
bool
|
2008-09-15 18:37:13 -07:00
|
|
|
nsXBLWindowKeyHandler::WalkHandlersAndExecute(nsIDOMKeyEvent* aKeyEvent,
|
2008-04-14 21:16:24 -07:00
|
|
|
nsIAtom* aEventType,
|
|
|
|
nsXBLPrototypeHandler* aHandler,
|
2012-08-22 08:56:38 -07:00
|
|
|
uint32_t aCharCode,
|
2011-09-28 23:19:26 -07:00
|
|
|
bool aIgnoreShiftKey)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
nsresult rv;
|
2008-04-14 21:16:24 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Try all of the handlers until we find one that matches the event.
|
|
|
|
for (nsXBLPrototypeHandler *currHandler = aHandler; currHandler;
|
|
|
|
currHandler = currHandler->GetNextHandler()) {
|
2012-06-10 16:44:50 -07:00
|
|
|
bool stopped = aKeyEvent->IsDispatchStopped();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (stopped) {
|
|
|
|
// The event is finished, don't execute any more handlers
|
2012-08-07 08:11:35 -07:00
|
|
|
return false;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-09-15 18:37:13 -07:00
|
|
|
if (!EventMatched(currHandler, aEventType, aKeyEvent,
|
2008-04-14 21:16:24 -07:00
|
|
|
aCharCode, aIgnoreShiftKey))
|
2007-03-22 10:30:00 -07:00
|
|
|
continue; // try the next one
|
|
|
|
|
|
|
|
// Before executing this handler, check that it's not disabled,
|
|
|
|
// and that it has something to do (oncommand of the <key> or its
|
|
|
|
// <command> is non-empty).
|
|
|
|
nsCOMPtr<nsIContent> elt = currHandler->GetHandlerElement();
|
2013-04-14 11:27:33 -07:00
|
|
|
nsCOMPtr<Element> commandElt;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// See if we're in a XUL doc.
|
2013-04-14 11:27:33 -07:00
|
|
|
nsCOMPtr<Element> el = GetElement();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (el && elt) {
|
|
|
|
// We are. Obtain our command attribute.
|
|
|
|
nsAutoString command;
|
|
|
|
elt->GetAttr(kNameSpaceID_None, nsGkAtoms::command, command);
|
|
|
|
if (!command.IsEmpty()) {
|
|
|
|
// Locate the command element in question. Note that we
|
|
|
|
// know "elt" is in a doc if we're dealing with it here.
|
|
|
|
NS_ASSERTION(elt->IsInDoc(), "elt must be in document");
|
2010-06-23 14:35:57 -07:00
|
|
|
nsIDocument *doc = elt->GetCurrentDoc();
|
|
|
|
if (doc)
|
|
|
|
commandElt = do_QueryInterface(doc->GetElementById(command));
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (!commandElt) {
|
2010-06-17 13:28:38 -07:00
|
|
|
NS_ERROR("A XUL <key> is observing a command that doesn't exist. Unable to execute key binding!");
|
2007-03-22 10:30:00 -07:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!commandElt) {
|
|
|
|
commandElt = do_QueryInterface(elt);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (commandElt) {
|
|
|
|
nsAutoString value;
|
|
|
|
commandElt->GetAttribute(NS_LITERAL_STRING("disabled"), value);
|
|
|
|
if (value.EqualsLiteral("true")) {
|
|
|
|
continue; // this handler is disabled, try the next one
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that there is an oncommand handler
|
|
|
|
commandElt->GetAttribute(NS_LITERAL_STRING("oncommand"), value);
|
|
|
|
if (value.IsEmpty()) {
|
|
|
|
continue; // nothing to do
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-05 17:44:26 -07:00
|
|
|
nsCOMPtr<EventTarget> piTarget;
|
2013-04-14 11:27:33 -07:00
|
|
|
nsCOMPtr<Element> element = GetElement();
|
2007-03-22 10:30:00 -07:00
|
|
|
if (element) {
|
2013-04-14 11:27:33 -07:00
|
|
|
piTarget = commandElt;
|
2007-03-22 10:30:00 -07:00
|
|
|
} else {
|
2013-04-14 11:27:33 -07:00
|
|
|
piTarget = mTarget;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-09-15 18:37:13 -07:00
|
|
|
rv = currHandler->ExecuteHandler(piTarget, aKeyEvent);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2011-10-17 07:59:28 -07:00
|
|
|
return true;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 07:59:28 -07:00
|
|
|
return false;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2013-04-14 11:27:33 -07:00
|
|
|
already_AddRefed<Element>
|
2007-03-22 10:30:00 -07:00
|
|
|
nsXBLWindowKeyHandler::GetElement()
|
|
|
|
{
|
2013-04-14 11:27:33 -07:00
|
|
|
nsCOMPtr<Element> element = do_QueryReferent(mWeakPtrForElement);
|
|
|
|
return element.forget();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2013-04-14 11:27:33 -07:00
|
|
|
already_AddRefed<nsXBLWindowKeyHandler>
|
|
|
|
NS_NewXBLWindowKeyHandler(nsIDOMElement* aElement, EventTarget* aTarget)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2013-04-14 11:27:33 -07:00
|
|
|
nsRefPtr<nsXBLWindowKeyHandler> result =
|
|
|
|
new nsXBLWindowKeyHandler(aElement, aTarget);
|
|
|
|
return result.forget();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|