Line data Source code
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 "nsCOMPtr.h"
8 : #include "nsIAtom.h"
9 : #include "nsIDOMEventListener.h"
10 : #include "nsIDOMKeyEvent.h"
11 : #include "nsIDOMMouseEvent.h"
12 : #include "nsXBLPrototypeHandler.h"
13 : #include "nsContentUtils.h"
14 : #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
15 : #include "mozilla/dom/EventTarget.h"
16 : #include "mozilla/TextEvents.h"
17 :
18 : using namespace mozilla;
19 : using namespace mozilla::dom;
20 :
21 133 : nsXBLEventHandler::nsXBLEventHandler(nsXBLPrototypeHandler* aHandler)
22 133 : : mProtoHandler(aHandler)
23 : {
24 133 : }
25 :
26 0 : nsXBLEventHandler::~nsXBLEventHandler()
27 : {
28 0 : }
29 :
30 1030 : NS_IMPL_ISUPPORTS(nsXBLEventHandler, nsIDOMEventListener)
31 :
32 : NS_IMETHODIMP
33 6 : nsXBLEventHandler::HandleEvent(nsIDOMEvent* aEvent)
34 : {
35 6 : if (!mProtoHandler)
36 0 : return NS_ERROR_FAILURE;
37 :
38 6 : uint8_t phase = mProtoHandler->GetPhase();
39 6 : if (phase == NS_PHASE_TARGET) {
40 : uint16_t eventPhase;
41 0 : aEvent->GetEventPhase(&eventPhase);
42 0 : if (eventPhase != nsIDOMEvent::AT_TARGET)
43 0 : return NS_OK;
44 : }
45 :
46 6 : if (!EventMatched(aEvent))
47 0 : return NS_OK;
48 :
49 6 : mProtoHandler->ExecuteHandler(aEvent->InternalDOMEvent()->GetCurrentTarget(),
50 6 : aEvent);
51 :
52 6 : return NS_OK;
53 : }
54 :
55 56 : nsXBLMouseEventHandler::nsXBLMouseEventHandler(nsXBLPrototypeHandler* aHandler)
56 56 : : nsXBLEventHandler(aHandler)
57 : {
58 56 : }
59 :
60 0 : nsXBLMouseEventHandler::~nsXBLMouseEventHandler()
61 : {
62 0 : }
63 :
64 : bool
65 0 : nsXBLMouseEventHandler::EventMatched(nsIDOMEvent* aEvent)
66 : {
67 0 : nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
68 0 : return mouse && mProtoHandler->MouseEventMatched(mouse);
69 : }
70 :
71 10 : nsXBLKeyEventHandler::nsXBLKeyEventHandler(nsIAtom* aEventType, uint8_t aPhase,
72 10 : uint8_t aType)
73 : : mEventType(aEventType),
74 : mPhase(aPhase),
75 : mType(aType),
76 : mIsBoundToChrome(false),
77 10 : mUsingContentXBLScope(false)
78 : {
79 10 : }
80 :
81 0 : nsXBLKeyEventHandler::~nsXBLKeyEventHandler()
82 : {
83 0 : }
84 :
85 133 : NS_IMPL_ISUPPORTS(nsXBLKeyEventHandler, nsIDOMEventListener)
86 :
87 : bool
88 0 : nsXBLKeyEventHandler::ExecuteMatchedHandlers(
89 : nsIDOMKeyEvent* aKeyEvent,
90 : uint32_t aCharCode,
91 : const IgnoreModifierState& aIgnoreModifierState)
92 : {
93 0 : WidgetEvent* event = aKeyEvent->AsEvent()->WidgetEventPtr();
94 0 : nsCOMPtr<EventTarget> target = aKeyEvent->AsEvent()->InternalDOMEvent()->GetCurrentTarget();
95 :
96 0 : bool executed = false;
97 0 : for (uint32_t i = 0; i < mProtoHandlers.Length(); ++i) {
98 0 : nsXBLPrototypeHandler* handler = mProtoHandlers[i];
99 0 : bool hasAllowUntrustedAttr = handler->HasAllowUntrustedAttr();
100 0 : if ((event->IsTrusted() ||
101 0 : (hasAllowUntrustedAttr && handler->AllowUntrustedEvents()) ||
102 0 : (!hasAllowUntrustedAttr && !mIsBoundToChrome && !mUsingContentXBLScope)) &&
103 0 : handler->KeyEventMatched(aKeyEvent, aCharCode, aIgnoreModifierState)) {
104 0 : handler->ExecuteHandler(target, aKeyEvent->AsEvent());
105 0 : executed = true;
106 : }
107 : }
108 : #ifdef XP_WIN
109 : // Windows native applications ignore Windows-Logo key state when checking
110 : // shortcut keys even if the key is pressed. Therefore, if there is no
111 : // shortcut key which exactly matches current modifier state, we should
112 : // retry to look for a shortcut key without the Windows-Logo key press.
113 : if (!executed && !aIgnoreModifierState.mOS) {
114 : WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent();
115 : if (keyEvent && keyEvent->IsOS()) {
116 : IgnoreModifierState ignoreModifierState(aIgnoreModifierState);
117 : ignoreModifierState.mOS = true;
118 : return ExecuteMatchedHandlers(aKeyEvent, aCharCode, ignoreModifierState);
119 : }
120 : }
121 : #endif
122 0 : return executed;
123 : }
124 :
125 : NS_IMETHODIMP
126 0 : nsXBLKeyEventHandler::HandleEvent(nsIDOMEvent* aEvent)
127 : {
128 0 : uint32_t count = mProtoHandlers.Length();
129 0 : if (count == 0)
130 0 : return NS_ERROR_FAILURE;
131 :
132 0 : if (mPhase == NS_PHASE_TARGET) {
133 : uint16_t eventPhase;
134 0 : aEvent->GetEventPhase(&eventPhase);
135 0 : if (eventPhase != nsIDOMEvent::AT_TARGET)
136 0 : return NS_OK;
137 : }
138 :
139 0 : nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
140 0 : if (!key)
141 0 : return NS_OK;
142 :
143 : WidgetKeyboardEvent* nativeKeyboardEvent =
144 0 : aEvent->WidgetEventPtr()->AsKeyboardEvent();
145 0 : MOZ_ASSERT(nativeKeyboardEvent);
146 0 : AutoShortcutKeyCandidateArray shortcutKeys;
147 0 : nativeKeyboardEvent->GetShortcutKeyCandidates(shortcutKeys);
148 :
149 0 : if (shortcutKeys.IsEmpty()) {
150 0 : ExecuteMatchedHandlers(key, 0, IgnoreModifierState());
151 0 : return NS_OK;
152 : }
153 :
154 0 : for (uint32_t i = 0; i < shortcutKeys.Length(); ++i) {
155 0 : IgnoreModifierState ignoreModifierState;
156 0 : ignoreModifierState.mShift = shortcutKeys[i].mIgnoreShift;
157 0 : if (ExecuteMatchedHandlers(key, shortcutKeys[i].mCharCode,
158 : ignoreModifierState)) {
159 0 : return NS_OK;
160 : }
161 : }
162 0 : return NS_OK;
163 : }
164 :
165 : ///////////////////////////////////////////////////////////////////////////////////
166 :
167 : already_AddRefed<nsXBLEventHandler>
168 133 : NS_NewXBLEventHandler(nsXBLPrototypeHandler* aHandler,
169 : nsIAtom* aEventType)
170 : {
171 266 : RefPtr<nsXBLEventHandler> handler;
172 :
173 133 : switch (nsContentUtils::GetEventClassID(nsDependentAtomString(aEventType))) {
174 : case eDragEventClass:
175 : case eMouseEventClass:
176 : case eMouseScrollEventClass:
177 : case eWheelEventClass:
178 : case eSimpleGestureEventClass:
179 56 : handler = new nsXBLMouseEventHandler(aHandler);
180 56 : break;
181 : default:
182 77 : handler = new nsXBLEventHandler(aHandler);
183 77 : break;
184 : }
185 :
186 266 : return handler.forget();
187 : }
|