nsXBLEventHandler.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsCOMPtr.h"
  6. #include "nsIAtom.h"
  7. #include "nsIDOMEventListener.h"
  8. #include "nsIDOMKeyEvent.h"
  9. #include "nsIDOMMouseEvent.h"
  10. #include "nsXBLPrototypeHandler.h"
  11. #include "nsContentUtils.h"
  12. #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
  13. #include "mozilla/dom/EventTarget.h"
  14. #include "mozilla/TextEvents.h"
  15. using namespace mozilla;
  16. using namespace mozilla::dom;
  17. nsXBLEventHandler::nsXBLEventHandler(nsXBLPrototypeHandler* aHandler)
  18. : mProtoHandler(aHandler)
  19. {
  20. }
  21. nsXBLEventHandler::~nsXBLEventHandler()
  22. {
  23. }
  24. NS_IMPL_ISUPPORTS(nsXBLEventHandler, nsIDOMEventListener)
  25. NS_IMETHODIMP
  26. nsXBLEventHandler::HandleEvent(nsIDOMEvent* aEvent)
  27. {
  28. if (!mProtoHandler)
  29. return NS_ERROR_FAILURE;
  30. uint8_t phase = mProtoHandler->GetPhase();
  31. if (phase == NS_PHASE_TARGET) {
  32. uint16_t eventPhase;
  33. aEvent->GetEventPhase(&eventPhase);
  34. if (eventPhase != nsIDOMEvent::AT_TARGET)
  35. return NS_OK;
  36. }
  37. if (!EventMatched(aEvent))
  38. return NS_OK;
  39. mProtoHandler->ExecuteHandler(aEvent->InternalDOMEvent()->GetCurrentTarget(),
  40. aEvent);
  41. return NS_OK;
  42. }
  43. nsXBLMouseEventHandler::nsXBLMouseEventHandler(nsXBLPrototypeHandler* aHandler)
  44. : nsXBLEventHandler(aHandler)
  45. {
  46. }
  47. nsXBLMouseEventHandler::~nsXBLMouseEventHandler()
  48. {
  49. }
  50. bool
  51. nsXBLMouseEventHandler::EventMatched(nsIDOMEvent* aEvent)
  52. {
  53. nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
  54. return mouse && mProtoHandler->MouseEventMatched(mouse);
  55. }
  56. nsXBLKeyEventHandler::nsXBLKeyEventHandler(nsIAtom* aEventType, uint8_t aPhase,
  57. uint8_t aType)
  58. : mEventType(aEventType),
  59. mPhase(aPhase),
  60. mType(aType),
  61. mIsBoundToChrome(false),
  62. mUsingContentXBLScope(false)
  63. {
  64. }
  65. nsXBLKeyEventHandler::~nsXBLKeyEventHandler()
  66. {
  67. }
  68. NS_IMPL_ISUPPORTS(nsXBLKeyEventHandler, nsIDOMEventListener)
  69. bool
  70. nsXBLKeyEventHandler::ExecuteMatchedHandlers(
  71. nsIDOMKeyEvent* aKeyEvent,
  72. uint32_t aCharCode,
  73. const IgnoreModifierState& aIgnoreModifierState)
  74. {
  75. WidgetEvent* event = aKeyEvent->AsEvent()->WidgetEventPtr();
  76. nsCOMPtr<EventTarget> target = aKeyEvent->AsEvent()->InternalDOMEvent()->GetCurrentTarget();
  77. bool executed = false;
  78. for (uint32_t i = 0; i < mProtoHandlers.Length(); ++i) {
  79. nsXBLPrototypeHandler* handler = mProtoHandlers[i];
  80. bool hasAllowUntrustedAttr = handler->HasAllowUntrustedAttr();
  81. if ((event->IsTrusted() ||
  82. (hasAllowUntrustedAttr && handler->AllowUntrustedEvents()) ||
  83. (!hasAllowUntrustedAttr && !mIsBoundToChrome && !mUsingContentXBLScope)) &&
  84. handler->KeyEventMatched(aKeyEvent, aCharCode, aIgnoreModifierState)) {
  85. handler->ExecuteHandler(target, aKeyEvent->AsEvent());
  86. executed = true;
  87. }
  88. }
  89. #ifdef XP_WIN
  90. // Windows native applications ignore Windows-Logo key state when checking
  91. // shortcut keys even if the key is pressed. Therefore, if there is no
  92. // shortcut key which exactly matches current modifier state, we should
  93. // retry to look for a shortcut key without the Windows-Logo key press.
  94. if (!executed && !aIgnoreModifierState.mOS) {
  95. WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent();
  96. if (keyEvent && keyEvent->IsOS()) {
  97. IgnoreModifierState ignoreModifierState(aIgnoreModifierState);
  98. ignoreModifierState.mOS = true;
  99. return ExecuteMatchedHandlers(aKeyEvent, aCharCode, ignoreModifierState);
  100. }
  101. }
  102. #endif
  103. return executed;
  104. }
  105. NS_IMETHODIMP
  106. nsXBLKeyEventHandler::HandleEvent(nsIDOMEvent* aEvent)
  107. {
  108. uint32_t count = mProtoHandlers.Length();
  109. if (count == 0)
  110. return NS_ERROR_FAILURE;
  111. if (mPhase == NS_PHASE_TARGET) {
  112. uint16_t eventPhase;
  113. aEvent->GetEventPhase(&eventPhase);
  114. if (eventPhase != nsIDOMEvent::AT_TARGET)
  115. return NS_OK;
  116. }
  117. nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
  118. if (!key)
  119. return NS_OK;
  120. WidgetKeyboardEvent* nativeKeyboardEvent =
  121. aEvent->WidgetEventPtr()->AsKeyboardEvent();
  122. MOZ_ASSERT(nativeKeyboardEvent);
  123. AutoShortcutKeyCandidateArray shortcutKeys;
  124. nativeKeyboardEvent->GetShortcutKeyCandidates(shortcutKeys);
  125. if (shortcutKeys.IsEmpty()) {
  126. ExecuteMatchedHandlers(key, 0, IgnoreModifierState());
  127. return NS_OK;
  128. }
  129. for (uint32_t i = 0; i < shortcutKeys.Length(); ++i) {
  130. IgnoreModifierState ignoreModifierState;
  131. ignoreModifierState.mShift = shortcutKeys[i].mIgnoreShift;
  132. if (ExecuteMatchedHandlers(key, shortcutKeys[i].mCharCode,
  133. ignoreModifierState)) {
  134. return NS_OK;
  135. }
  136. }
  137. return NS_OK;
  138. }
  139. ///////////////////////////////////////////////////////////////////////////////////
  140. already_AddRefed<nsXBLEventHandler>
  141. NS_NewXBLEventHandler(nsXBLPrototypeHandler* aHandler,
  142. nsIAtom* aEventType)
  143. {
  144. RefPtr<nsXBLEventHandler> handler;
  145. switch (nsContentUtils::GetEventClassID(nsDependentAtomString(aEventType))) {
  146. case eDragEventClass:
  147. case eMouseEventClass:
  148. case eMouseScrollEventClass:
  149. case eWheelEventClass:
  150. case eSimpleGestureEventClass:
  151. handler = new nsXBLMouseEventHandler(aHandler);
  152. break;
  153. default:
  154. handler = new nsXBLEventHandler(aHandler);
  155. break;
  156. }
  157. return handler.forget();
  158. }