michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIAtom.h" michael@0: #include "nsIDOMEventListener.h" michael@0: #include "nsIDOMKeyEvent.h" michael@0: #include "nsIDOMMouseEvent.h" michael@0: #include "nsXBLPrototypeHandler.h" michael@0: #include "nsContentUtils.h" michael@0: #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent() michael@0: #include "mozilla/dom/EventTarget.h" michael@0: michael@0: using namespace mozilla::dom; michael@0: michael@0: nsXBLEventHandler::nsXBLEventHandler(nsXBLPrototypeHandler* aHandler) michael@0: : mProtoHandler(aHandler) michael@0: { michael@0: } michael@0: michael@0: nsXBLEventHandler::~nsXBLEventHandler() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsXBLEventHandler, nsIDOMEventListener) michael@0: michael@0: NS_IMETHODIMP michael@0: nsXBLEventHandler::HandleEvent(nsIDOMEvent* aEvent) michael@0: { michael@0: if (!mProtoHandler) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: uint8_t phase = mProtoHandler->GetPhase(); michael@0: if (phase == NS_PHASE_TARGET) { michael@0: uint16_t eventPhase; michael@0: aEvent->GetEventPhase(&eventPhase); michael@0: if (eventPhase != nsIDOMEvent::AT_TARGET) michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (!EventMatched(aEvent)) michael@0: return NS_OK; michael@0: michael@0: mProtoHandler->ExecuteHandler(aEvent->InternalDOMEvent()->GetCurrentTarget(), michael@0: aEvent); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsXBLMouseEventHandler::nsXBLMouseEventHandler(nsXBLPrototypeHandler* aHandler) michael@0: : nsXBLEventHandler(aHandler) michael@0: { michael@0: } michael@0: michael@0: nsXBLMouseEventHandler::~nsXBLMouseEventHandler() michael@0: { michael@0: } michael@0: michael@0: bool michael@0: nsXBLMouseEventHandler::EventMatched(nsIDOMEvent* aEvent) michael@0: { michael@0: nsCOMPtr mouse(do_QueryInterface(aEvent)); michael@0: return mouse && mProtoHandler->MouseEventMatched(mouse); michael@0: } michael@0: michael@0: nsXBLKeyEventHandler::nsXBLKeyEventHandler(nsIAtom* aEventType, uint8_t aPhase, michael@0: uint8_t aType) michael@0: : mEventType(aEventType), michael@0: mPhase(aPhase), michael@0: mType(aType), michael@0: mIsBoundToChrome(false), michael@0: mUsingXBLScope(false) michael@0: { michael@0: } michael@0: michael@0: nsXBLKeyEventHandler::~nsXBLKeyEventHandler() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsXBLKeyEventHandler, nsIDOMEventListener) michael@0: michael@0: bool michael@0: nsXBLKeyEventHandler::ExecuteMatchedHandlers(nsIDOMKeyEvent* aKeyEvent, michael@0: uint32_t aCharCode, michael@0: bool aIgnoreShiftKey) michael@0: { michael@0: bool trustedEvent = false; michael@0: aKeyEvent->GetIsTrusted(&trustedEvent); michael@0: michael@0: nsCOMPtr target = aKeyEvent->InternalDOMEvent()->GetCurrentTarget(); michael@0: michael@0: bool executed = false; michael@0: for (uint32_t i = 0; i < mProtoHandlers.Length(); ++i) { michael@0: nsXBLPrototypeHandler* handler = mProtoHandlers[i]; michael@0: bool hasAllowUntrustedAttr = handler->HasAllowUntrustedAttr(); michael@0: if ((trustedEvent || michael@0: (hasAllowUntrustedAttr && handler->AllowUntrustedEvents()) || michael@0: (!hasAllowUntrustedAttr && !mIsBoundToChrome && !mUsingXBLScope)) && michael@0: handler->KeyEventMatched(aKeyEvent, aCharCode, aIgnoreShiftKey)) { michael@0: handler->ExecuteHandler(target, aKeyEvent); michael@0: executed = true; michael@0: } michael@0: } michael@0: return executed; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsXBLKeyEventHandler::HandleEvent(nsIDOMEvent* aEvent) michael@0: { michael@0: uint32_t count = mProtoHandlers.Length(); michael@0: if (count == 0) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: if (mPhase == NS_PHASE_TARGET) { michael@0: uint16_t eventPhase; michael@0: aEvent->GetEventPhase(&eventPhase); michael@0: if (eventPhase != nsIDOMEvent::AT_TARGET) michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsCOMPtr key(do_QueryInterface(aEvent)); michael@0: if (!key) michael@0: return NS_OK; michael@0: michael@0: nsAutoTArray accessKeys; michael@0: nsContentUtils::GetAccelKeyCandidates(key, accessKeys); michael@0: michael@0: if (accessKeys.IsEmpty()) { michael@0: ExecuteMatchedHandlers(key, 0, false); michael@0: return NS_OK; michael@0: } michael@0: michael@0: for (uint32_t i = 0; i < accessKeys.Length(); ++i) { michael@0: if (ExecuteMatchedHandlers(key, accessKeys[i].mCharCode, michael@0: accessKeys[i].mIgnoreShift)) michael@0: return NS_OK; michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: nsresult michael@0: NS_NewXBLEventHandler(nsXBLPrototypeHandler* aHandler, michael@0: nsIAtom* aEventType, michael@0: nsXBLEventHandler** aResult) michael@0: { michael@0: switch (nsContentUtils::GetEventCategory(nsDependentAtomString(aEventType))) { michael@0: case NS_DRAG_EVENT: michael@0: case NS_MOUSE_EVENT: michael@0: case NS_MOUSE_SCROLL_EVENT: michael@0: case NS_WHEEL_EVENT: michael@0: case NS_SIMPLE_GESTURE_EVENT: michael@0: *aResult = new nsXBLMouseEventHandler(aHandler); michael@0: break; michael@0: default: michael@0: *aResult = new nsXBLEventHandler(aHandler); michael@0: break; michael@0: } michael@0: michael@0: if (!*aResult) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: NS_ADDREF(*aResult); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: NS_NewXBLKeyEventHandler(nsIAtom* aEventType, uint8_t aPhase, uint8_t aType, michael@0: nsXBLKeyEventHandler** aResult) michael@0: { michael@0: *aResult = new nsXBLKeyEventHandler(aEventType, aPhase, aType); michael@0: michael@0: if (!*aResult) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: NS_ADDREF(*aResult); michael@0: michael@0: return NS_OK; michael@0: }