1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Original Author: David W. Hyatt (hyatt@netscape.com)
24 : * - Mike Pinkerton (pinkerton@netscape.com)
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsCOMPtr.h"
41 : #include "nsXBLPrototypeHandler.h"
42 : #include "nsXBLWindowKeyHandler.h"
43 : #include "nsIContent.h"
44 : #include "nsIAtom.h"
45 : #include "nsIDOMKeyEvent.h"
46 : #include "nsIDOMEventTarget.h"
47 : #include "nsIDOMNSEvent.h"
48 : #include "nsXBLService.h"
49 : #include "nsIServiceManager.h"
50 : #include "nsGkAtoms.h"
51 : #include "nsXBLDocumentInfo.h"
52 : #include "nsIDOMElement.h"
53 : #include "nsINativeKeyBindings.h"
54 : #include "nsIController.h"
55 : #include "nsIControllers.h"
56 : #include "nsFocusManager.h"
57 : #include "nsPIWindowRoot.h"
58 : #include "nsIURI.h"
59 : #include "nsNetUtil.h"
60 : #include "nsContentUtils.h"
61 : #include "nsXBLPrototypeBinding.h"
62 : #include "nsIDOMDocument.h"
63 : #include "nsPIWindowRoot.h"
64 : #include "nsPIDOMWindow.h"
65 : #include "nsIDocShell.h"
66 : #include "nsIPresShell.h"
67 : #include "nsIPrivateDOMEvent.h"
68 : #include "nsISelectionController.h"
69 : #include "nsGUIEvent.h"
70 : #include "mozilla/Preferences.h"
71 : #include "mozilla/dom/Element.h"
72 :
73 : using namespace mozilla;
74 :
75 : static nsINativeKeyBindings *sNativeEditorBindings = nsnull;
76 :
77 : class nsXBLSpecialDocInfo
78 0 : {
79 : public:
80 : nsRefPtr<nsXBLDocumentInfo> mHTMLBindings;
81 : nsRefPtr<nsXBLDocumentInfo> mUserHTMLBindings;
82 :
83 : static const char sHTMLBindingStr[];
84 : static const char sUserHTMLBindingStr[];
85 :
86 : bool mInitialized;
87 :
88 : public:
89 : void LoadDocInfo();
90 : void GetAllHandlers(const char* aType,
91 : nsXBLPrototypeHandler** handler,
92 : nsXBLPrototypeHandler** userHandler);
93 : void GetHandlers(nsXBLDocumentInfo* aInfo,
94 : const nsACString& aRef,
95 : nsXBLPrototypeHandler** aResult);
96 :
97 0 : nsXBLSpecialDocInfo() : mInitialized(false) {}
98 : };
99 :
100 : const char nsXBLSpecialDocInfo::sHTMLBindingStr[] =
101 : "chrome://global/content/platformHTMLBindings.xml";
102 :
103 0 : void nsXBLSpecialDocInfo::LoadDocInfo()
104 : {
105 0 : if (mInitialized)
106 0 : return;
107 0 : mInitialized = true;
108 :
109 : nsresult rv;
110 : nsCOMPtr<nsIXBLService> xblService =
111 0 : do_GetService("@mozilla.org/xbl;1", &rv);
112 0 : if (NS_FAILED(rv) || !xblService)
113 : return;
114 :
115 : // Obtain the platform doc info
116 0 : nsCOMPtr<nsIURI> bindingURI;
117 0 : NS_NewURI(getter_AddRefs(bindingURI), sHTMLBindingStr);
118 0 : if (!bindingURI) {
119 : return;
120 : }
121 0 : xblService->LoadBindingDocumentInfo(nsnull, nsnull,
122 : bindingURI,
123 : nsnull,
124 : true,
125 0 : getter_AddRefs(mHTMLBindings));
126 :
127 : const nsAdoptingCString& userHTMLBindingStr =
128 0 : Preferences::GetCString("dom.userHTMLBindings.uri");
129 0 : if (!userHTMLBindingStr.IsEmpty()) {
130 0 : NS_NewURI(getter_AddRefs(bindingURI), userHTMLBindingStr);
131 0 : if (!bindingURI) {
132 : return;
133 : }
134 :
135 0 : xblService->LoadBindingDocumentInfo(nsnull, nsnull,
136 : bindingURI,
137 : nsnull,
138 : true,
139 0 : getter_AddRefs(mUserHTMLBindings));
140 : }
141 : }
142 :
143 : //
144 : // GetHandlers
145 : //
146 : //
147 : void
148 0 : nsXBLSpecialDocInfo::GetHandlers(nsXBLDocumentInfo* aInfo,
149 : const nsACString& aRef,
150 : nsXBLPrototypeHandler** aResult)
151 : {
152 0 : nsXBLPrototypeBinding* binding = aInfo->GetPrototypeBinding(aRef);
153 :
154 0 : NS_ASSERTION(binding, "No binding found for the XBL window key handler.");
155 0 : if (!binding)
156 0 : return;
157 :
158 0 : *aResult = binding->GetPrototypeHandlers();
159 : }
160 :
161 : void
162 0 : nsXBLSpecialDocInfo::GetAllHandlers(const char* aType,
163 : nsXBLPrototypeHandler** aHandler,
164 : nsXBLPrototypeHandler** aUserHandler)
165 : {
166 0 : if (mUserHTMLBindings) {
167 0 : nsCAutoString type(aType);
168 0 : type.Append("User");
169 0 : GetHandlers(mUserHTMLBindings, type, aUserHandler);
170 : }
171 0 : if (mHTMLBindings) {
172 0 : GetHandlers(mHTMLBindings, nsDependentCString(aType), aHandler);
173 : }
174 0 : }
175 :
176 : // Init statics
177 : nsXBLSpecialDocInfo* nsXBLWindowKeyHandler::sXBLSpecialDocInfo = nsnull;
178 : PRUint32 nsXBLWindowKeyHandler::sRefCnt = 0;
179 :
180 0 : nsXBLWindowKeyHandler::nsXBLWindowKeyHandler(nsIDOMElement* aElement,
181 : nsIDOMEventTarget* aTarget)
182 : : mTarget(aTarget),
183 : mHandler(nsnull),
184 0 : mUserHandler(nsnull)
185 : {
186 0 : mWeakPtrForElement = do_GetWeakReference(aElement);
187 0 : ++sRefCnt;
188 0 : }
189 :
190 0 : nsXBLWindowKeyHandler::~nsXBLWindowKeyHandler()
191 : {
192 : // If mWeakPtrForElement is non-null, we created a prototype handler.
193 0 : if (mWeakPtrForElement)
194 0 : delete mHandler;
195 :
196 0 : --sRefCnt;
197 0 : if (!sRefCnt) {
198 0 : delete sXBLSpecialDocInfo;
199 0 : sXBLSpecialDocInfo = nsnull;
200 : }
201 0 : }
202 :
203 0 : NS_IMPL_ISUPPORTS1(nsXBLWindowKeyHandler,
204 : nsIDOMEventListener)
205 :
206 : static void
207 0 : BuildHandlerChain(nsIContent* aContent, nsXBLPrototypeHandler** aResult)
208 : {
209 0 : *aResult = nsnull;
210 :
211 : // Since we chain each handler onto the next handler,
212 : // we'll enumerate them here in reverse so that when we
213 : // walk the chain they'll come out in the original order
214 0 : for (nsIContent* key = aContent->GetLastChild();
215 : key;
216 0 : key = key->GetPreviousSibling()) {
217 :
218 0 : if (key->NodeInfo()->Equals(nsGkAtoms::key, kNameSpaceID_XUL)) {
219 : // Check whether the key element has empty value at key/char attribute.
220 : // Such element is used by localizers for alternative shortcut key
221 : // definition on the locale. See bug 426501.
222 0 : nsAutoString valKey, valCharCode, valKeyCode;
223 : bool attrExists =
224 0 : key->GetAttr(kNameSpaceID_None, nsGkAtoms::key, valKey) ||
225 0 : key->GetAttr(kNameSpaceID_None, nsGkAtoms::charcode, valCharCode) ||
226 0 : key->GetAttr(kNameSpaceID_None, nsGkAtoms::keycode, valKeyCode);
227 0 : if (attrExists &&
228 0 : valKey.IsEmpty() && valCharCode.IsEmpty() && valKeyCode.IsEmpty())
229 0 : continue;
230 :
231 0 : nsXBLPrototypeHandler* handler = new nsXBLPrototypeHandler(key);
232 :
233 0 : if (!handler)
234 : return;
235 :
236 0 : handler->SetNextHandler(*aResult);
237 0 : *aResult = handler;
238 : }
239 : }
240 : }
241 :
242 : //
243 : // EnsureHandlers
244 : //
245 : // Lazily load the XBL handlers. Overridden to handle being attached
246 : // to a particular element rather than the document
247 : //
248 : nsresult
249 0 : nsXBLWindowKeyHandler::EnsureHandlers(bool *aIsEditor)
250 : {
251 0 : nsCOMPtr<nsIDOMElement> el = GetElement();
252 0 : NS_ENSURE_STATE(!mWeakPtrForElement || el);
253 0 : if (el) {
254 : // We are actually a XUL <keyset>.
255 0 : if (aIsEditor)
256 0 : *aIsEditor = false;
257 :
258 0 : if (mHandler)
259 0 : return NS_OK;
260 :
261 0 : nsCOMPtr<nsIContent> content(do_QueryInterface(el));
262 0 : BuildHandlerChain(content, &mHandler);
263 : } else { // We are an XBL file of handlers.
264 0 : if (!sXBLSpecialDocInfo)
265 0 : sXBLSpecialDocInfo = new nsXBLSpecialDocInfo();
266 0 : if (!sXBLSpecialDocInfo) {
267 0 : if (aIsEditor) {
268 0 : *aIsEditor = false;
269 : }
270 0 : return NS_ERROR_OUT_OF_MEMORY;
271 : }
272 0 : sXBLSpecialDocInfo->LoadDocInfo();
273 :
274 : // Now determine which handlers we should be using.
275 0 : bool isEditor = IsEditor();
276 0 : if (isEditor) {
277 0 : sXBLSpecialDocInfo->GetAllHandlers("editor", &mHandler, &mUserHandler);
278 : }
279 : else {
280 0 : sXBLSpecialDocInfo->GetAllHandlers("browser", &mHandler, &mUserHandler);
281 : }
282 :
283 0 : if (aIsEditor)
284 0 : *aIsEditor = isEditor;
285 : }
286 :
287 0 : return NS_OK;
288 : }
289 :
290 : static nsINativeKeyBindings*
291 0 : GetEditorKeyBindings()
292 : {
293 : static bool noBindings = false;
294 0 : if (!sNativeEditorBindings && !noBindings) {
295 : CallGetService(NS_NATIVEKEYBINDINGS_CONTRACTID_PREFIX "editor",
296 0 : &sNativeEditorBindings);
297 :
298 0 : if (!sNativeEditorBindings) {
299 0 : noBindings = true;
300 : }
301 : }
302 :
303 0 : return sNativeEditorBindings;
304 : }
305 :
306 : static void
307 0 : DoCommandCallback(const char *aCommand, void *aData)
308 : {
309 0 : nsIControllers *controllers = static_cast<nsIControllers*>(aData);
310 0 : if (controllers) {
311 0 : nsCOMPtr<nsIController> controller;
312 0 : controllers->GetControllerForCommand(aCommand, getter_AddRefs(controller));
313 0 : if (controller) {
314 0 : controller->DoCommand(aCommand);
315 : }
316 : }
317 0 : }
318 :
319 : nsresult
320 0 : nsXBLWindowKeyHandler::WalkHandlers(nsIDOMKeyEvent* aKeyEvent, nsIAtom* aEventType)
321 : {
322 0 : nsCOMPtr<nsIDOMNSEvent> domNSEvent = do_QueryInterface(aKeyEvent);
323 : bool prevent;
324 0 : domNSEvent->GetPreventDefault(&prevent);
325 0 : if (prevent)
326 0 : return NS_OK;
327 :
328 0 : bool trustedEvent = false;
329 0 : if (domNSEvent) {
330 : //Don't process the event if it was not dispatched from a trusted source
331 0 : domNSEvent->GetIsTrusted(&trustedEvent);
332 : }
333 :
334 0 : if (!trustedEvent)
335 0 : return NS_OK;
336 :
337 : bool isEditor;
338 0 : nsresult rv = EnsureHandlers(&isEditor);
339 0 : NS_ENSURE_SUCCESS(rv, rv);
340 :
341 0 : nsCOMPtr<nsIDOMElement> el = GetElement();
342 0 : if (!el) {
343 0 : if (mUserHandler) {
344 0 : WalkHandlersInternal(aKeyEvent, aEventType, mUserHandler);
345 0 : domNSEvent->GetPreventDefault(&prevent);
346 0 : if (prevent)
347 0 : return NS_OK; // Handled by the user bindings. Our work here is done.
348 : }
349 : }
350 :
351 0 : nsCOMPtr<nsIContent> content = do_QueryInterface(el);
352 : // skip keysets that are disabled
353 0 : if (content && content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
354 0 : nsGkAtoms::_true, eCaseMatters)) {
355 0 : return NS_OK;
356 : }
357 :
358 0 : WalkHandlersInternal(aKeyEvent, aEventType, mHandler);
359 :
360 0 : if (isEditor && GetEditorKeyBindings()) {
361 : nsNativeKeyEvent nativeEvent;
362 : // get the DOM window we're attached to
363 0 : nsCOMPtr<nsIControllers> controllers;
364 0 : nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(mTarget);
365 0 : if (root) {
366 0 : root->GetControllers(getter_AddRefs(controllers));
367 : }
368 :
369 0 : bool handled = false;
370 0 : if (aEventType == nsGkAtoms::keypress) {
371 0 : if (nsContentUtils::DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent, true))
372 : handled = sNativeEditorBindings->KeyPress(nativeEvent,
373 0 : DoCommandCallback, controllers);
374 0 : } else if (aEventType == nsGkAtoms::keyup) {
375 0 : if (nsContentUtils::DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent, false))
376 : handled = sNativeEditorBindings->KeyUp(nativeEvent,
377 0 : DoCommandCallback, controllers);
378 : } else {
379 0 : NS_ASSERTION(aEventType == nsGkAtoms::keydown, "unknown key event type");
380 0 : if (nsContentUtils::DOMEventToNativeKeyEvent(aKeyEvent, &nativeEvent, false))
381 : handled = sNativeEditorBindings->KeyDown(nativeEvent,
382 0 : DoCommandCallback, controllers);
383 : }
384 :
385 0 : if (handled)
386 0 : aKeyEvent->PreventDefault();
387 :
388 : }
389 :
390 0 : return NS_OK;
391 : }
392 :
393 : NS_IMETHODIMP
394 0 : nsXBLWindowKeyHandler::HandleEvent(nsIDOMEvent* aEvent)
395 : {
396 0 : nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aEvent));
397 0 : NS_ENSURE_TRUE(keyEvent, NS_ERROR_INVALID_ARG);
398 :
399 0 : nsAutoString eventType;
400 0 : aEvent->GetType(eventType);
401 0 : nsCOMPtr<nsIAtom> eventTypeAtom = do_GetAtom(eventType);
402 0 : NS_ENSURE_TRUE(eventTypeAtom, NS_ERROR_OUT_OF_MEMORY);
403 :
404 0 : return WalkHandlers(keyEvent, eventTypeAtom);
405 : }
406 :
407 : //
408 : // EventMatched
409 : //
410 : // See if the given handler cares about this particular key event
411 : //
412 : bool
413 0 : nsXBLWindowKeyHandler::EventMatched(nsXBLPrototypeHandler* inHandler,
414 : nsIAtom* inEventType,
415 : nsIDOMKeyEvent* inEvent,
416 : PRUint32 aCharCode, bool aIgnoreShiftKey)
417 : {
418 : return inHandler->KeyEventMatched(inEventType, inEvent, aCharCode,
419 0 : aIgnoreShiftKey);
420 : }
421 :
422 : /* static */ void
423 1403 : nsXBLWindowKeyHandler::ShutDown()
424 : {
425 1403 : NS_IF_RELEASE(sNativeEditorBindings);
426 1403 : }
427 :
428 : //
429 : // IsEditor
430 : //
431 : // Determine if the document we're working with is Editor or Browser
432 : //
433 : bool
434 0 : nsXBLWindowKeyHandler::IsEditor()
435 : {
436 : // XXXndeakin even though this is only used for key events which should be
437 : // going to the focused frame anyway, this doesn't seem like the right way
438 : // to determine if something is an editor.
439 0 : nsIFocusManager* fm = nsFocusManager::GetFocusManager();
440 0 : if (!fm)
441 0 : return false;
442 :
443 0 : nsCOMPtr<nsIDOMWindow> focusedWindow;
444 0 : fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
445 0 : if (!focusedWindow)
446 0 : return false;
447 :
448 0 : nsCOMPtr<nsPIDOMWindow> piwin(do_QueryInterface(focusedWindow));
449 0 : nsIDocShell *docShell = piwin->GetDocShell();
450 0 : nsCOMPtr<nsIPresShell> presShell;
451 0 : if (docShell)
452 0 : docShell->GetPresShell(getter_AddRefs(presShell));
453 :
454 0 : if (presShell) {
455 0 : return presShell->GetSelectionFlags() == nsISelectionDisplay::DISPLAY_ALL;
456 : }
457 :
458 0 : return false;
459 : }
460 :
461 : //
462 : // WalkHandlersInternal and WalkHandlersAndExecute
463 : //
464 : // Given a particular DOM event and a pointer to the first handler in the list,
465 : // scan through the list to find something to handle the event and then make it
466 : // so.
467 : //
468 : nsresult
469 0 : nsXBLWindowKeyHandler::WalkHandlersInternal(nsIDOMKeyEvent* aKeyEvent,
470 : nsIAtom* aEventType,
471 : nsXBLPrototypeHandler* aHandler)
472 : {
473 0 : nsAutoTArray<nsShortcutCandidate, 10> accessKeys;
474 0 : nsContentUtils::GetAccelKeyCandidates(aKeyEvent, accessKeys);
475 :
476 0 : if (accessKeys.IsEmpty()) {
477 0 : WalkHandlersAndExecute(aKeyEvent, aEventType, aHandler, 0, false);
478 0 : return NS_OK;
479 : }
480 :
481 0 : for (PRUint32 i = 0; i < accessKeys.Length(); ++i) {
482 0 : nsShortcutCandidate &key = accessKeys[i];
483 0 : if (WalkHandlersAndExecute(aKeyEvent, aEventType, aHandler,
484 0 : key.mCharCode, key.mIgnoreShift))
485 0 : return NS_OK;
486 : }
487 0 : return NS_OK;
488 : }
489 :
490 : bool
491 0 : nsXBLWindowKeyHandler::WalkHandlersAndExecute(nsIDOMKeyEvent* aKeyEvent,
492 : nsIAtom* aEventType,
493 : nsXBLPrototypeHandler* aHandler,
494 : PRUint32 aCharCode,
495 : bool aIgnoreShiftKey)
496 : {
497 : nsresult rv;
498 0 : nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(aKeyEvent));
499 :
500 : // Try all of the handlers until we find one that matches the event.
501 0 : for (nsXBLPrototypeHandler *currHandler = aHandler; currHandler;
502 : currHandler = currHandler->GetNextHandler()) {
503 0 : bool stopped = privateEvent->IsDispatchStopped();
504 0 : if (stopped) {
505 : // The event is finished, don't execute any more handlers
506 0 : return NS_OK;
507 : }
508 :
509 0 : if (!EventMatched(currHandler, aEventType, aKeyEvent,
510 0 : aCharCode, aIgnoreShiftKey))
511 0 : continue; // try the next one
512 :
513 : // Before executing this handler, check that it's not disabled,
514 : // and that it has something to do (oncommand of the <key> or its
515 : // <command> is non-empty).
516 0 : nsCOMPtr<nsIContent> elt = currHandler->GetHandlerElement();
517 0 : nsCOMPtr<nsIDOMElement> commandElt;
518 :
519 : // See if we're in a XUL doc.
520 0 : nsCOMPtr<nsIDOMElement> el = GetElement();
521 0 : if (el && elt) {
522 : // We are. Obtain our command attribute.
523 0 : nsAutoString command;
524 0 : elt->GetAttr(kNameSpaceID_None, nsGkAtoms::command, command);
525 0 : if (!command.IsEmpty()) {
526 : // Locate the command element in question. Note that we
527 : // know "elt" is in a doc if we're dealing with it here.
528 0 : NS_ASSERTION(elt->IsInDoc(), "elt must be in document");
529 0 : nsIDocument *doc = elt->GetCurrentDoc();
530 0 : if (doc)
531 0 : commandElt = do_QueryInterface(doc->GetElementById(command));
532 :
533 0 : if (!commandElt) {
534 0 : NS_ERROR("A XUL <key> is observing a command that doesn't exist. Unable to execute key binding!");
535 0 : continue;
536 : }
537 : }
538 : }
539 :
540 0 : if (!commandElt) {
541 0 : commandElt = do_QueryInterface(elt);
542 : }
543 :
544 0 : if (commandElt) {
545 0 : nsAutoString value;
546 0 : commandElt->GetAttribute(NS_LITERAL_STRING("disabled"), value);
547 0 : if (value.EqualsLiteral("true")) {
548 0 : continue; // this handler is disabled, try the next one
549 : }
550 :
551 : // Check that there is an oncommand handler
552 0 : commandElt->GetAttribute(NS_LITERAL_STRING("oncommand"), value);
553 0 : if (value.IsEmpty()) {
554 0 : continue; // nothing to do
555 : }
556 : }
557 :
558 0 : nsCOMPtr<nsIDOMEventTarget> piTarget;
559 0 : nsCOMPtr<nsIDOMElement> element = GetElement();
560 0 : if (element) {
561 0 : piTarget = do_QueryInterface(commandElt);
562 : } else {
563 0 : piTarget = mTarget;
564 : }
565 :
566 0 : rv = currHandler->ExecuteHandler(piTarget, aKeyEvent);
567 0 : if (NS_SUCCEEDED(rv)) {
568 0 : return true;
569 : }
570 : }
571 :
572 0 : return false;
573 : }
574 :
575 : already_AddRefed<nsIDOMElement>
576 0 : nsXBLWindowKeyHandler::GetElement()
577 : {
578 0 : nsCOMPtr<nsIDOMElement> element = do_QueryReferent(mWeakPtrForElement);
579 0 : nsIDOMElement* el = nsnull;
580 0 : element.swap(el);
581 0 : return el;
582 : }
583 :
584 : ///////////////////////////////////////////////////////////////////////////////////
585 :
586 : nsresult
587 0 : NS_NewXBLWindowKeyHandler(nsIDOMElement* aElement, nsIDOMEventTarget* aTarget,
588 : nsXBLWindowKeyHandler** aResult)
589 : {
590 0 : *aResult = new nsXBLWindowKeyHandler(aElement, aTarget);
591 0 : if (!*aResult)
592 0 : return NS_ERROR_OUT_OF_MEMORY;
593 0 : NS_ADDREF(*aResult);
594 0 : return NS_OK;
595 : }
|