Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 *
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/. */
7 #include "nsPrintPreviewListener.h"
9 #include "mozilla/TextEvents.h"
10 #include "mozilla/dom/Element.h"
11 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
12 #include "nsIDOMWindow.h"
13 #include "nsPIDOMWindow.h"
14 #include "nsIDOMElement.h"
15 #include "nsIDOMKeyEvent.h"
16 #include "nsIDOMEvent.h"
17 #include "nsIDocument.h"
18 #include "nsIDocShell.h"
19 #include "nsPresContext.h"
20 #include "nsFocusManager.h"
21 #include "nsLiteralString.h"
23 using namespace mozilla;
24 using namespace mozilla::dom;
26 NS_IMPL_ISUPPORTS(nsPrintPreviewListener, nsIDOMEventListener)
29 //
30 // nsPrintPreviewListener ctor
31 //
32 nsPrintPreviewListener::nsPrintPreviewListener(EventTarget* aTarget)
33 : mEventTarget(aTarget)
34 {
35 NS_ADDREF_THIS();
36 } // ctor
38 nsPrintPreviewListener::~nsPrintPreviewListener()
39 {
40 }
42 //-------------------------------------------------------
43 //
44 // AddListeners
45 //
46 // Subscribe to the events that will allow us to track various events.
47 //
48 nsresult
49 nsPrintPreviewListener::AddListeners()
50 {
51 if (mEventTarget) {
52 mEventTarget->AddEventListener(NS_LITERAL_STRING("click"), this, true);
53 mEventTarget->AddEventListener(NS_LITERAL_STRING("contextmenu"), this, true);
54 mEventTarget->AddEventListener(NS_LITERAL_STRING("keydown"), this, true);
55 mEventTarget->AddEventListener(NS_LITERAL_STRING("keypress"), this, true);
56 mEventTarget->AddEventListener(NS_LITERAL_STRING("keyup"), this, true);
57 mEventTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), this, true);
58 mEventTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), this, true);
59 mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), this, true);
60 mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseover"), this, true);
61 mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseup"), this, true);
63 mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("keydown"),
64 this, true);
65 }
67 return NS_OK;
68 }
71 //-------------------------------------------------------
72 //
73 // RemoveListeners
74 //
75 // Unsubscribe from all the various events that we were listening to.
76 //
77 nsresult
78 nsPrintPreviewListener::RemoveListeners()
79 {
80 if (mEventTarget) {
81 mEventTarget->RemoveEventListener(NS_LITERAL_STRING("click"), this, true);
82 mEventTarget->RemoveEventListener(NS_LITERAL_STRING("contextmenu"), this, true);
83 mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true);
84 mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true);
85 mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keyup"), this, true);
86 mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, true);
87 mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, true);
88 mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, true);
89 mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseover"), this, true);
90 mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, true);
92 mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"),
93 this, true);
94 }
96 return NS_OK;
97 }
99 //-------------------------------------------------------
100 //
101 // GetActionForEvent
102 //
103 // Helper function to let certain key events through
104 //
105 enum eEventAction {
106 eEventAction_Tab, eEventAction_ShiftTab,
107 eEventAction_Propagate, eEventAction_Suppress,
108 eEventAction_StopPropagation
109 };
111 static eEventAction
112 GetActionForEvent(nsIDOMEvent* aEvent)
113 {
114 WidgetKeyboardEvent* keyEvent =
115 aEvent->GetInternalNSEvent()->AsKeyboardEvent();
116 if (!keyEvent) {
117 return eEventAction_Suppress;
118 }
120 if (keyEvent->mFlags.mInSystemGroup) {
121 NS_ASSERTION(keyEvent->message == NS_KEY_DOWN,
122 "Assuming we're listening only keydown event in system group");
123 return eEventAction_StopPropagation;
124 }
126 if (keyEvent->IsAlt() || keyEvent->IsControl() || keyEvent->IsMeta()) {
127 // Don't consume keydown event because following keypress event may be
128 // handled as access key or shortcut key.
129 return (keyEvent->message == NS_KEY_DOWN) ? eEventAction_StopPropagation :
130 eEventAction_Suppress;
131 }
133 static const uint32_t kOKKeyCodes[] = {
134 nsIDOMKeyEvent::DOM_VK_PAGE_UP, nsIDOMKeyEvent::DOM_VK_PAGE_DOWN,
135 nsIDOMKeyEvent::DOM_VK_UP, nsIDOMKeyEvent::DOM_VK_DOWN,
136 nsIDOMKeyEvent::DOM_VK_HOME, nsIDOMKeyEvent::DOM_VK_END
137 };
139 if (keyEvent->keyCode == nsIDOMKeyEvent::DOM_VK_TAB) {
140 return keyEvent->IsShift() ? eEventAction_ShiftTab : eEventAction_Tab;
141 }
143 if (keyEvent->charCode == ' ' || keyEvent->keyCode == NS_VK_SPACE) {
144 return eEventAction_Propagate;
145 }
147 if (keyEvent->IsShift()) {
148 return eEventAction_Suppress;
149 }
151 for (uint32_t i = 0; i < ArrayLength(kOKKeyCodes); ++i) {
152 if (keyEvent->keyCode == kOKKeyCodes[i]) {
153 return eEventAction_Propagate;
154 }
155 }
157 return eEventAction_Suppress;
158 }
160 NS_IMETHODIMP
161 nsPrintPreviewListener::HandleEvent(nsIDOMEvent* aEvent)
162 {
163 nsCOMPtr<nsIContent> content = do_QueryInterface(
164 aEvent ? aEvent->InternalDOMEvent()->GetOriginalTarget() : nullptr);
165 if (content && !content->IsXUL()) {
166 eEventAction action = ::GetActionForEvent(aEvent);
167 switch (action) {
168 case eEventAction_Tab:
169 case eEventAction_ShiftTab:
170 {
171 nsAutoString eventString;
172 aEvent->GetType(eventString);
173 if (eventString == NS_LITERAL_STRING("keydown")) {
174 // Handle tabbing explicitly here since we don't want focus ending up
175 // inside the content document, bug 244128.
176 nsIDocument* doc = content->GetCurrentDoc();
177 NS_ASSERTION(doc, "no document");
179 nsIDocument* parentDoc = doc->GetParentDocument();
180 NS_ASSERTION(parentDoc, "no parent document");
182 nsCOMPtr<nsIDOMWindow> win = do_QueryInterface(parentDoc->GetWindow());
184 nsIFocusManager* fm = nsFocusManager::GetFocusManager();
185 if (fm && win) {
186 dom::Element* fromElement = parentDoc->FindContentForSubDocument(doc);
187 nsCOMPtr<nsIDOMElement> from = do_QueryInterface(fromElement);
189 bool forward = (action == eEventAction_Tab);
190 nsCOMPtr<nsIDOMElement> result;
191 fm->MoveFocus(win, from,
192 forward ? nsIFocusManager::MOVEFOCUS_FORWARD :
193 nsIFocusManager::MOVEFOCUS_BACKWARD,
194 nsIFocusManager::FLAG_BYKEY, getter_AddRefs(result));
195 }
196 }
197 }
198 // fall-through
199 case eEventAction_Suppress:
200 aEvent->StopPropagation();
201 aEvent->PreventDefault();
202 break;
203 case eEventAction_StopPropagation:
204 aEvent->StopPropagation();
205 break;
206 case eEventAction_Propagate:
207 // intentionally empty
208 break;
209 }
210 }
211 return NS_OK;
212 }