This commit is contained in:
hyatt%netscape.com 2000-09-02 01:09:47 +00:00
Родитель b98c866d6f
Коммит 2909098718
30 изменённых файлов: 2360 добавлений и 1456 удалений

Просмотреть файл

@ -33,6 +33,7 @@ EXPORTS = \
nsIXBLBinding.h \
nsIXBLBindingAttachedHandler.h \
nsIXBLDocumentInfo.h \
nsIXBLPrototypeHandler.h \
nsIXBLService.h \
$(NULL)

Просмотреть файл

@ -2,5 +2,6 @@ nsIBindingManager.h
nsIXBLBinding.h
nsIXBLBindingAttachedHandler.h
nsIXBLDocumentInfo.h
nsIXBLPrototypeHandler.h
nsIXBLService.h

Просмотреть файл

@ -26,6 +26,7 @@ EXPORTS = \
nsIXBLBinding.h \
nsIXBLBindingAttachedHandler.h \
nsIXBLDocumentInfo.h \
nsIXBLPrototypeHandler.h \
nsIXBLService.h \
$(NULL)

Просмотреть файл

@ -38,6 +38,7 @@
class nsIContent;
class nsIDocument;
class nsIScriptContext;
class nsIXBLPrototypeHandler;
// {5C4D9674-A2CF-4ddf-9F65-E1806C34D28D}
#define NS_IXBLDOCUMENTINFO_IID \
@ -54,6 +55,8 @@ public:
NS_IMETHOD GetScriptAccess(PRBool* aResult)=0;
NS_IMETHOD SetScriptAccess(PRBool aAccess)=0;
NS_IMETHOD GetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler** aResult)=0;
NS_IMETHOD SetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler* aHandler)=0;
};
extern nsresult

Просмотреть файл

@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s):
*/
/*
Private interface to the XBL PrototypeHandler
*/
#ifndef nsIXBLPrototypeHandler_h__
#define nsIXBLPrototypeHandler_h__
class nsIContent;
class nsIDOMEvent;
// {921812E7-A044-4bd8-B49E-69BB0A607202}
#define NS_IXBLPROTOTYPEHANDLER_IID \
{ 0x921812e7, 0xa044, 0x4bd8, { 0xb4, 0x9e, 0x69, 0xbb, 0xa, 0x60, 0x72, 0x2 } }
class nsIXBLPrototypeHandler : public nsISupports
{
public:
static const nsIID& GetIID() { static nsIID iid = NS_IXBLPROTOTYPEHANDLER_IID; return iid; }
NS_IMETHOD EventMatched(nsIDOMEvent* aEvent, PRBool* aResult) = 0;
NS_IMETHOD GetHandlerElement(nsIContent** aResult) = 0;
NS_IMETHOD GetNextHandler(nsIXBLPrototypeHandler** aResult) = 0;
NS_IMETHOD SetNextHandler(nsIXBLPrototypeHandler* aHandler) = 0;
};
extern nsresult
NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult);
#endif // nsIXBLPrototypeHandler_h__

Просмотреть файл

@ -32,6 +32,7 @@ LIBRARY_NAME = gkxbl_s
CPPSRCS = \
nsXBLBinding.cpp \
nsXBLEventHandler.cpp \
nsXBLPrototypeHandler.cpp \
nsXBLService.cpp \
nsBindingManager.cpp \
$(NULL)

Просмотреть файл

@ -30,12 +30,14 @@ CPPSRCS= \
nsXBLBinding.cpp \
nsXBLService.cpp \
nsXBLEventHandler.cpp \
nsXBLPrototypeHandler.cpp \
nsBindingManager.cpp \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsXBLBinding.obj \
.\$(OBJDIR)\nsXBLEventHandler.obj \
.\$(OBJDIR)\nsXBLPrototypeHandler.obj \
.\$(OBJDIR)\nsXBLService.obj \
.\$(OBJDIR)\nsBindingManager.obj \
$(NULL)

Просмотреть файл

@ -58,6 +58,7 @@
#include "nsIStyleRuleProcessor.h"
#include "nsIStyleSet.h"
#include "nsIXBLPrototypeHandler.h"
// Static IIDs/CIDs. Try to minimize these.
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
@ -78,10 +79,14 @@ public:
NS_IMETHOD GetScriptAccess(PRBool* aResult) { *aResult = mScriptAccess; return NS_OK; };
NS_IMETHOD SetScriptAccess(PRBool aAccess) { mScriptAccess = aAccess; return NS_OK; };
NS_IMETHOD GetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler** aResult);
NS_IMETHOD SetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler* aHandler);
private:
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsISupportsArray> mRuleProcessors;
PRBool mScriptAccess;
nsSupportsHashtable* mHandlerTable;
};
/* Implementation file */
@ -93,12 +98,13 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument)
/* member initializers and constructor code */
mDocument = aDocument;
mScriptAccess = PR_TRUE;
mHandlerTable = nsnull;
}
nsXBLDocumentInfo::~nsXBLDocumentInfo()
{
/* destructor code */
delete mHandlerTable;
}
NS_IMETHODIMP
@ -136,7 +142,32 @@ nsXBLDocumentInfo::GetRuleProcessors(nsISupportsArray** aResult)
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsXBLDocumentInfo::GetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler** aResult)
{
*aResult = nsnull;
if (!mHandlerTable)
return NS_OK;
nsCStringKey key(aRef);
*aResult = NS_STATIC_CAST(nsIXBLPrototypeHandler*, mHandlerTable->Get(&key)); // Addref happens here.
return NS_OK;
}
NS_IMETHODIMP
nsXBLDocumentInfo::SetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler* aHandler)
{
if (!mHandlerTable)
mHandlerTable = new nsSupportsHashtable();
nsCStringKey key(aRef);
mHandlerTable->Put(&key, aHandler);
return NS_OK;
}
nsresult NS_NewXBLDocumentInfo(nsIDocument* aDocument, nsIXBLDocumentInfo** aResult)
{
*aResult = new nsXBLDocumentInfo(aDocument);

Просмотреть файл

@ -67,6 +67,7 @@
#include "nsIDOMAttr.h"
#include "nsIDOMNamedNodeMap.h"
#include "nsIXBLPrototypeHandler.h"
#include "nsXBLEventHandler.h"
#include "nsXBLBinding.h"
@ -573,112 +574,123 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement)
NS_IMETHODIMP
nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aBinding)
{
// Fetch the handlers element for this binding.
nsCOMPtr<nsIContent> handlers;
GetImmediateChild(kHandlersAtom, getter_AddRefs(handlers));
// Don't install handlers if scripts aren't allowed.
if (!AllowScripts())
return NS_OK;
// Fetch the handlers prototypes for this binding.
nsCOMPtr<nsIXBLDocumentInfo> info;
gXBLService->GetXBLDocumentInfo(mDocURI, mBoundElement, getter_AddRefs(info));
if (!info)
return NS_OK;
nsCOMPtr<nsIXBLPrototypeHandler> handlerChain;
info->GetPrototypeHandler(mID, getter_AddRefs(handlerChain));
if (!handlerChain)
return NS_OK;
nsCOMPtr<nsIXBLPrototypeHandler> curr = handlerChain;
nsXBLEventHandler* currHandler = nsnull;
if (handlers && AllowScripts()) {
// Now walk the handlers and add event listeners to the bound
// element.
PRInt32 childCount;
handlers->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> child;
handlers->ChildAt(i, *getter_AddRefs(child));
// Fetch the type attribute.
// XXX Deal with a comma-separated list of types
nsAutoString type;
child->GetAttribute(kNameSpaceID_None, kEventAtom, type);
if (!type.IsEmpty()) {
nsIID iid;
PRBool found = PR_FALSE;
PRBool special = PR_FALSE;
nsCOMPtr<nsIAtom> eventAtom = getter_AddRefs(NS_NewAtom(type));
if (eventAtom.get() == kBindingAttachedAtom) {
*aBinding = this;
NS_ADDREF(*aBinding);
special = PR_TRUE;
while (curr) {
nsCOMPtr<nsIContent> child;
curr->GetHandlerElement(getter_AddRefs(child));
// Fetch the type attribute.
// XXX Deal with a comma-separated list of types
nsAutoString type;
child->GetAttribute(kNameSpaceID_None, kEventAtom, type);
if (!type.IsEmpty()) {
nsIID iid;
PRBool found = PR_FALSE;
PRBool special = PR_FALSE;
nsCOMPtr<nsIAtom> eventAtom = getter_AddRefs(NS_NewAtom(type));
if (eventAtom.get() == kBindingAttachedAtom) {
*aBinding = this;
NS_ADDREF(*aBinding);
special = PR_TRUE;
}
else
GetEventHandlerIID(eventAtom, &iid, &found);
if (found || special) {
// Add an event listener for mouse and key events only.
PRBool mouse = IsMouseHandler(type);
PRBool key = IsKeyHandler(type);
PRBool focus = IsFocusHandler(type);
PRBool xul = IsXULHandler(type);
PRBool scroll = IsScrollHandler(type);
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mBoundElement);
nsAutoString attachType;
child->GetAttribute(kNameSpaceID_None, kAttachToAtom, attachType);
if (attachType == NS_LITERAL_STRING("_document") ||
attachType == NS_LITERAL_STRING("_window"))
{
nsCOMPtr<nsIDocument> boundDoc;
mBoundElement->GetDocument(*getter_AddRefs(boundDoc));
if (attachType == NS_LITERAL_STRING("_window")) {
nsCOMPtr<nsIScriptGlobalObject> global;
boundDoc->GetScriptGlobalObject(getter_AddRefs(global));
receiver = do_QueryInterface(global);
}
else receiver = do_QueryInterface(boundDoc);
}
else
GetEventHandlerIID(eventAtom, &iid, &found);
if (found || special) {
// Add an event listener for mouse and key events only.
PRBool mouse = IsMouseHandler(type);
PRBool key = IsKeyHandler(type);
PRBool focus = IsFocusHandler(type);
PRBool xul = IsXULHandler(type);
PRBool scroll = IsScrollHandler(type);
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mBoundElement);
nsAutoString attachType;
child->GetAttribute(kNameSpaceID_None, kAttachToAtom, attachType);
if (attachType == NS_LITERAL_STRING("_document") ||
attachType == NS_LITERAL_STRING("_window"))
{
nsCOMPtr<nsIDocument> boundDoc;
mBoundElement->GetDocument(*getter_AddRefs(boundDoc));
if (attachType == NS_LITERAL_STRING("_window")) {
nsCOMPtr<nsIScriptGlobalObject> global;
boundDoc->GetScriptGlobalObject(getter_AddRefs(global));
receiver = do_QueryInterface(global);
}
else receiver = do_QueryInterface(boundDoc);
}
if (mouse || key || focus || xul || scroll || special) {
// Create a new nsXBLEventHandler.
nsXBLEventHandler* handler;
NS_NewXBLEventHandler(receiver, curr, type, &handler);
if (mouse || key || focus || xul || scroll || special) {
// Create a new nsXBLEventHandler.
nsXBLEventHandler* handler;
NS_NewXBLEventHandler(receiver, child, type, &handler);
// We chain all our event handlers together for easy
// removal later (if/when the binding dies).
if (!currHandler)
mFirstHandler = handler;
else
currHandler->SetNextHandler(handler);
// We chain all our event handlers together for easy
// removal later (if/when the binding dies).
if (!currHandler)
mFirstHandler = handler;
else
currHandler->SetNextHandler(handler);
currHandler = handler;
currHandler = handler;
// Figure out if we're using capturing or not.
PRBool useCapture = PR_FALSE;
nsAutoString capturer;
child->GetAttribute(kNameSpaceID_None, kPhaseAtom, capturer);
if (capturer == NS_LITERAL_STRING("capturing"))
useCapture = PR_TRUE;
// Figure out if we're using capturing or not.
PRBool useCapture = PR_FALSE;
nsAutoString capturer;
child->GetAttribute(kNameSpaceID_None, kPhaseAtom, capturer);
if (capturer == NS_LITERAL_STRING("capturing"))
useCapture = PR_TRUE;
// Add the event listener.
if (mouse)
receiver->AddEventListener(type, (nsIDOMMouseListener*)handler, useCapture);
else if(key)
receiver->AddEventListener(type, (nsIDOMKeyListener*)handler, useCapture);
else if(focus)
receiver->AddEventListener(type, (nsIDOMFocusListener*)handler, useCapture);
else if (xul)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
else if (scroll)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
// Add the event listener.
if (mouse)
receiver->AddEventListener(type, (nsIDOMMouseListener*)handler, useCapture);
else if(key)
receiver->AddEventListener(type, (nsIDOMKeyListener*)handler, useCapture);
else if(focus)
receiver->AddEventListener(type, (nsIDOMFocusListener*)handler, useCapture);
else if (xul)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
else if (scroll)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
if (!special) // Let the listener manager hold on to the handler.
NS_RELEASE(handler);
}
else {
// Call AddScriptEventListener for other IID types
// XXX Want this to all go away!
NS_WARNING("***** Non-compliant XBL event listener attached! *****");
nsAutoString value;
child->GetAttribute(kNameSpaceID_None, kActionAtom, value);
if (value.IsEmpty())
GetTextData(child, value);
if (!special) // Let the listener manager hold on to the handler.
NS_RELEASE(handler);
}
else {
// Call AddScriptEventListener for other IID types
// XXX Want this to all go away!
NS_WARNING("***** Non-compliant XBL event listener attached! *****");
nsAutoString value;
child->GetAttribute(kNameSpaceID_None, kActionAtom, value);
if (value.IsEmpty())
GetTextData(child, value);
AddScriptEventListener(mBoundElement, eventAtom, value, iid);
}
AddScriptEventListener(mBoundElement, eventAtom, value, iid);
}
}
}
nsCOMPtr<nsIXBLPrototypeHandler> next;
curr->GetNextHandler(getter_AddRefs(next));
curr = next;
}
if (mNextBinding) {

Просмотреть файл

@ -23,6 +23,7 @@
*/
#include "nsCOMPtr.h"
#include "nsIXBLPrototypeHandler.h"
#include "nsXBLEventHandler.h"
#include "nsIContent.h"
#include "nsIAtom.h"
@ -63,19 +64,12 @@ nsIAtom* nsXBLEventHandler::kBindingAttachedAtom = nsnull;
nsIAtom* nsXBLEventHandler::kBindingDetachedAtom = nsnull;
nsIAtom* nsXBLEventHandler::kModifiersAtom = nsnull;
PRInt32 nsXBLEventHandler::kAccessKey = -1;
const PRInt32 nsXBLEventHandler::cShift = (1<<1);
const PRInt32 nsXBLEventHandler::cAlt = (1<<2);
const PRInt32 nsXBLEventHandler::cControl = (1<<3);
const PRInt32 nsXBLEventHandler::cMeta = (1<<4);
nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIContent* aHandlerElement,
nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandler,
const nsString& aEventName)
{
NS_INIT_REFCNT();
mEventReceiver = aEventReceiver;
mHandlerElement = aHandlerElement;
mProtoHandler = aHandler;
mEventName.Assign(aEventName);
mNextHandler = nsnull;
gRefCnt++;
@ -90,13 +84,7 @@ nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsICon
kButtonAtom = NS_NewAtom("button");
kBindingAttachedAtom = NS_NewAtom("bindingattached");
kBindingDetachedAtom = NS_NewAtom("bindingdetached");
// Get the primary accelerator key.
InitAccessKey();
}
// Make sure our mask is initialized.
ConstructMask();
}
nsXBLEventHandler::~nsXBLEventHandler()
@ -166,6 +154,7 @@ nsXBLEventHandler::BindingAttached()
NS_IMETHODIMP
nsXBLEventHandler::BindingDetached()
{
// XXX Write me!!!!
return NS_OK;
}
@ -180,8 +169,11 @@ nsresult nsXBLEventHandler::KeyUp(nsIDOMEvent* aKeyEvent)
if (mEventName != NS_LITERAL_STRING("keyup"))
return NS_OK;
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
if (KeyEventMatched(keyEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aKeyEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("keyup"), aKeyEvent);
return NS_OK;
}
@ -191,8 +183,11 @@ nsresult nsXBLEventHandler::KeyDown(nsIDOMEvent* aKeyEvent)
if (mEventName != NS_LITERAL_STRING("keydown"))
return NS_OK;
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
if (KeyEventMatched(keyEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aKeyEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("keydown"), aKeyEvent);
return NS_OK;
}
@ -202,8 +197,11 @@ nsresult nsXBLEventHandler::KeyPress(nsIDOMEvent* aKeyEvent)
if (mEventName != NS_LITERAL_STRING("keypress"))
return NS_OK;
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
if (KeyEventMatched(keyEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aKeyEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("keypress"), aKeyEvent);
return NS_OK;
}
@ -213,8 +211,11 @@ nsresult nsXBLEventHandler::MouseDown(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("mousedown"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("mousedown"), aMouseEvent);
return NS_OK;
}
@ -224,8 +225,11 @@ nsresult nsXBLEventHandler::MouseUp(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("mouseup"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("mouseup"), aMouseEvent);
return NS_OK;
}
@ -235,8 +239,11 @@ nsresult nsXBLEventHandler::MouseClick(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("click"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("click"), aMouseEvent);
return NS_OK;
}
@ -246,8 +253,11 @@ nsresult nsXBLEventHandler::MouseDblClick(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("dblclick"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("dblclick"), aMouseEvent);
return NS_OK;
}
@ -257,8 +267,11 @@ nsresult nsXBLEventHandler::MouseOver(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("mouseover"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("mouseover"), aMouseEvent);
return NS_OK;
}
@ -268,8 +281,11 @@ nsresult nsXBLEventHandler::MouseOut(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("mouseout"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("mouseout"), aMouseEvent);
return NS_OK;
}
@ -375,88 +391,22 @@ nsresult nsXBLEventHandler::Destroy(nsIDOMEvent* aEvent)
return NS_OK;
}
/////////////////////////////////////////////////////////////////////////////
// Get the menu access key from prefs.
// XXX Eventually pick up using CSS3 key-equivalent property or somesuch
void
nsXBLEventHandler::InitAccessKey()
{
if (kAccessKey >= 0)
return;
// Compiled-in defaults, in case we can't get the pref --
// mac doesn't have menu shortcuts, other platforms use alt.
#ifndef XP_MAC
kAccessKey = nsIDOMKeyEvent::DOM_VK_ALT;
#else
kAccessKey = 0;
#endif
// Get the menu access key value from prefs, overriding the default:
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv);
if (NS_SUCCEEDED(rv) && prefs)
{
rv = prefs->GetIntPref("ui.key.menuAccessKey", &kAccessKey);
}
}
PRBool
nsXBLEventHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent)
{
if (!mHandlerElement)
return PR_FALSE;
if (mDetail == 0 && mDetail2 == 0 && mKeyMask == 0)
return PR_TRUE; // No filters set up. It's generic.
// Get the keycode and charcode of the key event.
PRUint32 keyCode, charCode;
aKeyEvent->GetKeyCode(&keyCode);
aKeyEvent->GetCharCode(&charCode);
PRBool keyMatched = (mDetail == (mDetail2 ? charCode : keyCode));
if (!keyMatched)
return PR_FALSE;
// Now check modifier keys
return ModifiersMatchMask(aKeyEvent);
}
PRBool
nsXBLEventHandler::MouseEventMatched(nsIDOMMouseEvent* aMouseEvent)
{
if (!mHandlerElement)
return PR_FALSE;
if (mDetail == 0 && mDetail2 == 0 && mKeyMask == 0)
return PR_TRUE; // No filters set up. It's generic.
unsigned short button;
aMouseEvent->GetButton(&button);
if (mDetail != 0 && (button != mDetail))
return PR_FALSE;
PRInt32 clickcount;
aMouseEvent->GetDetail(&clickcount);
if (mDetail2 != 0 && (clickcount != mDetail2))
return PR_FALSE;
return ModifiersMatchMask(aMouseEvent);
}
NS_IMETHODIMP
nsXBLEventHandler::ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEvent* aEvent)
{
if (!mHandlerElement)
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIContent> handlerElement;
mProtoHandler->GetHandlerElement(getter_AddRefs(handlerElement));
if (!handlerElement)
return NS_ERROR_FAILURE;
// This is a special-case optimization to make command handling fast.
// It isn't really a part of XBL, but it helps speed things up.
nsAutoString command;
mHandlerElement->GetAttribute(kNameSpaceID_None, kCommandAtom, command);
handlerElement->GetAttribute(kNameSpaceID_None, kCommandAtom, command);
if (!command.IsEmpty()) {
// We are the default action for this command.
// Stop any other default action from executing.
@ -493,10 +443,10 @@ nsXBLEventHandler::ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEv
// Compile the event handler.
nsAutoString handlerText;
mHandlerElement->GetAttribute(kNameSpaceID_None, kActionAtom, handlerText);
handlerElement->GetAttribute(kNameSpaceID_None, kActionAtom, handlerText);
if (handlerText.IsEmpty()) {
// look to see if action content is contained by the handler element
GetTextData(mHandlerElement, handlerText);
GetTextData(handlerElement, handlerText);
if (handlerText.IsEmpty())
return NS_OK; // For whatever reason, they didn't give us anything to do.
}
@ -598,15 +548,22 @@ nsXBLEventHandler::RemoveEventHandlers()
}
// Figure out if we're using capturing or not.
if (!mProtoHandler)
return;
nsCOMPtr<nsIContent> handlerElement;
mProtoHandler->GetHandlerElement(getter_AddRefs(handlerElement));
if (!handlerElement)
return;
PRBool useCapture = PR_FALSE;
nsAutoString capturer;
mHandlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kPhaseAtom, capturer);
handlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kPhaseAtom, capturer);
if (capturer == NS_LITERAL_STRING("capturing"))
useCapture = PR_TRUE;
// XXX Will potentially be comma-separated
nsAutoString type;
mHandlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kEventAtom, type);
handlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kEventAtom, type);
// Figure out our type.
PRBool mouse = nsXBLBinding::IsMouseHandler(type);
@ -630,392 +587,6 @@ nsXBLEventHandler::RemoveEventHandlers()
/// Helpers that are relegated to the end of the file /////////////////////////////
enum {
VK_CANCEL = 3,
VK_BACK = 8,
VK_TAB = 9,
VK_CLEAR = 12,
VK_RETURN = 13,
VK_ENTER = 14,
VK_SHIFT = 16,
VK_CONTROL = 17,
VK_ALT = 18,
VK_PAUSE = 19,
VK_CAPS_LOCK = 20,
VK_ESCAPE = 27,
VK_SPACE = 32,
VK_PAGE_UP = 33,
VK_PAGE_DOWN = 34,
VK_END = 35,
VK_HOME = 36,
VK_LEFT = 37,
VK_UP = 38,
VK_RIGHT = 39,
VK_DOWN = 40,
VK_PRINTSCREEN = 44,
VK_INSERT = 45,
VK_DELETE = 46,
VK_0 = 48,
VK_1 = 49,
VK_2 = 50,
VK_3 = 51,
VK_4 = 52,
VK_5 = 53,
VK_6 = 54,
VK_7 = 55,
VK_8 = 56,
VK_9 = 57,
VK_SEMICOLON = 59,
VK_EQUALS = 61,
VK_A = 65,
VK_B = 66,
VK_C = 67,
VK_D = 68,
VK_E = 69,
VK_F = 70,
VK_G = 71,
VK_H = 72,
VK_I = 73,
VK_J = 74,
VK_K = 75,
VK_L = 76,
VK_M = 77,
VK_N = 78,
VK_O = 79,
VK_P = 80,
VK_Q = 81,
VK_R = 82,
VK_S = 83,
VK_T = 84,
VK_U = 85,
VK_V = 86,
VK_W = 87,
VK_X = 88,
VK_Y = 89,
VK_Z = 90,
VK_NUMPAD0 = 96,
VK_NUMPAD1 = 97,
VK_NUMPAD2 = 98,
VK_NUMPAD3 = 99,
VK_NUMPAD4 = 100,
VK_NUMPAD5 = 101,
VK_NUMPAD6 = 102,
VK_NUMPAD7 = 103,
VK_NUMPAD8 = 104,
VK_NUMPAD9 = 105,
VK_MULTIPLY = 106,
VK_ADD = 107,
VK_SEPARATOR = 108,
VK_SUBTRACT = 109,
VK_DECIMAL = 110,
VK_DIVIDE = 111,
VK_F1 = 112,
VK_F2 = 113,
VK_F3 = 114,
VK_F4 = 115,
VK_F5 = 116,
VK_F6 = 117,
VK_F7 = 118,
VK_F8 = 119,
VK_F9 = 120,
VK_F10 = 121,
VK_F11 = 122,
VK_F12 = 123,
VK_F13 = 124,
VK_F14 = 125,
VK_F15 = 126,
VK_F16 = 127,
VK_F17 = 128,
VK_F18 = 129,
VK_F19 = 130,
VK_F20 = 131,
VK_F21 = 132,
VK_F22 = 133,
VK_F23 = 134,
VK_F24 = 135,
VK_NUM_LOCK = 144,
VK_SCROLL_LOCK = 145,
VK_COMMA = 188,
VK_PERIOD = 190,
VK_SLASH = 191,
VK_BACK_QUOTE = 192,
VK_OPEN_BRACKET = 219,
VK_BACK_SLASH = 220,
VK_CLOSE_BRACKET = 221,
VK_QUOTE = 222
};
PRUint32 nsXBLEventHandler::GetMatchingKeyCode(const nsString& aKeyName)
{
PRBool ret = PR_FALSE;
nsCAutoString keyName; keyName.AssignWithConversion(aKeyName);
if (keyName.EqualsIgnoreCase("VK_CANCEL"))
return VK_CANCEL;
if(keyName.EqualsIgnoreCase("VK_BACK"))
return VK_BACK;
if(keyName.EqualsIgnoreCase("VK_TAB"))
return VK_TAB;
if(keyName.EqualsIgnoreCase("VK_CLEAR"))
return VK_CLEAR;
if(keyName.EqualsIgnoreCase("VK_RETURN"))
return VK_RETURN;
if(keyName.EqualsIgnoreCase("VK_ENTER"))
return VK_ENTER;
if(keyName.EqualsIgnoreCase("VK_SHIFT"))
return VK_SHIFT;
if(keyName.EqualsIgnoreCase("VK_CONTROL"))
return VK_CONTROL;
if(keyName.EqualsIgnoreCase("VK_ALT"))
return VK_ALT;
if(keyName.EqualsIgnoreCase("VK_PAUSE"))
return VK_PAUSE;
if(keyName.EqualsIgnoreCase("VK_CAPS_LOCK"))
return VK_CAPS_LOCK;
if(keyName.EqualsIgnoreCase("VK_ESCAPE"))
return VK_ESCAPE;
if(keyName.EqualsIgnoreCase("VK_SPACE"))
return VK_SPACE;
if(keyName.EqualsIgnoreCase("VK_PAGE_UP"))
return VK_PAGE_UP;
if(keyName.EqualsIgnoreCase("VK_PAGE_DOWN"))
return VK_PAGE_DOWN;
if(keyName.EqualsIgnoreCase("VK_END"))
return VK_END;
if(keyName.EqualsIgnoreCase("VK_HOME"))
return VK_HOME;
if(keyName.EqualsIgnoreCase("VK_LEFT"))
return VK_LEFT;
if(keyName.EqualsIgnoreCase("VK_UP"))
return VK_UP;
if(keyName.EqualsIgnoreCase("VK_RIGHT"))
return VK_RIGHT;
if(keyName.EqualsIgnoreCase("VK_DOWN"))
return VK_DOWN;
if(keyName.EqualsIgnoreCase("VK_PRINTSCREEN"))
return VK_PRINTSCREEN;
if(keyName.EqualsIgnoreCase("VK_INSERT"))
return VK_INSERT;
if(keyName.EqualsIgnoreCase("VK_DELETE"))
return VK_DELETE;
if(keyName.EqualsIgnoreCase("VK_0"))
return VK_0;
if(keyName.EqualsIgnoreCase("VK_1"))
return VK_1;
if(keyName.EqualsIgnoreCase("VK_2"))
return VK_2;
if(keyName.EqualsIgnoreCase("VK_3"))
return VK_3;
if(keyName.EqualsIgnoreCase("VK_4"))
return VK_4;
if(keyName.EqualsIgnoreCase("VK_5"))
return VK_5;
if(keyName.EqualsIgnoreCase("VK_6"))
return VK_6;
if(keyName.EqualsIgnoreCase("VK_7"))
return VK_7;
if(keyName.EqualsIgnoreCase("VK_8"))
return VK_8;
if(keyName.EqualsIgnoreCase("VK_9"))
return VK_9;
if(keyName.EqualsIgnoreCase("VK_SEMICOLON"))
return VK_SEMICOLON;
if(keyName.EqualsIgnoreCase("VK_EQUALS"))
return VK_EQUALS;
if(keyName.EqualsIgnoreCase("VK_A"))
return VK_A;
if(keyName.EqualsIgnoreCase("VK_B"))
return VK_B;
if(keyName.EqualsIgnoreCase("VK_C"))
return VK_C;
if(keyName.EqualsIgnoreCase("VK_D"))
return VK_D;
if(keyName.EqualsIgnoreCase("VK_E"))
return VK_E;
if(keyName.EqualsIgnoreCase("VK_F"))
return VK_F;
if(keyName.EqualsIgnoreCase("VK_G"))
return VK_G;
if(keyName.EqualsIgnoreCase("VK_H"))
return VK_H;
if(keyName.EqualsIgnoreCase("VK_I"))
return VK_I;
if(keyName.EqualsIgnoreCase("VK_J"))
return VK_J;
if(keyName.EqualsIgnoreCase("VK_K"))
return VK_K;
if(keyName.EqualsIgnoreCase("VK_L"))
return VK_L;
if(keyName.EqualsIgnoreCase("VK_M"))
return VK_M;
if(keyName.EqualsIgnoreCase("VK_N"))
return VK_N;
if(keyName.EqualsIgnoreCase("VK_O"))
return VK_O;
if(keyName.EqualsIgnoreCase("VK_P"))
return VK_P;
if(keyName.EqualsIgnoreCase("VK_Q"))
return VK_Q;
if(keyName.EqualsIgnoreCase("VK_R"))
return VK_R;
if(keyName.EqualsIgnoreCase("VK_S"))
return VK_S;
if(keyName.EqualsIgnoreCase("VK_T"))
return VK_T;
if(keyName.EqualsIgnoreCase("VK_U"))
return VK_U;
if(keyName.EqualsIgnoreCase("VK_V"))
return VK_V;
if(keyName.EqualsIgnoreCase("VK_W"))
return VK_W;
if(keyName.EqualsIgnoreCase("VK_X"))
return VK_X;
if(keyName.EqualsIgnoreCase("VK_Y"))
return VK_Y;
if(keyName.EqualsIgnoreCase("VK_Z"))
return VK_Z;
if(keyName.EqualsIgnoreCase("VK_NUMPAD0"))
return VK_NUMPAD0;
if(keyName.EqualsIgnoreCase("VK_NUMPAD1"))
return VK_NUMPAD1;
if(keyName.EqualsIgnoreCase("VK_NUMPAD2"))
return VK_NUMPAD2;
if(keyName.EqualsIgnoreCase("VK_NUMPAD3"))
return VK_NUMPAD3;
if(keyName.EqualsIgnoreCase("VK_NUMPAD4"))
return VK_NUMPAD4;
if(keyName.EqualsIgnoreCase("VK_NUMPAD5"))
return VK_NUMPAD5;
if(keyName.EqualsIgnoreCase("VK_NUMPAD6"))
return VK_NUMPAD6;
if(keyName.EqualsIgnoreCase("VK_NUMPAD7"))
return VK_NUMPAD7;
if(keyName.EqualsIgnoreCase("VK_NUMPAD8"))
return VK_NUMPAD8;
if(keyName.EqualsIgnoreCase("VK_NUMPAD9"))
return VK_NUMPAD9;
if(keyName.EqualsIgnoreCase("VK_MULTIPLY"))
return VK_MULTIPLY;
if(keyName.EqualsIgnoreCase("VK_ADD"))
return VK_ADD;
if(keyName.EqualsIgnoreCase("VK_SEPARATOR"))
return VK_SEPARATOR;
if(keyName.EqualsIgnoreCase("VK_SUBTRACT"))
return VK_SUBTRACT;
if(keyName.EqualsIgnoreCase("VK_DECIMAL"))
return VK_DECIMAL;
if(keyName.EqualsIgnoreCase("VK_DIVIDE"))
return VK_DIVIDE;
if(keyName.EqualsIgnoreCase("VK_F1"))
return VK_F1;
if(keyName.EqualsIgnoreCase("VK_F2"))
return VK_F2;
if(keyName.EqualsIgnoreCase("VK_F3"))
return VK_F3;
if(keyName.EqualsIgnoreCase("VK_F4"))
return VK_F4;
if(keyName.EqualsIgnoreCase("VK_F5"))
return VK_F5;
if(keyName.EqualsIgnoreCase("VK_F6"))
return VK_F6;
if(keyName.EqualsIgnoreCase("VK_F7"))
return VK_F7;
if(keyName.EqualsIgnoreCase("VK_F8"))
return VK_F8;
if(keyName.EqualsIgnoreCase("VK_F9"))
return VK_F9;
if(keyName.EqualsIgnoreCase("VK_F10"))
return VK_F10;
if(keyName.EqualsIgnoreCase("VK_F11"))
return VK_F11;
if(keyName.EqualsIgnoreCase("VK_F12"))
return VK_F12;
if(keyName.EqualsIgnoreCase("VK_F13"))
return VK_F13;
if(keyName.EqualsIgnoreCase("VK_F14"))
return VK_F14;
if(keyName.EqualsIgnoreCase("VK_F15"))
return VK_F15;
if(keyName.EqualsIgnoreCase("VK_F16"))
return VK_F16;
if(keyName.EqualsIgnoreCase("VK_F17"))
return VK_F17;
if(keyName.EqualsIgnoreCase("VK_F18"))
return VK_F18;
if(keyName.EqualsIgnoreCase("VK_F19"))
return VK_F19;
if(keyName.EqualsIgnoreCase("VK_F20"))
return VK_F20;
if(keyName.EqualsIgnoreCase("VK_F21"))
return VK_F21;
if(keyName.EqualsIgnoreCase("VK_F22"))
return VK_F22;
if(keyName.EqualsIgnoreCase("VK_F23"))
return VK_F23;
if(keyName.EqualsIgnoreCase("VK_F24"))
return VK_F24;
if(keyName.EqualsIgnoreCase("VK_NUM_LOCK"))
return VK_NUM_LOCK;
if(keyName.EqualsIgnoreCase("VK_SCROLL_LOCK"))
return VK_SCROLL_LOCK;
if(keyName.EqualsIgnoreCase("VK_COMMA"))
return VK_COMMA;
if(keyName.EqualsIgnoreCase("VK_PERIOD"))
return VK_PERIOD;
if(keyName.EqualsIgnoreCase("VK_SLASH"))
return VK_SLASH;
if(keyName.EqualsIgnoreCase("VK_BACK_QUOTE"))
return VK_BACK_QUOTE;
if(keyName.EqualsIgnoreCase("VK_OPEN_BRACKET"))
return VK_OPEN_BRACKET;
if(keyName.EqualsIgnoreCase("VK_BACK_SLASH"))
return VK_BACK_SLASH;
if(keyName.EqualsIgnoreCase("VK_CLOSE_BRACKET"))
return VK_CLOSE_BRACKET;
if(keyName.EqualsIgnoreCase("VK_QUOTE"))
return VK_QUOTE;
return 0;
}
nsresult
nsXBLEventHandler::GetTextData(nsIContent *aParent, nsString& aResult)
{
@ -1038,117 +609,14 @@ nsXBLEventHandler::GetTextData(nsIContent *aParent, nsString& aResult)
return NS_OK;
}
void
nsXBLEventHandler::ConstructMask()
{
mDetail = 0;
mDetail2 = 0;
mKeyMask = 0;
nsAutoString key;
mHandlerElement->GetAttribute(kNameSpaceID_None, kKeyAtom, key);
if (key.IsEmpty())
mHandlerElement->GetAttribute(kNameSpaceID_None, kCharCodeAtom, key);
if (!key.IsEmpty()) {
// We have a charcode.
mDetail2 = 1;
mDetail = key[0];
}
else {
mHandlerElement->GetAttribute(kNameSpaceID_None, kKeyCodeAtom, key);
if (!key.IsEmpty())
mDetail = GetMatchingKeyCode(key);
}
nsAutoString buttonStr, clickCountStr;
mHandlerElement->GetAttribute(kNameSpaceID_None, kClickCountAtom, clickCountStr);
mHandlerElement->GetAttribute(kNameSpaceID_None, kButtonAtom, buttonStr);
if (!buttonStr.IsEmpty()) {
PRInt32 error;
mDetail = buttonStr.ToInteger(&error);
}
if (!clickCountStr.IsEmpty()) {
PRInt32 error;
mDetail2 = clickCountStr.ToInteger(&error);
}
nsAutoString modifiers;
mHandlerElement->GetAttribute(kNameSpaceID_None, kModifiersAtom, modifiers);
if (modifiers.IsEmpty())
return;
char* str = modifiers.ToNewCString();
char* newStr;
char* token = nsCRT::strtok( str, ", ", &newStr );
while( token != NULL ) {
if (PL_strcmp(token, "shift") == 0)
mKeyMask |= cShift;
else if (PL_strcmp(token, "alt") == 0)
mKeyMask |= cAlt;
else if (PL_strcmp(token, "meta") == 0)
mKeyMask |= cMeta;
else if (PL_strcmp(token, "control") == 0)
mKeyMask |= cControl;
else if (PL_strcmp(token, "primary") == 0) {
switch (kAccessKey)
{
case nsIDOMKeyEvent::DOM_VK_META:
mKeyMask |= cMeta;
break;
case nsIDOMKeyEvent::DOM_VK_ALT:
mKeyMask |= cAlt;
break;
case nsIDOMKeyEvent::DOM_VK_CONTROL:
default:
mKeyMask |= cControl;
}
}
token = nsCRT::strtok( newStr, ", ", &newStr );
}
nsMemory::Free(str);
}
PRBool
nsXBLEventHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent)
{
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
PRBool keyPresent;
key ? key->GetMetaKey(&keyPresent) : mouse->GetMetaKey(&keyPresent);
if (keyPresent != ((mKeyMask & cMeta) != 0))
return PR_FALSE;
key ? key->GetShiftKey(&keyPresent) : mouse->GetShiftKey(&keyPresent);
if (keyPresent != ((mKeyMask & cShift) != 0))
return PR_FALSE;
key ? key->GetAltKey(&keyPresent) : mouse->GetAltKey(&keyPresent);
if (keyPresent != ((mKeyMask & cAlt) != 0))
return PR_FALSE;
key ? key->GetCtrlKey(&keyPresent) : mouse->GetCtrlKey(&keyPresent);
if (keyPresent != ((mKeyMask & cControl) != 0))
return PR_FALSE;
return PR_TRUE;
}
///////////////////////////////////////////////////////////////////////////////////
nsresult
NS_NewXBLEventHandler(nsIDOMEventReceiver* aRec, nsIContent* aHandlerElement,
NS_NewXBLEventHandler(nsIDOMEventReceiver* aRec, nsIXBLPrototypeHandler* aHandler,
const nsString& aEventName,
nsXBLEventHandler** aResult)
{
*aResult = new nsXBLEventHandler(aRec, aHandlerElement, aEventName);
*aResult = new nsXBLEventHandler(aRec, aHandler, aEventName);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);

Просмотреть файл

@ -40,6 +40,7 @@ class nsIDOMKeyEvent;
class nsIDOMMouseEvent;
class nsIAtom;
class nsIController;
class nsIXBLPrototypeHandler;
class nsXBLEventHandler : public nsIDOMKeyListener,
public nsIDOMMouseListener,
@ -48,7 +49,7 @@ class nsXBLEventHandler : public nsIDOMKeyListener,
public nsIDOMScrollListener
{
public:
nsXBLEventHandler(nsIDOMEventReceiver* aReceiver, nsIContent* aHandlerElement, const nsString& aEventName);
nsXBLEventHandler(nsIDOMEventReceiver* aReceiver, nsIXBLPrototypeHandler* aHandler, const nsString& aEventName);
virtual ~nsXBLEventHandler();
NS_IMETHOD BindingAttached();
@ -94,22 +95,13 @@ public:
void RemoveEventHandlers();
void MarkForDeath() {
if (mNextHandler) mNextHandler->MarkForDeath(); mHandlerElement = nsnull; mEventReceiver = nsnull;
if (mNextHandler) mNextHandler->MarkForDeath(); mProtoHandler = nsnull; mEventReceiver = nsnull;
}
protected:
inline PRBool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent);
inline PRBool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent);
inline PRUint32 GetMatchingKeyCode(const nsString& aKeyName);
NS_IMETHOD GetController(nsIController** aResult);
NS_IMETHOD ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEvent* aEvent);
void ConstructMask();
PRBool ModifiersMatchMask(nsIDOMUIEvent* aEvent);
static PRUint32 gRefCnt;
static nsIAtom* kKeyAtom;
static nsIAtom* kKeyCodeAtom;
@ -122,36 +114,19 @@ protected:
static nsIAtom* kBindingDetachedAtom;
static nsIAtom* kModifiersAtom;
static PRInt32 kAccessKey;
static void InitAccessKey();
static nsresult GetTextData(nsIContent *aParent, nsString& aResult);
static const PRInt32 cShift;
static const PRInt32 cAlt;
static const PRInt32 cControl;
static const PRInt32 cMeta;
protected:
nsIDOMEventReceiver* mEventReceiver; // Both of these refs are weak.
nsIContent* mHandlerElement;
nsIXBLPrototypeHandler* mProtoHandler;
nsAutoString mEventName;
PRInt32 mKeyMask; // Which modifier keys this event handler expects to have down
// in order to be matched.
PRUint32 mDetail; // For key events, contains a charcode or keycode. For
// mouse events, stores the button info.
PRInt32 mDetail2; // Miscellaneous extra information. For key events,
// stores whether or not we're a key code or char code.
// For mouse events, stores the clickCount.
nsXBLEventHandler* mNextHandler; // Handlers are chained for easy unloading later.
};
extern nsresult
NS_NewXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIContent* aHandlerElement,
NS_NewXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandlerElement,
const nsString& aEventName,
nsXBLEventHandler** aResult);

Просмотреть файл

@ -0,0 +1,719 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
*/
#include "nsCOMPtr.h"
#include "nsXBLPrototypeHandler.h"
#include "nsIContent.h"
#include "nsIAtom.h"
#include "nsIDOMKeyEvent.h"
#include "nsIDOMMouseEvent.h"
#include "nsINameSpaceManager.h"
#include "nsIScriptContext.h"
#include "nsIScriptObjectOwner.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIJSEventListener.h"
#include "nsIController.h"
#include "nsIControllers.h"
#include "nsIDOMXULElement.h"
#include "nsIDOMNSHTMLTextAreaElement.h"
#include "nsIDOMNSHTMLInputElement.h"
#include "nsIDOMText.h"
#include "nsIEventListenerManager.h"
#include "nsIDOMEventReceiver.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMWindowInternal.h"
#include "nsIPref.h"
#include "nsIServiceManager.h"
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
PRUint32 nsXBLPrototypeHandler::gRefCnt = 0;
nsIAtom* nsXBLPrototypeHandler::kKeyCodeAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kCharCodeAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kKeyAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kActionAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kCommandAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kClickCountAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kButtonAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kModifiersAtom = nsnull;
PRInt32 nsXBLPrototypeHandler::kAccessKey = -1;
const PRInt32 nsXBLPrototypeHandler::cShift = (1<<1);
const PRInt32 nsXBLPrototypeHandler::cAlt = (1<<2);
const PRInt32 nsXBLPrototypeHandler::cControl = (1<<3);
const PRInt32 nsXBLPrototypeHandler::cMeta = (1<<4);
nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement)
{
NS_INIT_REFCNT();
mHandlerElement = aHandlerElement;
gRefCnt++;
if (gRefCnt == 1) {
kKeyCodeAtom = NS_NewAtom("keycode");
kKeyAtom = NS_NewAtom("key");
kCharCodeAtom = NS_NewAtom("charcode");
kModifiersAtom = NS_NewAtom("modifiers");
kActionAtom = NS_NewAtom("action");
kCommandAtom = NS_NewAtom("command");
kClickCountAtom = NS_NewAtom("clickcount");
kButtonAtom = NS_NewAtom("button");
// Get the primary accelerator key.
InitAccessKey();
}
// Make sure our mask is initialized.
ConstructMask();
}
nsXBLPrototypeHandler::~nsXBLPrototypeHandler()
{
gRefCnt--;
if (gRefCnt == 0) {
NS_RELEASE(kKeyAtom);
NS_RELEASE(kKeyCodeAtom);
NS_RELEASE(kCharCodeAtom);
NS_RELEASE(kModifiersAtom);
NS_RELEASE(kActionAtom);
NS_RELEASE(kCommandAtom);
NS_RELEASE(kButtonAtom);
NS_RELEASE(kClickCountAtom);
}
}
NS_IMPL_ISUPPORTS1(nsXBLPrototypeHandler, nsIXBLPrototypeHandler)
NS_IMETHODIMP
nsXBLPrototypeHandler::EventMatched(nsIDOMEvent* aEvent, PRBool* aResult)
{
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
if (key)
*aResult = KeyEventMatched(key);
else {
nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
if (mouse)
*aResult = MouseEventMatched(mouse);
else *aResult = PR_TRUE;
}
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::GetHandlerElement(nsIContent** aResult)
{
*aResult = mHandlerElement;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::GetNextHandler(nsIXBLPrototypeHandler** aResult)
{
*aResult = mNextHandler;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::SetNextHandler(nsIXBLPrototypeHandler* aHandler)
{
mNextHandler = aHandler;
return NS_OK;
}
/////////////////////////////////////////////////////////////////////////////
// Get the menu access key from prefs.
// XXX Eventually pick up using CSS3 key-equivalent property or somesuch
void
nsXBLPrototypeHandler::InitAccessKey()
{
if (kAccessKey >= 0)
return;
// Compiled-in defaults, in case we can't get the pref --
// mac doesn't have menu shortcuts, other platforms use alt.
#ifndef XP_MAC
kAccessKey = nsIDOMKeyEvent::DOM_VK_ALT;
#else
kAccessKey = 0;
#endif
// Get the menu access key value from prefs, overriding the default:
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv);
if (NS_SUCCEEDED(rv) && prefs)
{
rv = prefs->GetIntPref("ui.key.menuAccessKey", &kAccessKey);
}
}
PRBool
nsXBLPrototypeHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent)
{
if (!mHandlerElement)
return PR_FALSE;
if (mDetail == 0 && mDetail2 == 0 && mKeyMask == 0)
return PR_TRUE; // No filters set up. It's generic.
// Get the keycode and charcode of the key event.
PRUint32 keyCode, charCode;
aKeyEvent->GetKeyCode(&keyCode);
aKeyEvent->GetCharCode(&charCode);
PRBool keyMatched = (mDetail == (mDetail2 ? charCode : keyCode));
if (!keyMatched)
return PR_FALSE;
// Now check modifier keys
return ModifiersMatchMask(aKeyEvent);
}
PRBool
nsXBLPrototypeHandler::MouseEventMatched(nsIDOMMouseEvent* aMouseEvent)
{
if (!mHandlerElement)
return PR_FALSE;
if (mDetail == 0 && mDetail2 == 0 && mKeyMask == 0)
return PR_TRUE; // No filters set up. It's generic.
unsigned short button;
aMouseEvent->GetButton(&button);
if (mDetail != 0 && (button != mDetail))
return PR_FALSE;
PRInt32 clickcount;
aMouseEvent->GetDetail(&clickcount);
if (mDetail2 != 0 && (clickcount != mDetail2))
return PR_FALSE;
return ModifiersMatchMask(aMouseEvent);
}
enum {
VK_CANCEL = 3,
VK_BACK = 8,
VK_TAB = 9,
VK_CLEAR = 12,
VK_RETURN = 13,
VK_ENTER = 14,
VK_SHIFT = 16,
VK_CONTROL = 17,
VK_ALT = 18,
VK_PAUSE = 19,
VK_CAPS_LOCK = 20,
VK_ESCAPE = 27,
VK_SPACE = 32,
VK_PAGE_UP = 33,
VK_PAGE_DOWN = 34,
VK_END = 35,
VK_HOME = 36,
VK_LEFT = 37,
VK_UP = 38,
VK_RIGHT = 39,
VK_DOWN = 40,
VK_PRINTSCREEN = 44,
VK_INSERT = 45,
VK_DELETE = 46,
VK_0 = 48,
VK_1 = 49,
VK_2 = 50,
VK_3 = 51,
VK_4 = 52,
VK_5 = 53,
VK_6 = 54,
VK_7 = 55,
VK_8 = 56,
VK_9 = 57,
VK_SEMICOLON = 59,
VK_EQUALS = 61,
VK_A = 65,
VK_B = 66,
VK_C = 67,
VK_D = 68,
VK_E = 69,
VK_F = 70,
VK_G = 71,
VK_H = 72,
VK_I = 73,
VK_J = 74,
VK_K = 75,
VK_L = 76,
VK_M = 77,
VK_N = 78,
VK_O = 79,
VK_P = 80,
VK_Q = 81,
VK_R = 82,
VK_S = 83,
VK_T = 84,
VK_U = 85,
VK_V = 86,
VK_W = 87,
VK_X = 88,
VK_Y = 89,
VK_Z = 90,
VK_NUMPAD0 = 96,
VK_NUMPAD1 = 97,
VK_NUMPAD2 = 98,
VK_NUMPAD3 = 99,
VK_NUMPAD4 = 100,
VK_NUMPAD5 = 101,
VK_NUMPAD6 = 102,
VK_NUMPAD7 = 103,
VK_NUMPAD8 = 104,
VK_NUMPAD9 = 105,
VK_MULTIPLY = 106,
VK_ADD = 107,
VK_SEPARATOR = 108,
VK_SUBTRACT = 109,
VK_DECIMAL = 110,
VK_DIVIDE = 111,
VK_F1 = 112,
VK_F2 = 113,
VK_F3 = 114,
VK_F4 = 115,
VK_F5 = 116,
VK_F6 = 117,
VK_F7 = 118,
VK_F8 = 119,
VK_F9 = 120,
VK_F10 = 121,
VK_F11 = 122,
VK_F12 = 123,
VK_F13 = 124,
VK_F14 = 125,
VK_F15 = 126,
VK_F16 = 127,
VK_F17 = 128,
VK_F18 = 129,
VK_F19 = 130,
VK_F20 = 131,
VK_F21 = 132,
VK_F22 = 133,
VK_F23 = 134,
VK_F24 = 135,
VK_NUM_LOCK = 144,
VK_SCROLL_LOCK = 145,
VK_COMMA = 188,
VK_PERIOD = 190,
VK_SLASH = 191,
VK_BACK_QUOTE = 192,
VK_OPEN_BRACKET = 219,
VK_BACK_SLASH = 220,
VK_CLOSE_BRACKET = 221,
VK_QUOTE = 222
};
PRUint32 nsXBLPrototypeHandler::GetMatchingKeyCode(const nsString& aKeyName)
{
PRBool ret = PR_FALSE;
nsCAutoString keyName; keyName.AssignWithConversion(aKeyName);
if (keyName.EqualsIgnoreCase("VK_CANCEL"))
return VK_CANCEL;
if(keyName.EqualsIgnoreCase("VK_BACK"))
return VK_BACK;
if(keyName.EqualsIgnoreCase("VK_TAB"))
return VK_TAB;
if(keyName.EqualsIgnoreCase("VK_CLEAR"))
return VK_CLEAR;
if(keyName.EqualsIgnoreCase("VK_RETURN"))
return VK_RETURN;
if(keyName.EqualsIgnoreCase("VK_ENTER"))
return VK_ENTER;
if(keyName.EqualsIgnoreCase("VK_SHIFT"))
return VK_SHIFT;
if(keyName.EqualsIgnoreCase("VK_CONTROL"))
return VK_CONTROL;
if(keyName.EqualsIgnoreCase("VK_ALT"))
return VK_ALT;
if(keyName.EqualsIgnoreCase("VK_PAUSE"))
return VK_PAUSE;
if(keyName.EqualsIgnoreCase("VK_CAPS_LOCK"))
return VK_CAPS_LOCK;
if(keyName.EqualsIgnoreCase("VK_ESCAPE"))
return VK_ESCAPE;
if(keyName.EqualsIgnoreCase("VK_SPACE"))
return VK_SPACE;
if(keyName.EqualsIgnoreCase("VK_PAGE_UP"))
return VK_PAGE_UP;
if(keyName.EqualsIgnoreCase("VK_PAGE_DOWN"))
return VK_PAGE_DOWN;
if(keyName.EqualsIgnoreCase("VK_END"))
return VK_END;
if(keyName.EqualsIgnoreCase("VK_HOME"))
return VK_HOME;
if(keyName.EqualsIgnoreCase("VK_LEFT"))
return VK_LEFT;
if(keyName.EqualsIgnoreCase("VK_UP"))
return VK_UP;
if(keyName.EqualsIgnoreCase("VK_RIGHT"))
return VK_RIGHT;
if(keyName.EqualsIgnoreCase("VK_DOWN"))
return VK_DOWN;
if(keyName.EqualsIgnoreCase("VK_PRINTSCREEN"))
return VK_PRINTSCREEN;
if(keyName.EqualsIgnoreCase("VK_INSERT"))
return VK_INSERT;
if(keyName.EqualsIgnoreCase("VK_DELETE"))
return VK_DELETE;
if(keyName.EqualsIgnoreCase("VK_0"))
return VK_0;
if(keyName.EqualsIgnoreCase("VK_1"))
return VK_1;
if(keyName.EqualsIgnoreCase("VK_2"))
return VK_2;
if(keyName.EqualsIgnoreCase("VK_3"))
return VK_3;
if(keyName.EqualsIgnoreCase("VK_4"))
return VK_4;
if(keyName.EqualsIgnoreCase("VK_5"))
return VK_5;
if(keyName.EqualsIgnoreCase("VK_6"))
return VK_6;
if(keyName.EqualsIgnoreCase("VK_7"))
return VK_7;
if(keyName.EqualsIgnoreCase("VK_8"))
return VK_8;
if(keyName.EqualsIgnoreCase("VK_9"))
return VK_9;
if(keyName.EqualsIgnoreCase("VK_SEMICOLON"))
return VK_SEMICOLON;
if(keyName.EqualsIgnoreCase("VK_EQUALS"))
return VK_EQUALS;
if(keyName.EqualsIgnoreCase("VK_A"))
return VK_A;
if(keyName.EqualsIgnoreCase("VK_B"))
return VK_B;
if(keyName.EqualsIgnoreCase("VK_C"))
return VK_C;
if(keyName.EqualsIgnoreCase("VK_D"))
return VK_D;
if(keyName.EqualsIgnoreCase("VK_E"))
return VK_E;
if(keyName.EqualsIgnoreCase("VK_F"))
return VK_F;
if(keyName.EqualsIgnoreCase("VK_G"))
return VK_G;
if(keyName.EqualsIgnoreCase("VK_H"))
return VK_H;
if(keyName.EqualsIgnoreCase("VK_I"))
return VK_I;
if(keyName.EqualsIgnoreCase("VK_J"))
return VK_J;
if(keyName.EqualsIgnoreCase("VK_K"))
return VK_K;
if(keyName.EqualsIgnoreCase("VK_L"))
return VK_L;
if(keyName.EqualsIgnoreCase("VK_M"))
return VK_M;
if(keyName.EqualsIgnoreCase("VK_N"))
return VK_N;
if(keyName.EqualsIgnoreCase("VK_O"))
return VK_O;
if(keyName.EqualsIgnoreCase("VK_P"))
return VK_P;
if(keyName.EqualsIgnoreCase("VK_Q"))
return VK_Q;
if(keyName.EqualsIgnoreCase("VK_R"))
return VK_R;
if(keyName.EqualsIgnoreCase("VK_S"))
return VK_S;
if(keyName.EqualsIgnoreCase("VK_T"))
return VK_T;
if(keyName.EqualsIgnoreCase("VK_U"))
return VK_U;
if(keyName.EqualsIgnoreCase("VK_V"))
return VK_V;
if(keyName.EqualsIgnoreCase("VK_W"))
return VK_W;
if(keyName.EqualsIgnoreCase("VK_X"))
return VK_X;
if(keyName.EqualsIgnoreCase("VK_Y"))
return VK_Y;
if(keyName.EqualsIgnoreCase("VK_Z"))
return VK_Z;
if(keyName.EqualsIgnoreCase("VK_NUMPAD0"))
return VK_NUMPAD0;
if(keyName.EqualsIgnoreCase("VK_NUMPAD1"))
return VK_NUMPAD1;
if(keyName.EqualsIgnoreCase("VK_NUMPAD2"))
return VK_NUMPAD2;
if(keyName.EqualsIgnoreCase("VK_NUMPAD3"))
return VK_NUMPAD3;
if(keyName.EqualsIgnoreCase("VK_NUMPAD4"))
return VK_NUMPAD4;
if(keyName.EqualsIgnoreCase("VK_NUMPAD5"))
return VK_NUMPAD5;
if(keyName.EqualsIgnoreCase("VK_NUMPAD6"))
return VK_NUMPAD6;
if(keyName.EqualsIgnoreCase("VK_NUMPAD7"))
return VK_NUMPAD7;
if(keyName.EqualsIgnoreCase("VK_NUMPAD8"))
return VK_NUMPAD8;
if(keyName.EqualsIgnoreCase("VK_NUMPAD9"))
return VK_NUMPAD9;
if(keyName.EqualsIgnoreCase("VK_MULTIPLY"))
return VK_MULTIPLY;
if(keyName.EqualsIgnoreCase("VK_ADD"))
return VK_ADD;
if(keyName.EqualsIgnoreCase("VK_SEPARATOR"))
return VK_SEPARATOR;
if(keyName.EqualsIgnoreCase("VK_SUBTRACT"))
return VK_SUBTRACT;
if(keyName.EqualsIgnoreCase("VK_DECIMAL"))
return VK_DECIMAL;
if(keyName.EqualsIgnoreCase("VK_DIVIDE"))
return VK_DIVIDE;
if(keyName.EqualsIgnoreCase("VK_F1"))
return VK_F1;
if(keyName.EqualsIgnoreCase("VK_F2"))
return VK_F2;
if(keyName.EqualsIgnoreCase("VK_F3"))
return VK_F3;
if(keyName.EqualsIgnoreCase("VK_F4"))
return VK_F4;
if(keyName.EqualsIgnoreCase("VK_F5"))
return VK_F5;
if(keyName.EqualsIgnoreCase("VK_F6"))
return VK_F6;
if(keyName.EqualsIgnoreCase("VK_F7"))
return VK_F7;
if(keyName.EqualsIgnoreCase("VK_F8"))
return VK_F8;
if(keyName.EqualsIgnoreCase("VK_F9"))
return VK_F9;
if(keyName.EqualsIgnoreCase("VK_F10"))
return VK_F10;
if(keyName.EqualsIgnoreCase("VK_F11"))
return VK_F11;
if(keyName.EqualsIgnoreCase("VK_F12"))
return VK_F12;
if(keyName.EqualsIgnoreCase("VK_F13"))
return VK_F13;
if(keyName.EqualsIgnoreCase("VK_F14"))
return VK_F14;
if(keyName.EqualsIgnoreCase("VK_F15"))
return VK_F15;
if(keyName.EqualsIgnoreCase("VK_F16"))
return VK_F16;
if(keyName.EqualsIgnoreCase("VK_F17"))
return VK_F17;
if(keyName.EqualsIgnoreCase("VK_F18"))
return VK_F18;
if(keyName.EqualsIgnoreCase("VK_F19"))
return VK_F19;
if(keyName.EqualsIgnoreCase("VK_F20"))
return VK_F20;
if(keyName.EqualsIgnoreCase("VK_F21"))
return VK_F21;
if(keyName.EqualsIgnoreCase("VK_F22"))
return VK_F22;
if(keyName.EqualsIgnoreCase("VK_F23"))
return VK_F23;
if(keyName.EqualsIgnoreCase("VK_F24"))
return VK_F24;
if(keyName.EqualsIgnoreCase("VK_NUM_LOCK"))
return VK_NUM_LOCK;
if(keyName.EqualsIgnoreCase("VK_SCROLL_LOCK"))
return VK_SCROLL_LOCK;
if(keyName.EqualsIgnoreCase("VK_COMMA"))
return VK_COMMA;
if(keyName.EqualsIgnoreCase("VK_PERIOD"))
return VK_PERIOD;
if(keyName.EqualsIgnoreCase("VK_SLASH"))
return VK_SLASH;
if(keyName.EqualsIgnoreCase("VK_BACK_QUOTE"))
return VK_BACK_QUOTE;
if(keyName.EqualsIgnoreCase("VK_OPEN_BRACKET"))
return VK_OPEN_BRACKET;
if(keyName.EqualsIgnoreCase("VK_BACK_SLASH"))
return VK_BACK_SLASH;
if(keyName.EqualsIgnoreCase("VK_CLOSE_BRACKET"))
return VK_CLOSE_BRACKET;
if(keyName.EqualsIgnoreCase("VK_QUOTE"))
return VK_QUOTE;
return 0;
}
void
nsXBLPrototypeHandler::ConstructMask()
{
mDetail = 0;
mDetail2 = 0;
mKeyMask = 0;
nsAutoString key;
mHandlerElement->GetAttribute(kNameSpaceID_None, kKeyAtom, key);
if (key.IsEmpty())
mHandlerElement->GetAttribute(kNameSpaceID_None, kCharCodeAtom, key);
if (!key.IsEmpty()) {
// We have a charcode.
mDetail2 = 1;
mDetail = key[0];
}
else {
mHandlerElement->GetAttribute(kNameSpaceID_None, kKeyCodeAtom, key);
if (!key.IsEmpty())
mDetail = GetMatchingKeyCode(key);
}
nsAutoString buttonStr, clickCountStr;
mHandlerElement->GetAttribute(kNameSpaceID_None, kClickCountAtom, clickCountStr);
mHandlerElement->GetAttribute(kNameSpaceID_None, kButtonAtom, buttonStr);
if (!buttonStr.IsEmpty()) {
PRInt32 error;
mDetail = buttonStr.ToInteger(&error);
}
if (!clickCountStr.IsEmpty()) {
PRInt32 error;
mDetail2 = clickCountStr.ToInteger(&error);
}
nsAutoString modifiers;
mHandlerElement->GetAttribute(kNameSpaceID_None, kModifiersAtom, modifiers);
if (modifiers.IsEmpty())
return;
char* str = modifiers.ToNewCString();
char* newStr;
char* token = nsCRT::strtok( str, ", ", &newStr );
while( token != NULL ) {
if (PL_strcmp(token, "shift") == 0)
mKeyMask |= cShift;
else if (PL_strcmp(token, "alt") == 0)
mKeyMask |= cAlt;
else if (PL_strcmp(token, "meta") == 0)
mKeyMask |= cMeta;
else if (PL_strcmp(token, "control") == 0)
mKeyMask |= cControl;
else if (PL_strcmp(token, "primary") == 0) {
switch (kAccessKey)
{
case nsIDOMKeyEvent::DOM_VK_META:
mKeyMask |= cMeta;
break;
case nsIDOMKeyEvent::DOM_VK_ALT:
mKeyMask |= cAlt;
break;
case nsIDOMKeyEvent::DOM_VK_CONTROL:
default:
mKeyMask |= cControl;
}
}
token = nsCRT::strtok( newStr, ", ", &newStr );
}
nsMemory::Free(str);
}
PRBool
nsXBLPrototypeHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent)
{
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
PRBool keyPresent;
key ? key->GetMetaKey(&keyPresent) : mouse->GetMetaKey(&keyPresent);
if (keyPresent != ((mKeyMask & cMeta) != 0))
return PR_FALSE;
key ? key->GetShiftKey(&keyPresent) : mouse->GetShiftKey(&keyPresent);
if (keyPresent != ((mKeyMask & cShift) != 0))
return PR_FALSE;
key ? key->GetAltKey(&keyPresent) : mouse->GetAltKey(&keyPresent);
if (keyPresent != ((mKeyMask & cAlt) != 0))
return PR_FALSE;
key ? key->GetCtrlKey(&keyPresent) : mouse->GetCtrlKey(&keyPresent);
if (keyPresent != ((mKeyMask & cControl) != 0))
return PR_FALSE;
return PR_TRUE;
}
///////////////////////////////////////////////////////////////////////////////////
nsresult
NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult)
{
*aResult = new nsXBLPrototypeHandler(aHandlerElement);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,98 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s):
*/
#ifndef nsXBLPrototypeHandler_h__
#define nsXBLPrototypeHandler_h__
#include "nsIXBLPrototypeHandler.h"
class nsIXBLBinding;
class nsIDOMEvent;
class nsIContent;
class nsIDOMUIEvent;
class nsIDOMKeyEvent;
class nsIDOMMouseEvent;
class nsIAtom;
class nsString;
class nsXBLPrototypeHandler : public nsIXBLPrototypeHandler
{
public:
nsXBLPrototypeHandler(nsIContent* aHandlerElement);
virtual ~nsXBLPrototypeHandler();
NS_DECL_ISUPPORTS
NS_IMETHOD EventMatched(nsIDOMEvent* aEvent, PRBool* aResult);
NS_IMETHOD GetHandlerElement(nsIContent** aResult);
NS_IMETHOD GetNextHandler(nsIXBLPrototypeHandler** aResult);
NS_IMETHOD SetNextHandler(nsIXBLPrototypeHandler* aHandler);
protected:
inline PRUint32 GetMatchingKeyCode(const nsString& aKeyName);
void ConstructMask();
PRBool ModifiersMatchMask(nsIDOMUIEvent* aEvent);
inline PRBool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent);
inline PRBool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent);
static PRUint32 gRefCnt;
static nsIAtom* kKeyAtom;
static nsIAtom* kKeyCodeAtom;
static nsIAtom* kCharCodeAtom;
static nsIAtom* kActionAtom;
static nsIAtom* kCommandAtom;
static nsIAtom* kClickCountAtom;
static nsIAtom* kButtonAtom;
static nsIAtom* kModifiersAtom;
static PRInt32 kAccessKey;
static void InitAccessKey();
static const PRInt32 cShift;
static const PRInt32 cAlt;
static const PRInt32 cControl;
static const PRInt32 cMeta;
protected:
nsIContent* mHandlerElement; // This ref is weak.
PRInt32 mKeyMask; // Which modifier keys this event handler expects to have down
// in order to be matched.
PRUint32 mDetail; // For key events, contains a charcode or keycode. For
// mouse events, stores the button info.
PRInt32 mDetail2; // Miscellaneous extra information. For key events,
// stores whether or not we're a key code or char code.
// For mouse events, stores the clickCount.
nsCOMPtr<nsIXBLPrototypeHandler> mNextHandler; // Prototype handlers are chained. We own the next handler in the chain.
};
extern nsresult
NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult);
#endif

Просмотреть файл

@ -51,6 +51,8 @@
#include "nsIXBLBinding.h"
#include "nsIXBLDocumentInfo.h"
#include "nsIXBLPrototypeHandler.h"
#include "nsIChromeRegistry.h"
#include "nsIPref.h"
@ -325,11 +327,18 @@ nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
nsCOMPtr<nsIContent> root = getter_AddRefs(mBindingDocument->GetRootContent());
if (root)
nsXBLService::StripWhitespaceNodes(root);
else {
NS_ERROR("*** XBL doc with no root element! Something went horribly wrong! ***");
return NS_ERROR_FAILURE;
}
// Put our doc in the doc table.
nsCOMPtr<nsIXBLDocumentInfo> info;
NS_NewXBLDocumentInfo(mBindingDocument, getter_AddRefs(info));
// Construct our prototype handlers.
nsXBLService::ConstructPrototypeHandlers(info);
// If the doc is a chrome URI, then we put it into the XUL cache.
PRBool cached = PR_FALSE;
if (IsChromeURI(uri) && gXULUtils->UseXULCache()) {
@ -470,6 +479,7 @@ PRUint32 nsXBLService::gClassLRUListLength = 0;
PRUint32 nsXBLService::gClassLRUListQuota = 64;
nsIAtom* nsXBLService::kExtendsAtom = nsnull;
nsIAtom* nsXBLService::kHandlersAtom = nsnull;
nsIAtom* nsXBLService::kScrollbarAtom = nsnull;
nsIAtom* nsXBLService::kInputAtom = nsnull;
@ -509,6 +519,7 @@ nsXBLService::nsXBLService(void)
// Create our atoms
kExtendsAtom = NS_NewAtom("extends");
kHandlersAtom = NS_NewAtom("handlers");
kScrollbarAtom = NS_NewAtom("scrollbar");
kInputAtom = NS_NewAtom("input");
@ -544,6 +555,7 @@ nsXBLService::~nsXBLService(void)
// Release our atoms
NS_RELEASE(kExtendsAtom);
NS_RELEASE(kHandlersAtom);
NS_RELEASE(kScrollbarAtom);
NS_RELEASE(kInputAtom);
@ -999,6 +1011,9 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement, nsIDocument* aB
if (document) {
NS_NewXBLDocumentInfo(document, getter_AddRefs(info));
// Construct our prototype handlers.
ConstructPrototypeHandlers(info);
// If the doc is a chrome URI, then we put it into the XUL cache.
PRBool cached = PR_FALSE;
@ -1183,6 +1198,74 @@ nsXBLService::StripWhitespaceNodes(nsIContent* aElement)
return NS_OK;
}
static void GetImmediateChild(nsIAtom* aTag, nsIContent* aParent, nsIContent** aResult)
{
*aResult = nsnull;
PRInt32 childCount;
aParent->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> child;
aParent->ChildAt(i, *getter_AddRefs(child));
nsCOMPtr<nsIAtom> tag;
child->GetTag(*getter_AddRefs(tag));
if (aTag == tag.get()) {
*aResult = child;
NS_ADDREF(*aResult);
return;
}
}
}
nsresult
nsXBLService::ConstructPrototypeHandlers(nsIXBLDocumentInfo* aInfo)
{
nsCOMPtr<nsIDocument> doc;
aInfo->GetDocument(getter_AddRefs(doc));
nsCOMPtr<nsIContent> bindings = getter_AddRefs(doc->GetRootContent());
PRInt32 childCount;
bindings->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> binding;
bindings->ChildAt(i, *getter_AddRefs(binding));
// See if this binding has a handler elt.
nsCOMPtr<nsIContent> handlers;
GetImmediateChild(kHandlersAtom, binding, getter_AddRefs(handlers));
if (handlers) {
nsCOMPtr<nsIXBLPrototypeHandler> firstHandler;
nsCOMPtr<nsIXBLPrototypeHandler> currHandler;
PRInt32 handlerCount;
handlers->ChildCount(handlerCount);
for (PRInt32 j = 0; j < handlerCount; j++) {
nsCOMPtr<nsIContent> handler;
handlers->ChildAt(j, *getter_AddRefs(handler));
nsCOMPtr<nsIXBLPrototypeHandler> newHandler;
NS_NewXBLPrototypeHandler(handler, getter_AddRefs(newHandler));
if (newHandler) {
if (currHandler)
currHandler->SetNextHandler(newHandler);
else firstHandler = newHandler;
currHandler = newHandler;
}
}
if (firstHandler) {
nsAutoString ref;
binding->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, ref);
nsCAutoString cref;
cref.AssignWithConversion(ref);
aInfo->SetPrototypeHandler(cref, firstHandler);
}
}
}
return NS_OK;
}
// Creation Routine ///////////////////////////////////////////////////////////////////////
nsresult

Просмотреть файл

@ -96,6 +96,7 @@ public:
// This method walks a binding document and removes any text nodes
// that contain only whitespace.
static nsresult StripWhitespaceNodes(nsIContent* aContent);
static nsresult ConstructPrototypeHandlers(nsIXBLDocumentInfo* aInfo);
// MEMBER VARIABLES
public:
@ -117,7 +118,7 @@ public:
// XBL Atoms
static nsIAtom* kExtendsAtom;
static nsIAtom* kHandlersAtom;
static nsIAtom* kScrollbarAtom;
static nsIAtom* kInputAtom;

Просмотреть файл

@ -33,6 +33,7 @@ EXPORTS = \
nsIXBLBinding.h \
nsIXBLBindingAttachedHandler.h \
nsIXBLDocumentInfo.h \
nsIXBLPrototypeHandler.h \
nsIXBLService.h \
$(NULL)

Просмотреть файл

@ -2,5 +2,6 @@ nsIBindingManager.h
nsIXBLBinding.h
nsIXBLBindingAttachedHandler.h
nsIXBLDocumentInfo.h
nsIXBLPrototypeHandler.h
nsIXBLService.h

Просмотреть файл

@ -26,6 +26,7 @@ EXPORTS = \
nsIXBLBinding.h \
nsIXBLBindingAttachedHandler.h \
nsIXBLDocumentInfo.h \
nsIXBLPrototypeHandler.h \
nsIXBLService.h \
$(NULL)

Просмотреть файл

@ -38,6 +38,7 @@
class nsIContent;
class nsIDocument;
class nsIScriptContext;
class nsIXBLPrototypeHandler;
// {5C4D9674-A2CF-4ddf-9F65-E1806C34D28D}
#define NS_IXBLDOCUMENTINFO_IID \
@ -54,6 +55,8 @@ public:
NS_IMETHOD GetScriptAccess(PRBool* aResult)=0;
NS_IMETHOD SetScriptAccess(PRBool aAccess)=0;
NS_IMETHOD GetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler** aResult)=0;
NS_IMETHOD SetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler* aHandler)=0;
};
extern nsresult

Просмотреть файл

@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s):
*/
/*
Private interface to the XBL PrototypeHandler
*/
#ifndef nsIXBLPrototypeHandler_h__
#define nsIXBLPrototypeHandler_h__
class nsIContent;
class nsIDOMEvent;
// {921812E7-A044-4bd8-B49E-69BB0A607202}
#define NS_IXBLPROTOTYPEHANDLER_IID \
{ 0x921812e7, 0xa044, 0x4bd8, { 0xb4, 0x9e, 0x69, 0xbb, 0xa, 0x60, 0x72, 0x2 } }
class nsIXBLPrototypeHandler : public nsISupports
{
public:
static const nsIID& GetIID() { static nsIID iid = NS_IXBLPROTOTYPEHANDLER_IID; return iid; }
NS_IMETHOD EventMatched(nsIDOMEvent* aEvent, PRBool* aResult) = 0;
NS_IMETHOD GetHandlerElement(nsIContent** aResult) = 0;
NS_IMETHOD GetNextHandler(nsIXBLPrototypeHandler** aResult) = 0;
NS_IMETHOD SetNextHandler(nsIXBLPrototypeHandler* aHandler) = 0;
};
extern nsresult
NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult);
#endif // nsIXBLPrototypeHandler_h__

Просмотреть файл

@ -32,6 +32,7 @@ LIBRARY_NAME = gkxbl_s
CPPSRCS = \
nsXBLBinding.cpp \
nsXBLEventHandler.cpp \
nsXBLPrototypeHandler.cpp \
nsXBLService.cpp \
nsBindingManager.cpp \
$(NULL)

Просмотреть файл

@ -30,12 +30,14 @@ CPPSRCS= \
nsXBLBinding.cpp \
nsXBLService.cpp \
nsXBLEventHandler.cpp \
nsXBLPrototypeHandler.cpp \
nsBindingManager.cpp \
$(NULL)
CPP_OBJS= \
.\$(OBJDIR)\nsXBLBinding.obj \
.\$(OBJDIR)\nsXBLEventHandler.obj \
.\$(OBJDIR)\nsXBLPrototypeHandler.obj \
.\$(OBJDIR)\nsXBLService.obj \
.\$(OBJDIR)\nsBindingManager.obj \
$(NULL)

Просмотреть файл

@ -58,6 +58,7 @@
#include "nsIStyleRuleProcessor.h"
#include "nsIStyleSet.h"
#include "nsIXBLPrototypeHandler.h"
// Static IIDs/CIDs. Try to minimize these.
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
@ -78,10 +79,14 @@ public:
NS_IMETHOD GetScriptAccess(PRBool* aResult) { *aResult = mScriptAccess; return NS_OK; };
NS_IMETHOD SetScriptAccess(PRBool aAccess) { mScriptAccess = aAccess; return NS_OK; };
NS_IMETHOD GetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler** aResult);
NS_IMETHOD SetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler* aHandler);
private:
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsISupportsArray> mRuleProcessors;
PRBool mScriptAccess;
nsSupportsHashtable* mHandlerTable;
};
/* Implementation file */
@ -93,12 +98,13 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument)
/* member initializers and constructor code */
mDocument = aDocument;
mScriptAccess = PR_TRUE;
mHandlerTable = nsnull;
}
nsXBLDocumentInfo::~nsXBLDocumentInfo()
{
/* destructor code */
delete mHandlerTable;
}
NS_IMETHODIMP
@ -136,7 +142,32 @@ nsXBLDocumentInfo::GetRuleProcessors(nsISupportsArray** aResult)
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsXBLDocumentInfo::GetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler** aResult)
{
*aResult = nsnull;
if (!mHandlerTable)
return NS_OK;
nsCStringKey key(aRef);
*aResult = NS_STATIC_CAST(nsIXBLPrototypeHandler*, mHandlerTable->Get(&key)); // Addref happens here.
return NS_OK;
}
NS_IMETHODIMP
nsXBLDocumentInfo::SetPrototypeHandler(const nsCString& aRef, nsIXBLPrototypeHandler* aHandler)
{
if (!mHandlerTable)
mHandlerTable = new nsSupportsHashtable();
nsCStringKey key(aRef);
mHandlerTable->Put(&key, aHandler);
return NS_OK;
}
nsresult NS_NewXBLDocumentInfo(nsIDocument* aDocument, nsIXBLDocumentInfo** aResult)
{
*aResult = new nsXBLDocumentInfo(aDocument);

Просмотреть файл

@ -67,6 +67,7 @@
#include "nsIDOMAttr.h"
#include "nsIDOMNamedNodeMap.h"
#include "nsIXBLPrototypeHandler.h"
#include "nsXBLEventHandler.h"
#include "nsXBLBinding.h"
@ -573,112 +574,123 @@ nsXBLBinding::GenerateAnonymousContent(nsIContent* aBoundElement)
NS_IMETHODIMP
nsXBLBinding::InstallEventHandlers(nsIContent* aBoundElement, nsIXBLBinding** aBinding)
{
// Fetch the handlers element for this binding.
nsCOMPtr<nsIContent> handlers;
GetImmediateChild(kHandlersAtom, getter_AddRefs(handlers));
// Don't install handlers if scripts aren't allowed.
if (!AllowScripts())
return NS_OK;
// Fetch the handlers prototypes for this binding.
nsCOMPtr<nsIXBLDocumentInfo> info;
gXBLService->GetXBLDocumentInfo(mDocURI, mBoundElement, getter_AddRefs(info));
if (!info)
return NS_OK;
nsCOMPtr<nsIXBLPrototypeHandler> handlerChain;
info->GetPrototypeHandler(mID, getter_AddRefs(handlerChain));
if (!handlerChain)
return NS_OK;
nsCOMPtr<nsIXBLPrototypeHandler> curr = handlerChain;
nsXBLEventHandler* currHandler = nsnull;
if (handlers && AllowScripts()) {
// Now walk the handlers and add event listeners to the bound
// element.
PRInt32 childCount;
handlers->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> child;
handlers->ChildAt(i, *getter_AddRefs(child));
// Fetch the type attribute.
// XXX Deal with a comma-separated list of types
nsAutoString type;
child->GetAttribute(kNameSpaceID_None, kEventAtom, type);
if (!type.IsEmpty()) {
nsIID iid;
PRBool found = PR_FALSE;
PRBool special = PR_FALSE;
nsCOMPtr<nsIAtom> eventAtom = getter_AddRefs(NS_NewAtom(type));
if (eventAtom.get() == kBindingAttachedAtom) {
*aBinding = this;
NS_ADDREF(*aBinding);
special = PR_TRUE;
while (curr) {
nsCOMPtr<nsIContent> child;
curr->GetHandlerElement(getter_AddRefs(child));
// Fetch the type attribute.
// XXX Deal with a comma-separated list of types
nsAutoString type;
child->GetAttribute(kNameSpaceID_None, kEventAtom, type);
if (!type.IsEmpty()) {
nsIID iid;
PRBool found = PR_FALSE;
PRBool special = PR_FALSE;
nsCOMPtr<nsIAtom> eventAtom = getter_AddRefs(NS_NewAtom(type));
if (eventAtom.get() == kBindingAttachedAtom) {
*aBinding = this;
NS_ADDREF(*aBinding);
special = PR_TRUE;
}
else
GetEventHandlerIID(eventAtom, &iid, &found);
if (found || special) {
// Add an event listener for mouse and key events only.
PRBool mouse = IsMouseHandler(type);
PRBool key = IsKeyHandler(type);
PRBool focus = IsFocusHandler(type);
PRBool xul = IsXULHandler(type);
PRBool scroll = IsScrollHandler(type);
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mBoundElement);
nsAutoString attachType;
child->GetAttribute(kNameSpaceID_None, kAttachToAtom, attachType);
if (attachType == NS_LITERAL_STRING("_document") ||
attachType == NS_LITERAL_STRING("_window"))
{
nsCOMPtr<nsIDocument> boundDoc;
mBoundElement->GetDocument(*getter_AddRefs(boundDoc));
if (attachType == NS_LITERAL_STRING("_window")) {
nsCOMPtr<nsIScriptGlobalObject> global;
boundDoc->GetScriptGlobalObject(getter_AddRefs(global));
receiver = do_QueryInterface(global);
}
else receiver = do_QueryInterface(boundDoc);
}
else
GetEventHandlerIID(eventAtom, &iid, &found);
if (found || special) {
// Add an event listener for mouse and key events only.
PRBool mouse = IsMouseHandler(type);
PRBool key = IsKeyHandler(type);
PRBool focus = IsFocusHandler(type);
PRBool xul = IsXULHandler(type);
PRBool scroll = IsScrollHandler(type);
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mBoundElement);
nsAutoString attachType;
child->GetAttribute(kNameSpaceID_None, kAttachToAtom, attachType);
if (attachType == NS_LITERAL_STRING("_document") ||
attachType == NS_LITERAL_STRING("_window"))
{
nsCOMPtr<nsIDocument> boundDoc;
mBoundElement->GetDocument(*getter_AddRefs(boundDoc));
if (attachType == NS_LITERAL_STRING("_window")) {
nsCOMPtr<nsIScriptGlobalObject> global;
boundDoc->GetScriptGlobalObject(getter_AddRefs(global));
receiver = do_QueryInterface(global);
}
else receiver = do_QueryInterface(boundDoc);
}
if (mouse || key || focus || xul || scroll || special) {
// Create a new nsXBLEventHandler.
nsXBLEventHandler* handler;
NS_NewXBLEventHandler(receiver, curr, type, &handler);
if (mouse || key || focus || xul || scroll || special) {
// Create a new nsXBLEventHandler.
nsXBLEventHandler* handler;
NS_NewXBLEventHandler(receiver, child, type, &handler);
// We chain all our event handlers together for easy
// removal later (if/when the binding dies).
if (!currHandler)
mFirstHandler = handler;
else
currHandler->SetNextHandler(handler);
// We chain all our event handlers together for easy
// removal later (if/when the binding dies).
if (!currHandler)
mFirstHandler = handler;
else
currHandler->SetNextHandler(handler);
currHandler = handler;
currHandler = handler;
// Figure out if we're using capturing or not.
PRBool useCapture = PR_FALSE;
nsAutoString capturer;
child->GetAttribute(kNameSpaceID_None, kPhaseAtom, capturer);
if (capturer == NS_LITERAL_STRING("capturing"))
useCapture = PR_TRUE;
// Figure out if we're using capturing or not.
PRBool useCapture = PR_FALSE;
nsAutoString capturer;
child->GetAttribute(kNameSpaceID_None, kPhaseAtom, capturer);
if (capturer == NS_LITERAL_STRING("capturing"))
useCapture = PR_TRUE;
// Add the event listener.
if (mouse)
receiver->AddEventListener(type, (nsIDOMMouseListener*)handler, useCapture);
else if(key)
receiver->AddEventListener(type, (nsIDOMKeyListener*)handler, useCapture);
else if(focus)
receiver->AddEventListener(type, (nsIDOMFocusListener*)handler, useCapture);
else if (xul)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
else if (scroll)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
// Add the event listener.
if (mouse)
receiver->AddEventListener(type, (nsIDOMMouseListener*)handler, useCapture);
else if(key)
receiver->AddEventListener(type, (nsIDOMKeyListener*)handler, useCapture);
else if(focus)
receiver->AddEventListener(type, (nsIDOMFocusListener*)handler, useCapture);
else if (xul)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
else if (scroll)
receiver->AddEventListener(type, (nsIDOMScrollListener*)handler, useCapture);
if (!special) // Let the listener manager hold on to the handler.
NS_RELEASE(handler);
}
else {
// Call AddScriptEventListener for other IID types
// XXX Want this to all go away!
NS_WARNING("***** Non-compliant XBL event listener attached! *****");
nsAutoString value;
child->GetAttribute(kNameSpaceID_None, kActionAtom, value);
if (value.IsEmpty())
GetTextData(child, value);
if (!special) // Let the listener manager hold on to the handler.
NS_RELEASE(handler);
}
else {
// Call AddScriptEventListener for other IID types
// XXX Want this to all go away!
NS_WARNING("***** Non-compliant XBL event listener attached! *****");
nsAutoString value;
child->GetAttribute(kNameSpaceID_None, kActionAtom, value);
if (value.IsEmpty())
GetTextData(child, value);
AddScriptEventListener(mBoundElement, eventAtom, value, iid);
}
AddScriptEventListener(mBoundElement, eventAtom, value, iid);
}
}
}
nsCOMPtr<nsIXBLPrototypeHandler> next;
curr->GetNextHandler(getter_AddRefs(next));
curr = next;
}
if (mNextBinding) {

Просмотреть файл

@ -23,6 +23,7 @@
*/
#include "nsCOMPtr.h"
#include "nsIXBLPrototypeHandler.h"
#include "nsXBLEventHandler.h"
#include "nsIContent.h"
#include "nsIAtom.h"
@ -63,19 +64,12 @@ nsIAtom* nsXBLEventHandler::kBindingAttachedAtom = nsnull;
nsIAtom* nsXBLEventHandler::kBindingDetachedAtom = nsnull;
nsIAtom* nsXBLEventHandler::kModifiersAtom = nsnull;
PRInt32 nsXBLEventHandler::kAccessKey = -1;
const PRInt32 nsXBLEventHandler::cShift = (1<<1);
const PRInt32 nsXBLEventHandler::cAlt = (1<<2);
const PRInt32 nsXBLEventHandler::cControl = (1<<3);
const PRInt32 nsXBLEventHandler::cMeta = (1<<4);
nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIContent* aHandlerElement,
nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandler,
const nsString& aEventName)
{
NS_INIT_REFCNT();
mEventReceiver = aEventReceiver;
mHandlerElement = aHandlerElement;
mProtoHandler = aHandler;
mEventName.Assign(aEventName);
mNextHandler = nsnull;
gRefCnt++;
@ -90,13 +84,7 @@ nsXBLEventHandler::nsXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsICon
kButtonAtom = NS_NewAtom("button");
kBindingAttachedAtom = NS_NewAtom("bindingattached");
kBindingDetachedAtom = NS_NewAtom("bindingdetached");
// Get the primary accelerator key.
InitAccessKey();
}
// Make sure our mask is initialized.
ConstructMask();
}
nsXBLEventHandler::~nsXBLEventHandler()
@ -166,6 +154,7 @@ nsXBLEventHandler::BindingAttached()
NS_IMETHODIMP
nsXBLEventHandler::BindingDetached()
{
// XXX Write me!!!!
return NS_OK;
}
@ -180,8 +169,11 @@ nsresult nsXBLEventHandler::KeyUp(nsIDOMEvent* aKeyEvent)
if (mEventName != NS_LITERAL_STRING("keyup"))
return NS_OK;
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
if (KeyEventMatched(keyEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aKeyEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("keyup"), aKeyEvent);
return NS_OK;
}
@ -191,8 +183,11 @@ nsresult nsXBLEventHandler::KeyDown(nsIDOMEvent* aKeyEvent)
if (mEventName != NS_LITERAL_STRING("keydown"))
return NS_OK;
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
if (KeyEventMatched(keyEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aKeyEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("keydown"), aKeyEvent);
return NS_OK;
}
@ -202,8 +197,11 @@ nsresult nsXBLEventHandler::KeyPress(nsIDOMEvent* aKeyEvent)
if (mEventName != NS_LITERAL_STRING("keypress"))
return NS_OK;
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aKeyEvent);
if (KeyEventMatched(keyEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aKeyEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("keypress"), aKeyEvent);
return NS_OK;
}
@ -213,8 +211,11 @@ nsresult nsXBLEventHandler::MouseDown(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("mousedown"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("mousedown"), aMouseEvent);
return NS_OK;
}
@ -224,8 +225,11 @@ nsresult nsXBLEventHandler::MouseUp(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("mouseup"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("mouseup"), aMouseEvent);
return NS_OK;
}
@ -235,8 +239,11 @@ nsresult nsXBLEventHandler::MouseClick(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("click"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("click"), aMouseEvent);
return NS_OK;
}
@ -246,8 +253,11 @@ nsresult nsXBLEventHandler::MouseDblClick(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("dblclick"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("dblclick"), aMouseEvent);
return NS_OK;
}
@ -257,8 +267,11 @@ nsresult nsXBLEventHandler::MouseOver(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("mouseover"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("mouseover"), aMouseEvent);
return NS_OK;
}
@ -268,8 +281,11 @@ nsresult nsXBLEventHandler::MouseOut(nsIDOMEvent* aMouseEvent)
if (mEventName != NS_LITERAL_STRING("mouseout"))
return NS_OK;
nsCOMPtr<nsIDOMMouseEvent> mouseEvent = do_QueryInterface(aMouseEvent);
if (MouseEventMatched(mouseEvent))
PRBool matched = PR_FALSE;
if (mProtoHandler)
mProtoHandler->EventMatched(aMouseEvent, &matched);
if (matched)
ExecuteHandler(NS_LITERAL_STRING("mouseout"), aMouseEvent);
return NS_OK;
}
@ -375,88 +391,22 @@ nsresult nsXBLEventHandler::Destroy(nsIDOMEvent* aEvent)
return NS_OK;
}
/////////////////////////////////////////////////////////////////////////////
// Get the menu access key from prefs.
// XXX Eventually pick up using CSS3 key-equivalent property or somesuch
void
nsXBLEventHandler::InitAccessKey()
{
if (kAccessKey >= 0)
return;
// Compiled-in defaults, in case we can't get the pref --
// mac doesn't have menu shortcuts, other platforms use alt.
#ifndef XP_MAC
kAccessKey = nsIDOMKeyEvent::DOM_VK_ALT;
#else
kAccessKey = 0;
#endif
// Get the menu access key value from prefs, overriding the default:
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv);
if (NS_SUCCEEDED(rv) && prefs)
{
rv = prefs->GetIntPref("ui.key.menuAccessKey", &kAccessKey);
}
}
PRBool
nsXBLEventHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent)
{
if (!mHandlerElement)
return PR_FALSE;
if (mDetail == 0 && mDetail2 == 0 && mKeyMask == 0)
return PR_TRUE; // No filters set up. It's generic.
// Get the keycode and charcode of the key event.
PRUint32 keyCode, charCode;
aKeyEvent->GetKeyCode(&keyCode);
aKeyEvent->GetCharCode(&charCode);
PRBool keyMatched = (mDetail == (mDetail2 ? charCode : keyCode));
if (!keyMatched)
return PR_FALSE;
// Now check modifier keys
return ModifiersMatchMask(aKeyEvent);
}
PRBool
nsXBLEventHandler::MouseEventMatched(nsIDOMMouseEvent* aMouseEvent)
{
if (!mHandlerElement)
return PR_FALSE;
if (mDetail == 0 && mDetail2 == 0 && mKeyMask == 0)
return PR_TRUE; // No filters set up. It's generic.
unsigned short button;
aMouseEvent->GetButton(&button);
if (mDetail != 0 && (button != mDetail))
return PR_FALSE;
PRInt32 clickcount;
aMouseEvent->GetDetail(&clickcount);
if (mDetail2 != 0 && (clickcount != mDetail2))
return PR_FALSE;
return ModifiersMatchMask(aMouseEvent);
}
NS_IMETHODIMP
nsXBLEventHandler::ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEvent* aEvent)
{
if (!mHandlerElement)
if (!mProtoHandler)
return NS_ERROR_FAILURE;
nsCOMPtr<nsIContent> handlerElement;
mProtoHandler->GetHandlerElement(getter_AddRefs(handlerElement));
if (!handlerElement)
return NS_ERROR_FAILURE;
// This is a special-case optimization to make command handling fast.
// It isn't really a part of XBL, but it helps speed things up.
nsAutoString command;
mHandlerElement->GetAttribute(kNameSpaceID_None, kCommandAtom, command);
handlerElement->GetAttribute(kNameSpaceID_None, kCommandAtom, command);
if (!command.IsEmpty()) {
// We are the default action for this command.
// Stop any other default action from executing.
@ -493,10 +443,10 @@ nsXBLEventHandler::ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEv
// Compile the event handler.
nsAutoString handlerText;
mHandlerElement->GetAttribute(kNameSpaceID_None, kActionAtom, handlerText);
handlerElement->GetAttribute(kNameSpaceID_None, kActionAtom, handlerText);
if (handlerText.IsEmpty()) {
// look to see if action content is contained by the handler element
GetTextData(mHandlerElement, handlerText);
GetTextData(handlerElement, handlerText);
if (handlerText.IsEmpty())
return NS_OK; // For whatever reason, they didn't give us anything to do.
}
@ -598,15 +548,22 @@ nsXBLEventHandler::RemoveEventHandlers()
}
// Figure out if we're using capturing or not.
if (!mProtoHandler)
return;
nsCOMPtr<nsIContent> handlerElement;
mProtoHandler->GetHandlerElement(getter_AddRefs(handlerElement));
if (!handlerElement)
return;
PRBool useCapture = PR_FALSE;
nsAutoString capturer;
mHandlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kPhaseAtom, capturer);
handlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kPhaseAtom, capturer);
if (capturer == NS_LITERAL_STRING("capturing"))
useCapture = PR_TRUE;
// XXX Will potentially be comma-separated
nsAutoString type;
mHandlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kEventAtom, type);
handlerElement->GetAttribute(kNameSpaceID_None, nsXBLBinding::kEventAtom, type);
// Figure out our type.
PRBool mouse = nsXBLBinding::IsMouseHandler(type);
@ -630,392 +587,6 @@ nsXBLEventHandler::RemoveEventHandlers()
/// Helpers that are relegated to the end of the file /////////////////////////////
enum {
VK_CANCEL = 3,
VK_BACK = 8,
VK_TAB = 9,
VK_CLEAR = 12,
VK_RETURN = 13,
VK_ENTER = 14,
VK_SHIFT = 16,
VK_CONTROL = 17,
VK_ALT = 18,
VK_PAUSE = 19,
VK_CAPS_LOCK = 20,
VK_ESCAPE = 27,
VK_SPACE = 32,
VK_PAGE_UP = 33,
VK_PAGE_DOWN = 34,
VK_END = 35,
VK_HOME = 36,
VK_LEFT = 37,
VK_UP = 38,
VK_RIGHT = 39,
VK_DOWN = 40,
VK_PRINTSCREEN = 44,
VK_INSERT = 45,
VK_DELETE = 46,
VK_0 = 48,
VK_1 = 49,
VK_2 = 50,
VK_3 = 51,
VK_4 = 52,
VK_5 = 53,
VK_6 = 54,
VK_7 = 55,
VK_8 = 56,
VK_9 = 57,
VK_SEMICOLON = 59,
VK_EQUALS = 61,
VK_A = 65,
VK_B = 66,
VK_C = 67,
VK_D = 68,
VK_E = 69,
VK_F = 70,
VK_G = 71,
VK_H = 72,
VK_I = 73,
VK_J = 74,
VK_K = 75,
VK_L = 76,
VK_M = 77,
VK_N = 78,
VK_O = 79,
VK_P = 80,
VK_Q = 81,
VK_R = 82,
VK_S = 83,
VK_T = 84,
VK_U = 85,
VK_V = 86,
VK_W = 87,
VK_X = 88,
VK_Y = 89,
VK_Z = 90,
VK_NUMPAD0 = 96,
VK_NUMPAD1 = 97,
VK_NUMPAD2 = 98,
VK_NUMPAD3 = 99,
VK_NUMPAD4 = 100,
VK_NUMPAD5 = 101,
VK_NUMPAD6 = 102,
VK_NUMPAD7 = 103,
VK_NUMPAD8 = 104,
VK_NUMPAD9 = 105,
VK_MULTIPLY = 106,
VK_ADD = 107,
VK_SEPARATOR = 108,
VK_SUBTRACT = 109,
VK_DECIMAL = 110,
VK_DIVIDE = 111,
VK_F1 = 112,
VK_F2 = 113,
VK_F3 = 114,
VK_F4 = 115,
VK_F5 = 116,
VK_F6 = 117,
VK_F7 = 118,
VK_F8 = 119,
VK_F9 = 120,
VK_F10 = 121,
VK_F11 = 122,
VK_F12 = 123,
VK_F13 = 124,
VK_F14 = 125,
VK_F15 = 126,
VK_F16 = 127,
VK_F17 = 128,
VK_F18 = 129,
VK_F19 = 130,
VK_F20 = 131,
VK_F21 = 132,
VK_F22 = 133,
VK_F23 = 134,
VK_F24 = 135,
VK_NUM_LOCK = 144,
VK_SCROLL_LOCK = 145,
VK_COMMA = 188,
VK_PERIOD = 190,
VK_SLASH = 191,
VK_BACK_QUOTE = 192,
VK_OPEN_BRACKET = 219,
VK_BACK_SLASH = 220,
VK_CLOSE_BRACKET = 221,
VK_QUOTE = 222
};
PRUint32 nsXBLEventHandler::GetMatchingKeyCode(const nsString& aKeyName)
{
PRBool ret = PR_FALSE;
nsCAutoString keyName; keyName.AssignWithConversion(aKeyName);
if (keyName.EqualsIgnoreCase("VK_CANCEL"))
return VK_CANCEL;
if(keyName.EqualsIgnoreCase("VK_BACK"))
return VK_BACK;
if(keyName.EqualsIgnoreCase("VK_TAB"))
return VK_TAB;
if(keyName.EqualsIgnoreCase("VK_CLEAR"))
return VK_CLEAR;
if(keyName.EqualsIgnoreCase("VK_RETURN"))
return VK_RETURN;
if(keyName.EqualsIgnoreCase("VK_ENTER"))
return VK_ENTER;
if(keyName.EqualsIgnoreCase("VK_SHIFT"))
return VK_SHIFT;
if(keyName.EqualsIgnoreCase("VK_CONTROL"))
return VK_CONTROL;
if(keyName.EqualsIgnoreCase("VK_ALT"))
return VK_ALT;
if(keyName.EqualsIgnoreCase("VK_PAUSE"))
return VK_PAUSE;
if(keyName.EqualsIgnoreCase("VK_CAPS_LOCK"))
return VK_CAPS_LOCK;
if(keyName.EqualsIgnoreCase("VK_ESCAPE"))
return VK_ESCAPE;
if(keyName.EqualsIgnoreCase("VK_SPACE"))
return VK_SPACE;
if(keyName.EqualsIgnoreCase("VK_PAGE_UP"))
return VK_PAGE_UP;
if(keyName.EqualsIgnoreCase("VK_PAGE_DOWN"))
return VK_PAGE_DOWN;
if(keyName.EqualsIgnoreCase("VK_END"))
return VK_END;
if(keyName.EqualsIgnoreCase("VK_HOME"))
return VK_HOME;
if(keyName.EqualsIgnoreCase("VK_LEFT"))
return VK_LEFT;
if(keyName.EqualsIgnoreCase("VK_UP"))
return VK_UP;
if(keyName.EqualsIgnoreCase("VK_RIGHT"))
return VK_RIGHT;
if(keyName.EqualsIgnoreCase("VK_DOWN"))
return VK_DOWN;
if(keyName.EqualsIgnoreCase("VK_PRINTSCREEN"))
return VK_PRINTSCREEN;
if(keyName.EqualsIgnoreCase("VK_INSERT"))
return VK_INSERT;
if(keyName.EqualsIgnoreCase("VK_DELETE"))
return VK_DELETE;
if(keyName.EqualsIgnoreCase("VK_0"))
return VK_0;
if(keyName.EqualsIgnoreCase("VK_1"))
return VK_1;
if(keyName.EqualsIgnoreCase("VK_2"))
return VK_2;
if(keyName.EqualsIgnoreCase("VK_3"))
return VK_3;
if(keyName.EqualsIgnoreCase("VK_4"))
return VK_4;
if(keyName.EqualsIgnoreCase("VK_5"))
return VK_5;
if(keyName.EqualsIgnoreCase("VK_6"))
return VK_6;
if(keyName.EqualsIgnoreCase("VK_7"))
return VK_7;
if(keyName.EqualsIgnoreCase("VK_8"))
return VK_8;
if(keyName.EqualsIgnoreCase("VK_9"))
return VK_9;
if(keyName.EqualsIgnoreCase("VK_SEMICOLON"))
return VK_SEMICOLON;
if(keyName.EqualsIgnoreCase("VK_EQUALS"))
return VK_EQUALS;
if(keyName.EqualsIgnoreCase("VK_A"))
return VK_A;
if(keyName.EqualsIgnoreCase("VK_B"))
return VK_B;
if(keyName.EqualsIgnoreCase("VK_C"))
return VK_C;
if(keyName.EqualsIgnoreCase("VK_D"))
return VK_D;
if(keyName.EqualsIgnoreCase("VK_E"))
return VK_E;
if(keyName.EqualsIgnoreCase("VK_F"))
return VK_F;
if(keyName.EqualsIgnoreCase("VK_G"))
return VK_G;
if(keyName.EqualsIgnoreCase("VK_H"))
return VK_H;
if(keyName.EqualsIgnoreCase("VK_I"))
return VK_I;
if(keyName.EqualsIgnoreCase("VK_J"))
return VK_J;
if(keyName.EqualsIgnoreCase("VK_K"))
return VK_K;
if(keyName.EqualsIgnoreCase("VK_L"))
return VK_L;
if(keyName.EqualsIgnoreCase("VK_M"))
return VK_M;
if(keyName.EqualsIgnoreCase("VK_N"))
return VK_N;
if(keyName.EqualsIgnoreCase("VK_O"))
return VK_O;
if(keyName.EqualsIgnoreCase("VK_P"))
return VK_P;
if(keyName.EqualsIgnoreCase("VK_Q"))
return VK_Q;
if(keyName.EqualsIgnoreCase("VK_R"))
return VK_R;
if(keyName.EqualsIgnoreCase("VK_S"))
return VK_S;
if(keyName.EqualsIgnoreCase("VK_T"))
return VK_T;
if(keyName.EqualsIgnoreCase("VK_U"))
return VK_U;
if(keyName.EqualsIgnoreCase("VK_V"))
return VK_V;
if(keyName.EqualsIgnoreCase("VK_W"))
return VK_W;
if(keyName.EqualsIgnoreCase("VK_X"))
return VK_X;
if(keyName.EqualsIgnoreCase("VK_Y"))
return VK_Y;
if(keyName.EqualsIgnoreCase("VK_Z"))
return VK_Z;
if(keyName.EqualsIgnoreCase("VK_NUMPAD0"))
return VK_NUMPAD0;
if(keyName.EqualsIgnoreCase("VK_NUMPAD1"))
return VK_NUMPAD1;
if(keyName.EqualsIgnoreCase("VK_NUMPAD2"))
return VK_NUMPAD2;
if(keyName.EqualsIgnoreCase("VK_NUMPAD3"))
return VK_NUMPAD3;
if(keyName.EqualsIgnoreCase("VK_NUMPAD4"))
return VK_NUMPAD4;
if(keyName.EqualsIgnoreCase("VK_NUMPAD5"))
return VK_NUMPAD5;
if(keyName.EqualsIgnoreCase("VK_NUMPAD6"))
return VK_NUMPAD6;
if(keyName.EqualsIgnoreCase("VK_NUMPAD7"))
return VK_NUMPAD7;
if(keyName.EqualsIgnoreCase("VK_NUMPAD8"))
return VK_NUMPAD8;
if(keyName.EqualsIgnoreCase("VK_NUMPAD9"))
return VK_NUMPAD9;
if(keyName.EqualsIgnoreCase("VK_MULTIPLY"))
return VK_MULTIPLY;
if(keyName.EqualsIgnoreCase("VK_ADD"))
return VK_ADD;
if(keyName.EqualsIgnoreCase("VK_SEPARATOR"))
return VK_SEPARATOR;
if(keyName.EqualsIgnoreCase("VK_SUBTRACT"))
return VK_SUBTRACT;
if(keyName.EqualsIgnoreCase("VK_DECIMAL"))
return VK_DECIMAL;
if(keyName.EqualsIgnoreCase("VK_DIVIDE"))
return VK_DIVIDE;
if(keyName.EqualsIgnoreCase("VK_F1"))
return VK_F1;
if(keyName.EqualsIgnoreCase("VK_F2"))
return VK_F2;
if(keyName.EqualsIgnoreCase("VK_F3"))
return VK_F3;
if(keyName.EqualsIgnoreCase("VK_F4"))
return VK_F4;
if(keyName.EqualsIgnoreCase("VK_F5"))
return VK_F5;
if(keyName.EqualsIgnoreCase("VK_F6"))
return VK_F6;
if(keyName.EqualsIgnoreCase("VK_F7"))
return VK_F7;
if(keyName.EqualsIgnoreCase("VK_F8"))
return VK_F8;
if(keyName.EqualsIgnoreCase("VK_F9"))
return VK_F9;
if(keyName.EqualsIgnoreCase("VK_F10"))
return VK_F10;
if(keyName.EqualsIgnoreCase("VK_F11"))
return VK_F11;
if(keyName.EqualsIgnoreCase("VK_F12"))
return VK_F12;
if(keyName.EqualsIgnoreCase("VK_F13"))
return VK_F13;
if(keyName.EqualsIgnoreCase("VK_F14"))
return VK_F14;
if(keyName.EqualsIgnoreCase("VK_F15"))
return VK_F15;
if(keyName.EqualsIgnoreCase("VK_F16"))
return VK_F16;
if(keyName.EqualsIgnoreCase("VK_F17"))
return VK_F17;
if(keyName.EqualsIgnoreCase("VK_F18"))
return VK_F18;
if(keyName.EqualsIgnoreCase("VK_F19"))
return VK_F19;
if(keyName.EqualsIgnoreCase("VK_F20"))
return VK_F20;
if(keyName.EqualsIgnoreCase("VK_F21"))
return VK_F21;
if(keyName.EqualsIgnoreCase("VK_F22"))
return VK_F22;
if(keyName.EqualsIgnoreCase("VK_F23"))
return VK_F23;
if(keyName.EqualsIgnoreCase("VK_F24"))
return VK_F24;
if(keyName.EqualsIgnoreCase("VK_NUM_LOCK"))
return VK_NUM_LOCK;
if(keyName.EqualsIgnoreCase("VK_SCROLL_LOCK"))
return VK_SCROLL_LOCK;
if(keyName.EqualsIgnoreCase("VK_COMMA"))
return VK_COMMA;
if(keyName.EqualsIgnoreCase("VK_PERIOD"))
return VK_PERIOD;
if(keyName.EqualsIgnoreCase("VK_SLASH"))
return VK_SLASH;
if(keyName.EqualsIgnoreCase("VK_BACK_QUOTE"))
return VK_BACK_QUOTE;
if(keyName.EqualsIgnoreCase("VK_OPEN_BRACKET"))
return VK_OPEN_BRACKET;
if(keyName.EqualsIgnoreCase("VK_BACK_SLASH"))
return VK_BACK_SLASH;
if(keyName.EqualsIgnoreCase("VK_CLOSE_BRACKET"))
return VK_CLOSE_BRACKET;
if(keyName.EqualsIgnoreCase("VK_QUOTE"))
return VK_QUOTE;
return 0;
}
nsresult
nsXBLEventHandler::GetTextData(nsIContent *aParent, nsString& aResult)
{
@ -1038,117 +609,14 @@ nsXBLEventHandler::GetTextData(nsIContent *aParent, nsString& aResult)
return NS_OK;
}
void
nsXBLEventHandler::ConstructMask()
{
mDetail = 0;
mDetail2 = 0;
mKeyMask = 0;
nsAutoString key;
mHandlerElement->GetAttribute(kNameSpaceID_None, kKeyAtom, key);
if (key.IsEmpty())
mHandlerElement->GetAttribute(kNameSpaceID_None, kCharCodeAtom, key);
if (!key.IsEmpty()) {
// We have a charcode.
mDetail2 = 1;
mDetail = key[0];
}
else {
mHandlerElement->GetAttribute(kNameSpaceID_None, kKeyCodeAtom, key);
if (!key.IsEmpty())
mDetail = GetMatchingKeyCode(key);
}
nsAutoString buttonStr, clickCountStr;
mHandlerElement->GetAttribute(kNameSpaceID_None, kClickCountAtom, clickCountStr);
mHandlerElement->GetAttribute(kNameSpaceID_None, kButtonAtom, buttonStr);
if (!buttonStr.IsEmpty()) {
PRInt32 error;
mDetail = buttonStr.ToInteger(&error);
}
if (!clickCountStr.IsEmpty()) {
PRInt32 error;
mDetail2 = clickCountStr.ToInteger(&error);
}
nsAutoString modifiers;
mHandlerElement->GetAttribute(kNameSpaceID_None, kModifiersAtom, modifiers);
if (modifiers.IsEmpty())
return;
char* str = modifiers.ToNewCString();
char* newStr;
char* token = nsCRT::strtok( str, ", ", &newStr );
while( token != NULL ) {
if (PL_strcmp(token, "shift") == 0)
mKeyMask |= cShift;
else if (PL_strcmp(token, "alt") == 0)
mKeyMask |= cAlt;
else if (PL_strcmp(token, "meta") == 0)
mKeyMask |= cMeta;
else if (PL_strcmp(token, "control") == 0)
mKeyMask |= cControl;
else if (PL_strcmp(token, "primary") == 0) {
switch (kAccessKey)
{
case nsIDOMKeyEvent::DOM_VK_META:
mKeyMask |= cMeta;
break;
case nsIDOMKeyEvent::DOM_VK_ALT:
mKeyMask |= cAlt;
break;
case nsIDOMKeyEvent::DOM_VK_CONTROL:
default:
mKeyMask |= cControl;
}
}
token = nsCRT::strtok( newStr, ", ", &newStr );
}
nsMemory::Free(str);
}
PRBool
nsXBLEventHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent)
{
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
PRBool keyPresent;
key ? key->GetMetaKey(&keyPresent) : mouse->GetMetaKey(&keyPresent);
if (keyPresent != ((mKeyMask & cMeta) != 0))
return PR_FALSE;
key ? key->GetShiftKey(&keyPresent) : mouse->GetShiftKey(&keyPresent);
if (keyPresent != ((mKeyMask & cShift) != 0))
return PR_FALSE;
key ? key->GetAltKey(&keyPresent) : mouse->GetAltKey(&keyPresent);
if (keyPresent != ((mKeyMask & cAlt) != 0))
return PR_FALSE;
key ? key->GetCtrlKey(&keyPresent) : mouse->GetCtrlKey(&keyPresent);
if (keyPresent != ((mKeyMask & cControl) != 0))
return PR_FALSE;
return PR_TRUE;
}
///////////////////////////////////////////////////////////////////////////////////
nsresult
NS_NewXBLEventHandler(nsIDOMEventReceiver* aRec, nsIContent* aHandlerElement,
NS_NewXBLEventHandler(nsIDOMEventReceiver* aRec, nsIXBLPrototypeHandler* aHandler,
const nsString& aEventName,
nsXBLEventHandler** aResult)
{
*aResult = new nsXBLEventHandler(aRec, aHandlerElement, aEventName);
*aResult = new nsXBLEventHandler(aRec, aHandler, aEventName);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);

Просмотреть файл

@ -40,6 +40,7 @@ class nsIDOMKeyEvent;
class nsIDOMMouseEvent;
class nsIAtom;
class nsIController;
class nsIXBLPrototypeHandler;
class nsXBLEventHandler : public nsIDOMKeyListener,
public nsIDOMMouseListener,
@ -48,7 +49,7 @@ class nsXBLEventHandler : public nsIDOMKeyListener,
public nsIDOMScrollListener
{
public:
nsXBLEventHandler(nsIDOMEventReceiver* aReceiver, nsIContent* aHandlerElement, const nsString& aEventName);
nsXBLEventHandler(nsIDOMEventReceiver* aReceiver, nsIXBLPrototypeHandler* aHandler, const nsString& aEventName);
virtual ~nsXBLEventHandler();
NS_IMETHOD BindingAttached();
@ -94,22 +95,13 @@ public:
void RemoveEventHandlers();
void MarkForDeath() {
if (mNextHandler) mNextHandler->MarkForDeath(); mHandlerElement = nsnull; mEventReceiver = nsnull;
if (mNextHandler) mNextHandler->MarkForDeath(); mProtoHandler = nsnull; mEventReceiver = nsnull;
}
protected:
inline PRBool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent);
inline PRBool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent);
inline PRUint32 GetMatchingKeyCode(const nsString& aKeyName);
NS_IMETHOD GetController(nsIController** aResult);
NS_IMETHOD ExecuteHandler(const nsAReadableString & aEventName, nsIDOMEvent* aEvent);
void ConstructMask();
PRBool ModifiersMatchMask(nsIDOMUIEvent* aEvent);
static PRUint32 gRefCnt;
static nsIAtom* kKeyAtom;
static nsIAtom* kKeyCodeAtom;
@ -122,36 +114,19 @@ protected:
static nsIAtom* kBindingDetachedAtom;
static nsIAtom* kModifiersAtom;
static PRInt32 kAccessKey;
static void InitAccessKey();
static nsresult GetTextData(nsIContent *aParent, nsString& aResult);
static const PRInt32 cShift;
static const PRInt32 cAlt;
static const PRInt32 cControl;
static const PRInt32 cMeta;
protected:
nsIDOMEventReceiver* mEventReceiver; // Both of these refs are weak.
nsIContent* mHandlerElement;
nsIXBLPrototypeHandler* mProtoHandler;
nsAutoString mEventName;
PRInt32 mKeyMask; // Which modifier keys this event handler expects to have down
// in order to be matched.
PRUint32 mDetail; // For key events, contains a charcode or keycode. For
// mouse events, stores the button info.
PRInt32 mDetail2; // Miscellaneous extra information. For key events,
// stores whether or not we're a key code or char code.
// For mouse events, stores the clickCount.
nsXBLEventHandler* mNextHandler; // Handlers are chained for easy unloading later.
};
extern nsresult
NS_NewXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIContent* aHandlerElement,
NS_NewXBLEventHandler(nsIDOMEventReceiver* aEventReceiver, nsIXBLPrototypeHandler* aHandlerElement,
const nsString& aEventName,
nsXBLEventHandler** aResult);

Просмотреть файл

@ -0,0 +1,719 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
*/
#include "nsCOMPtr.h"
#include "nsXBLPrototypeHandler.h"
#include "nsIContent.h"
#include "nsIAtom.h"
#include "nsIDOMKeyEvent.h"
#include "nsIDOMMouseEvent.h"
#include "nsINameSpaceManager.h"
#include "nsIScriptContext.h"
#include "nsIScriptObjectOwner.h"
#include "nsIScriptGlobalObject.h"
#include "nsIDocument.h"
#include "nsIDOMDocument.h"
#include "nsIJSEventListener.h"
#include "nsIController.h"
#include "nsIControllers.h"
#include "nsIDOMXULElement.h"
#include "nsIDOMNSHTMLTextAreaElement.h"
#include "nsIDOMNSHTMLInputElement.h"
#include "nsIDOMText.h"
#include "nsIEventListenerManager.h"
#include "nsIDOMEventReceiver.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMWindowInternal.h"
#include "nsIPref.h"
#include "nsIServiceManager.h"
static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID);
PRUint32 nsXBLPrototypeHandler::gRefCnt = 0;
nsIAtom* nsXBLPrototypeHandler::kKeyCodeAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kCharCodeAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kKeyAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kActionAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kCommandAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kClickCountAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kButtonAtom = nsnull;
nsIAtom* nsXBLPrototypeHandler::kModifiersAtom = nsnull;
PRInt32 nsXBLPrototypeHandler::kAccessKey = -1;
const PRInt32 nsXBLPrototypeHandler::cShift = (1<<1);
const PRInt32 nsXBLPrototypeHandler::cAlt = (1<<2);
const PRInt32 nsXBLPrototypeHandler::cControl = (1<<3);
const PRInt32 nsXBLPrototypeHandler::cMeta = (1<<4);
nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement)
{
NS_INIT_REFCNT();
mHandlerElement = aHandlerElement;
gRefCnt++;
if (gRefCnt == 1) {
kKeyCodeAtom = NS_NewAtom("keycode");
kKeyAtom = NS_NewAtom("key");
kCharCodeAtom = NS_NewAtom("charcode");
kModifiersAtom = NS_NewAtom("modifiers");
kActionAtom = NS_NewAtom("action");
kCommandAtom = NS_NewAtom("command");
kClickCountAtom = NS_NewAtom("clickcount");
kButtonAtom = NS_NewAtom("button");
// Get the primary accelerator key.
InitAccessKey();
}
// Make sure our mask is initialized.
ConstructMask();
}
nsXBLPrototypeHandler::~nsXBLPrototypeHandler()
{
gRefCnt--;
if (gRefCnt == 0) {
NS_RELEASE(kKeyAtom);
NS_RELEASE(kKeyCodeAtom);
NS_RELEASE(kCharCodeAtom);
NS_RELEASE(kModifiersAtom);
NS_RELEASE(kActionAtom);
NS_RELEASE(kCommandAtom);
NS_RELEASE(kButtonAtom);
NS_RELEASE(kClickCountAtom);
}
}
NS_IMPL_ISUPPORTS1(nsXBLPrototypeHandler, nsIXBLPrototypeHandler)
NS_IMETHODIMP
nsXBLPrototypeHandler::EventMatched(nsIDOMEvent* aEvent, PRBool* aResult)
{
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
if (key)
*aResult = KeyEventMatched(key);
else {
nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
if (mouse)
*aResult = MouseEventMatched(mouse);
else *aResult = PR_TRUE;
}
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::GetHandlerElement(nsIContent** aResult)
{
*aResult = mHandlerElement;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::GetNextHandler(nsIXBLPrototypeHandler** aResult)
{
*aResult = mNextHandler;
NS_IF_ADDREF(*aResult);
return NS_OK;
}
NS_IMETHODIMP
nsXBLPrototypeHandler::SetNextHandler(nsIXBLPrototypeHandler* aHandler)
{
mNextHandler = aHandler;
return NS_OK;
}
/////////////////////////////////////////////////////////////////////////////
// Get the menu access key from prefs.
// XXX Eventually pick up using CSS3 key-equivalent property or somesuch
void
nsXBLPrototypeHandler::InitAccessKey()
{
if (kAccessKey >= 0)
return;
// Compiled-in defaults, in case we can't get the pref --
// mac doesn't have menu shortcuts, other platforms use alt.
#ifndef XP_MAC
kAccessKey = nsIDOMKeyEvent::DOM_VK_ALT;
#else
kAccessKey = 0;
#endif
// Get the menu access key value from prefs, overriding the default:
nsresult rv;
NS_WITH_SERVICE(nsIPref, prefs, NS_PREF_PROGID, &rv);
if (NS_SUCCEEDED(rv) && prefs)
{
rv = prefs->GetIntPref("ui.key.menuAccessKey", &kAccessKey);
}
}
PRBool
nsXBLPrototypeHandler::KeyEventMatched(nsIDOMKeyEvent* aKeyEvent)
{
if (!mHandlerElement)
return PR_FALSE;
if (mDetail == 0 && mDetail2 == 0 && mKeyMask == 0)
return PR_TRUE; // No filters set up. It's generic.
// Get the keycode and charcode of the key event.
PRUint32 keyCode, charCode;
aKeyEvent->GetKeyCode(&keyCode);
aKeyEvent->GetCharCode(&charCode);
PRBool keyMatched = (mDetail == (mDetail2 ? charCode : keyCode));
if (!keyMatched)
return PR_FALSE;
// Now check modifier keys
return ModifiersMatchMask(aKeyEvent);
}
PRBool
nsXBLPrototypeHandler::MouseEventMatched(nsIDOMMouseEvent* aMouseEvent)
{
if (!mHandlerElement)
return PR_FALSE;
if (mDetail == 0 && mDetail2 == 0 && mKeyMask == 0)
return PR_TRUE; // No filters set up. It's generic.
unsigned short button;
aMouseEvent->GetButton(&button);
if (mDetail != 0 && (button != mDetail))
return PR_FALSE;
PRInt32 clickcount;
aMouseEvent->GetDetail(&clickcount);
if (mDetail2 != 0 && (clickcount != mDetail2))
return PR_FALSE;
return ModifiersMatchMask(aMouseEvent);
}
enum {
VK_CANCEL = 3,
VK_BACK = 8,
VK_TAB = 9,
VK_CLEAR = 12,
VK_RETURN = 13,
VK_ENTER = 14,
VK_SHIFT = 16,
VK_CONTROL = 17,
VK_ALT = 18,
VK_PAUSE = 19,
VK_CAPS_LOCK = 20,
VK_ESCAPE = 27,
VK_SPACE = 32,
VK_PAGE_UP = 33,
VK_PAGE_DOWN = 34,
VK_END = 35,
VK_HOME = 36,
VK_LEFT = 37,
VK_UP = 38,
VK_RIGHT = 39,
VK_DOWN = 40,
VK_PRINTSCREEN = 44,
VK_INSERT = 45,
VK_DELETE = 46,
VK_0 = 48,
VK_1 = 49,
VK_2 = 50,
VK_3 = 51,
VK_4 = 52,
VK_5 = 53,
VK_6 = 54,
VK_7 = 55,
VK_8 = 56,
VK_9 = 57,
VK_SEMICOLON = 59,
VK_EQUALS = 61,
VK_A = 65,
VK_B = 66,
VK_C = 67,
VK_D = 68,
VK_E = 69,
VK_F = 70,
VK_G = 71,
VK_H = 72,
VK_I = 73,
VK_J = 74,
VK_K = 75,
VK_L = 76,
VK_M = 77,
VK_N = 78,
VK_O = 79,
VK_P = 80,
VK_Q = 81,
VK_R = 82,
VK_S = 83,
VK_T = 84,
VK_U = 85,
VK_V = 86,
VK_W = 87,
VK_X = 88,
VK_Y = 89,
VK_Z = 90,
VK_NUMPAD0 = 96,
VK_NUMPAD1 = 97,
VK_NUMPAD2 = 98,
VK_NUMPAD3 = 99,
VK_NUMPAD4 = 100,
VK_NUMPAD5 = 101,
VK_NUMPAD6 = 102,
VK_NUMPAD7 = 103,
VK_NUMPAD8 = 104,
VK_NUMPAD9 = 105,
VK_MULTIPLY = 106,
VK_ADD = 107,
VK_SEPARATOR = 108,
VK_SUBTRACT = 109,
VK_DECIMAL = 110,
VK_DIVIDE = 111,
VK_F1 = 112,
VK_F2 = 113,
VK_F3 = 114,
VK_F4 = 115,
VK_F5 = 116,
VK_F6 = 117,
VK_F7 = 118,
VK_F8 = 119,
VK_F9 = 120,
VK_F10 = 121,
VK_F11 = 122,
VK_F12 = 123,
VK_F13 = 124,
VK_F14 = 125,
VK_F15 = 126,
VK_F16 = 127,
VK_F17 = 128,
VK_F18 = 129,
VK_F19 = 130,
VK_F20 = 131,
VK_F21 = 132,
VK_F22 = 133,
VK_F23 = 134,
VK_F24 = 135,
VK_NUM_LOCK = 144,
VK_SCROLL_LOCK = 145,
VK_COMMA = 188,
VK_PERIOD = 190,
VK_SLASH = 191,
VK_BACK_QUOTE = 192,
VK_OPEN_BRACKET = 219,
VK_BACK_SLASH = 220,
VK_CLOSE_BRACKET = 221,
VK_QUOTE = 222
};
PRUint32 nsXBLPrototypeHandler::GetMatchingKeyCode(const nsString& aKeyName)
{
PRBool ret = PR_FALSE;
nsCAutoString keyName; keyName.AssignWithConversion(aKeyName);
if (keyName.EqualsIgnoreCase("VK_CANCEL"))
return VK_CANCEL;
if(keyName.EqualsIgnoreCase("VK_BACK"))
return VK_BACK;
if(keyName.EqualsIgnoreCase("VK_TAB"))
return VK_TAB;
if(keyName.EqualsIgnoreCase("VK_CLEAR"))
return VK_CLEAR;
if(keyName.EqualsIgnoreCase("VK_RETURN"))
return VK_RETURN;
if(keyName.EqualsIgnoreCase("VK_ENTER"))
return VK_ENTER;
if(keyName.EqualsIgnoreCase("VK_SHIFT"))
return VK_SHIFT;
if(keyName.EqualsIgnoreCase("VK_CONTROL"))
return VK_CONTROL;
if(keyName.EqualsIgnoreCase("VK_ALT"))
return VK_ALT;
if(keyName.EqualsIgnoreCase("VK_PAUSE"))
return VK_PAUSE;
if(keyName.EqualsIgnoreCase("VK_CAPS_LOCK"))
return VK_CAPS_LOCK;
if(keyName.EqualsIgnoreCase("VK_ESCAPE"))
return VK_ESCAPE;
if(keyName.EqualsIgnoreCase("VK_SPACE"))
return VK_SPACE;
if(keyName.EqualsIgnoreCase("VK_PAGE_UP"))
return VK_PAGE_UP;
if(keyName.EqualsIgnoreCase("VK_PAGE_DOWN"))
return VK_PAGE_DOWN;
if(keyName.EqualsIgnoreCase("VK_END"))
return VK_END;
if(keyName.EqualsIgnoreCase("VK_HOME"))
return VK_HOME;
if(keyName.EqualsIgnoreCase("VK_LEFT"))
return VK_LEFT;
if(keyName.EqualsIgnoreCase("VK_UP"))
return VK_UP;
if(keyName.EqualsIgnoreCase("VK_RIGHT"))
return VK_RIGHT;
if(keyName.EqualsIgnoreCase("VK_DOWN"))
return VK_DOWN;
if(keyName.EqualsIgnoreCase("VK_PRINTSCREEN"))
return VK_PRINTSCREEN;
if(keyName.EqualsIgnoreCase("VK_INSERT"))
return VK_INSERT;
if(keyName.EqualsIgnoreCase("VK_DELETE"))
return VK_DELETE;
if(keyName.EqualsIgnoreCase("VK_0"))
return VK_0;
if(keyName.EqualsIgnoreCase("VK_1"))
return VK_1;
if(keyName.EqualsIgnoreCase("VK_2"))
return VK_2;
if(keyName.EqualsIgnoreCase("VK_3"))
return VK_3;
if(keyName.EqualsIgnoreCase("VK_4"))
return VK_4;
if(keyName.EqualsIgnoreCase("VK_5"))
return VK_5;
if(keyName.EqualsIgnoreCase("VK_6"))
return VK_6;
if(keyName.EqualsIgnoreCase("VK_7"))
return VK_7;
if(keyName.EqualsIgnoreCase("VK_8"))
return VK_8;
if(keyName.EqualsIgnoreCase("VK_9"))
return VK_9;
if(keyName.EqualsIgnoreCase("VK_SEMICOLON"))
return VK_SEMICOLON;
if(keyName.EqualsIgnoreCase("VK_EQUALS"))
return VK_EQUALS;
if(keyName.EqualsIgnoreCase("VK_A"))
return VK_A;
if(keyName.EqualsIgnoreCase("VK_B"))
return VK_B;
if(keyName.EqualsIgnoreCase("VK_C"))
return VK_C;
if(keyName.EqualsIgnoreCase("VK_D"))
return VK_D;
if(keyName.EqualsIgnoreCase("VK_E"))
return VK_E;
if(keyName.EqualsIgnoreCase("VK_F"))
return VK_F;
if(keyName.EqualsIgnoreCase("VK_G"))
return VK_G;
if(keyName.EqualsIgnoreCase("VK_H"))
return VK_H;
if(keyName.EqualsIgnoreCase("VK_I"))
return VK_I;
if(keyName.EqualsIgnoreCase("VK_J"))
return VK_J;
if(keyName.EqualsIgnoreCase("VK_K"))
return VK_K;
if(keyName.EqualsIgnoreCase("VK_L"))
return VK_L;
if(keyName.EqualsIgnoreCase("VK_M"))
return VK_M;
if(keyName.EqualsIgnoreCase("VK_N"))
return VK_N;
if(keyName.EqualsIgnoreCase("VK_O"))
return VK_O;
if(keyName.EqualsIgnoreCase("VK_P"))
return VK_P;
if(keyName.EqualsIgnoreCase("VK_Q"))
return VK_Q;
if(keyName.EqualsIgnoreCase("VK_R"))
return VK_R;
if(keyName.EqualsIgnoreCase("VK_S"))
return VK_S;
if(keyName.EqualsIgnoreCase("VK_T"))
return VK_T;
if(keyName.EqualsIgnoreCase("VK_U"))
return VK_U;
if(keyName.EqualsIgnoreCase("VK_V"))
return VK_V;
if(keyName.EqualsIgnoreCase("VK_W"))
return VK_W;
if(keyName.EqualsIgnoreCase("VK_X"))
return VK_X;
if(keyName.EqualsIgnoreCase("VK_Y"))
return VK_Y;
if(keyName.EqualsIgnoreCase("VK_Z"))
return VK_Z;
if(keyName.EqualsIgnoreCase("VK_NUMPAD0"))
return VK_NUMPAD0;
if(keyName.EqualsIgnoreCase("VK_NUMPAD1"))
return VK_NUMPAD1;
if(keyName.EqualsIgnoreCase("VK_NUMPAD2"))
return VK_NUMPAD2;
if(keyName.EqualsIgnoreCase("VK_NUMPAD3"))
return VK_NUMPAD3;
if(keyName.EqualsIgnoreCase("VK_NUMPAD4"))
return VK_NUMPAD4;
if(keyName.EqualsIgnoreCase("VK_NUMPAD5"))
return VK_NUMPAD5;
if(keyName.EqualsIgnoreCase("VK_NUMPAD6"))
return VK_NUMPAD6;
if(keyName.EqualsIgnoreCase("VK_NUMPAD7"))
return VK_NUMPAD7;
if(keyName.EqualsIgnoreCase("VK_NUMPAD8"))
return VK_NUMPAD8;
if(keyName.EqualsIgnoreCase("VK_NUMPAD9"))
return VK_NUMPAD9;
if(keyName.EqualsIgnoreCase("VK_MULTIPLY"))
return VK_MULTIPLY;
if(keyName.EqualsIgnoreCase("VK_ADD"))
return VK_ADD;
if(keyName.EqualsIgnoreCase("VK_SEPARATOR"))
return VK_SEPARATOR;
if(keyName.EqualsIgnoreCase("VK_SUBTRACT"))
return VK_SUBTRACT;
if(keyName.EqualsIgnoreCase("VK_DECIMAL"))
return VK_DECIMAL;
if(keyName.EqualsIgnoreCase("VK_DIVIDE"))
return VK_DIVIDE;
if(keyName.EqualsIgnoreCase("VK_F1"))
return VK_F1;
if(keyName.EqualsIgnoreCase("VK_F2"))
return VK_F2;
if(keyName.EqualsIgnoreCase("VK_F3"))
return VK_F3;
if(keyName.EqualsIgnoreCase("VK_F4"))
return VK_F4;
if(keyName.EqualsIgnoreCase("VK_F5"))
return VK_F5;
if(keyName.EqualsIgnoreCase("VK_F6"))
return VK_F6;
if(keyName.EqualsIgnoreCase("VK_F7"))
return VK_F7;
if(keyName.EqualsIgnoreCase("VK_F8"))
return VK_F8;
if(keyName.EqualsIgnoreCase("VK_F9"))
return VK_F9;
if(keyName.EqualsIgnoreCase("VK_F10"))
return VK_F10;
if(keyName.EqualsIgnoreCase("VK_F11"))
return VK_F11;
if(keyName.EqualsIgnoreCase("VK_F12"))
return VK_F12;
if(keyName.EqualsIgnoreCase("VK_F13"))
return VK_F13;
if(keyName.EqualsIgnoreCase("VK_F14"))
return VK_F14;
if(keyName.EqualsIgnoreCase("VK_F15"))
return VK_F15;
if(keyName.EqualsIgnoreCase("VK_F16"))
return VK_F16;
if(keyName.EqualsIgnoreCase("VK_F17"))
return VK_F17;
if(keyName.EqualsIgnoreCase("VK_F18"))
return VK_F18;
if(keyName.EqualsIgnoreCase("VK_F19"))
return VK_F19;
if(keyName.EqualsIgnoreCase("VK_F20"))
return VK_F20;
if(keyName.EqualsIgnoreCase("VK_F21"))
return VK_F21;
if(keyName.EqualsIgnoreCase("VK_F22"))
return VK_F22;
if(keyName.EqualsIgnoreCase("VK_F23"))
return VK_F23;
if(keyName.EqualsIgnoreCase("VK_F24"))
return VK_F24;
if(keyName.EqualsIgnoreCase("VK_NUM_LOCK"))
return VK_NUM_LOCK;
if(keyName.EqualsIgnoreCase("VK_SCROLL_LOCK"))
return VK_SCROLL_LOCK;
if(keyName.EqualsIgnoreCase("VK_COMMA"))
return VK_COMMA;
if(keyName.EqualsIgnoreCase("VK_PERIOD"))
return VK_PERIOD;
if(keyName.EqualsIgnoreCase("VK_SLASH"))
return VK_SLASH;
if(keyName.EqualsIgnoreCase("VK_BACK_QUOTE"))
return VK_BACK_QUOTE;
if(keyName.EqualsIgnoreCase("VK_OPEN_BRACKET"))
return VK_OPEN_BRACKET;
if(keyName.EqualsIgnoreCase("VK_BACK_SLASH"))
return VK_BACK_SLASH;
if(keyName.EqualsIgnoreCase("VK_CLOSE_BRACKET"))
return VK_CLOSE_BRACKET;
if(keyName.EqualsIgnoreCase("VK_QUOTE"))
return VK_QUOTE;
return 0;
}
void
nsXBLPrototypeHandler::ConstructMask()
{
mDetail = 0;
mDetail2 = 0;
mKeyMask = 0;
nsAutoString key;
mHandlerElement->GetAttribute(kNameSpaceID_None, kKeyAtom, key);
if (key.IsEmpty())
mHandlerElement->GetAttribute(kNameSpaceID_None, kCharCodeAtom, key);
if (!key.IsEmpty()) {
// We have a charcode.
mDetail2 = 1;
mDetail = key[0];
}
else {
mHandlerElement->GetAttribute(kNameSpaceID_None, kKeyCodeAtom, key);
if (!key.IsEmpty())
mDetail = GetMatchingKeyCode(key);
}
nsAutoString buttonStr, clickCountStr;
mHandlerElement->GetAttribute(kNameSpaceID_None, kClickCountAtom, clickCountStr);
mHandlerElement->GetAttribute(kNameSpaceID_None, kButtonAtom, buttonStr);
if (!buttonStr.IsEmpty()) {
PRInt32 error;
mDetail = buttonStr.ToInteger(&error);
}
if (!clickCountStr.IsEmpty()) {
PRInt32 error;
mDetail2 = clickCountStr.ToInteger(&error);
}
nsAutoString modifiers;
mHandlerElement->GetAttribute(kNameSpaceID_None, kModifiersAtom, modifiers);
if (modifiers.IsEmpty())
return;
char* str = modifiers.ToNewCString();
char* newStr;
char* token = nsCRT::strtok( str, ", ", &newStr );
while( token != NULL ) {
if (PL_strcmp(token, "shift") == 0)
mKeyMask |= cShift;
else if (PL_strcmp(token, "alt") == 0)
mKeyMask |= cAlt;
else if (PL_strcmp(token, "meta") == 0)
mKeyMask |= cMeta;
else if (PL_strcmp(token, "control") == 0)
mKeyMask |= cControl;
else if (PL_strcmp(token, "primary") == 0) {
switch (kAccessKey)
{
case nsIDOMKeyEvent::DOM_VK_META:
mKeyMask |= cMeta;
break;
case nsIDOMKeyEvent::DOM_VK_ALT:
mKeyMask |= cAlt;
break;
case nsIDOMKeyEvent::DOM_VK_CONTROL:
default:
mKeyMask |= cControl;
}
}
token = nsCRT::strtok( newStr, ", ", &newStr );
}
nsMemory::Free(str);
}
PRBool
nsXBLPrototypeHandler::ModifiersMatchMask(nsIDOMUIEvent* aEvent)
{
nsCOMPtr<nsIDOMKeyEvent> key(do_QueryInterface(aEvent));
nsCOMPtr<nsIDOMMouseEvent> mouse(do_QueryInterface(aEvent));
PRBool keyPresent;
key ? key->GetMetaKey(&keyPresent) : mouse->GetMetaKey(&keyPresent);
if (keyPresent != ((mKeyMask & cMeta) != 0))
return PR_FALSE;
key ? key->GetShiftKey(&keyPresent) : mouse->GetShiftKey(&keyPresent);
if (keyPresent != ((mKeyMask & cShift) != 0))
return PR_FALSE;
key ? key->GetAltKey(&keyPresent) : mouse->GetAltKey(&keyPresent);
if (keyPresent != ((mKeyMask & cAlt) != 0))
return PR_FALSE;
key ? key->GetCtrlKey(&keyPresent) : mouse->GetCtrlKey(&keyPresent);
if (keyPresent != ((mKeyMask & cControl) != 0))
return PR_FALSE;
return PR_TRUE;
}
///////////////////////////////////////////////////////////////////////////////////
nsresult
NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult)
{
*aResult = new nsXBLPrototypeHandler(aHandlerElement);
if (!*aResult)
return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(*aResult);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,98 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Original Author: David W. Hyatt (hyatt@netscape.com)
*
* Contributor(s):
*/
#ifndef nsXBLPrototypeHandler_h__
#define nsXBLPrototypeHandler_h__
#include "nsIXBLPrototypeHandler.h"
class nsIXBLBinding;
class nsIDOMEvent;
class nsIContent;
class nsIDOMUIEvent;
class nsIDOMKeyEvent;
class nsIDOMMouseEvent;
class nsIAtom;
class nsString;
class nsXBLPrototypeHandler : public nsIXBLPrototypeHandler
{
public:
nsXBLPrototypeHandler(nsIContent* aHandlerElement);
virtual ~nsXBLPrototypeHandler();
NS_DECL_ISUPPORTS
NS_IMETHOD EventMatched(nsIDOMEvent* aEvent, PRBool* aResult);
NS_IMETHOD GetHandlerElement(nsIContent** aResult);
NS_IMETHOD GetNextHandler(nsIXBLPrototypeHandler** aResult);
NS_IMETHOD SetNextHandler(nsIXBLPrototypeHandler* aHandler);
protected:
inline PRUint32 GetMatchingKeyCode(const nsString& aKeyName);
void ConstructMask();
PRBool ModifiersMatchMask(nsIDOMUIEvent* aEvent);
inline PRBool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent);
inline PRBool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent);
static PRUint32 gRefCnt;
static nsIAtom* kKeyAtom;
static nsIAtom* kKeyCodeAtom;
static nsIAtom* kCharCodeAtom;
static nsIAtom* kActionAtom;
static nsIAtom* kCommandAtom;
static nsIAtom* kClickCountAtom;
static nsIAtom* kButtonAtom;
static nsIAtom* kModifiersAtom;
static PRInt32 kAccessKey;
static void InitAccessKey();
static const PRInt32 cShift;
static const PRInt32 cAlt;
static const PRInt32 cControl;
static const PRInt32 cMeta;
protected:
nsIContent* mHandlerElement; // This ref is weak.
PRInt32 mKeyMask; // Which modifier keys this event handler expects to have down
// in order to be matched.
PRUint32 mDetail; // For key events, contains a charcode or keycode. For
// mouse events, stores the button info.
PRInt32 mDetail2; // Miscellaneous extra information. For key events,
// stores whether or not we're a key code or char code.
// For mouse events, stores the clickCount.
nsCOMPtr<nsIXBLPrototypeHandler> mNextHandler; // Prototype handlers are chained. We own the next handler in the chain.
};
extern nsresult
NS_NewXBLPrototypeHandler(nsIContent* aHandlerElement, nsIXBLPrototypeHandler** aResult);
#endif

Просмотреть файл

@ -51,6 +51,8 @@
#include "nsIXBLBinding.h"
#include "nsIXBLDocumentInfo.h"
#include "nsIXBLPrototypeHandler.h"
#include "nsIChromeRegistry.h"
#include "nsIPref.h"
@ -325,11 +327,18 @@ nsXBLStreamListener::Load(nsIDOMEvent* aEvent)
nsCOMPtr<nsIContent> root = getter_AddRefs(mBindingDocument->GetRootContent());
if (root)
nsXBLService::StripWhitespaceNodes(root);
else {
NS_ERROR("*** XBL doc with no root element! Something went horribly wrong! ***");
return NS_ERROR_FAILURE;
}
// Put our doc in the doc table.
nsCOMPtr<nsIXBLDocumentInfo> info;
NS_NewXBLDocumentInfo(mBindingDocument, getter_AddRefs(info));
// Construct our prototype handlers.
nsXBLService::ConstructPrototypeHandlers(info);
// If the doc is a chrome URI, then we put it into the XUL cache.
PRBool cached = PR_FALSE;
if (IsChromeURI(uri) && gXULUtils->UseXULCache()) {
@ -470,6 +479,7 @@ PRUint32 nsXBLService::gClassLRUListLength = 0;
PRUint32 nsXBLService::gClassLRUListQuota = 64;
nsIAtom* nsXBLService::kExtendsAtom = nsnull;
nsIAtom* nsXBLService::kHandlersAtom = nsnull;
nsIAtom* nsXBLService::kScrollbarAtom = nsnull;
nsIAtom* nsXBLService::kInputAtom = nsnull;
@ -509,6 +519,7 @@ nsXBLService::nsXBLService(void)
// Create our atoms
kExtendsAtom = NS_NewAtom("extends");
kHandlersAtom = NS_NewAtom("handlers");
kScrollbarAtom = NS_NewAtom("scrollbar");
kInputAtom = NS_NewAtom("input");
@ -544,6 +555,7 @@ nsXBLService::~nsXBLService(void)
// Release our atoms
NS_RELEASE(kExtendsAtom);
NS_RELEASE(kHandlersAtom);
NS_RELEASE(kScrollbarAtom);
NS_RELEASE(kInputAtom);
@ -999,6 +1011,9 @@ nsXBLService::LoadBindingDocumentInfo(nsIContent* aBoundElement, nsIDocument* aB
if (document) {
NS_NewXBLDocumentInfo(document, getter_AddRefs(info));
// Construct our prototype handlers.
ConstructPrototypeHandlers(info);
// If the doc is a chrome URI, then we put it into the XUL cache.
PRBool cached = PR_FALSE;
@ -1183,6 +1198,74 @@ nsXBLService::StripWhitespaceNodes(nsIContent* aElement)
return NS_OK;
}
static void GetImmediateChild(nsIAtom* aTag, nsIContent* aParent, nsIContent** aResult)
{
*aResult = nsnull;
PRInt32 childCount;
aParent->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> child;
aParent->ChildAt(i, *getter_AddRefs(child));
nsCOMPtr<nsIAtom> tag;
child->GetTag(*getter_AddRefs(tag));
if (aTag == tag.get()) {
*aResult = child;
NS_ADDREF(*aResult);
return;
}
}
}
nsresult
nsXBLService::ConstructPrototypeHandlers(nsIXBLDocumentInfo* aInfo)
{
nsCOMPtr<nsIDocument> doc;
aInfo->GetDocument(getter_AddRefs(doc));
nsCOMPtr<nsIContent> bindings = getter_AddRefs(doc->GetRootContent());
PRInt32 childCount;
bindings->ChildCount(childCount);
for (PRInt32 i = 0; i < childCount; i++) {
nsCOMPtr<nsIContent> binding;
bindings->ChildAt(i, *getter_AddRefs(binding));
// See if this binding has a handler elt.
nsCOMPtr<nsIContent> handlers;
GetImmediateChild(kHandlersAtom, binding, getter_AddRefs(handlers));
if (handlers) {
nsCOMPtr<nsIXBLPrototypeHandler> firstHandler;
nsCOMPtr<nsIXBLPrototypeHandler> currHandler;
PRInt32 handlerCount;
handlers->ChildCount(handlerCount);
for (PRInt32 j = 0; j < handlerCount; j++) {
nsCOMPtr<nsIContent> handler;
handlers->ChildAt(j, *getter_AddRefs(handler));
nsCOMPtr<nsIXBLPrototypeHandler> newHandler;
NS_NewXBLPrototypeHandler(handler, getter_AddRefs(newHandler));
if (newHandler) {
if (currHandler)
currHandler->SetNextHandler(newHandler);
else firstHandler = newHandler;
currHandler = newHandler;
}
}
if (firstHandler) {
nsAutoString ref;
binding->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::id, ref);
nsCAutoString cref;
cref.AssignWithConversion(ref);
aInfo->SetPrototypeHandler(cref, firstHandler);
}
}
}
return NS_OK;
}
// Creation Routine ///////////////////////////////////////////////////////////////////////
nsresult

Просмотреть файл

@ -96,6 +96,7 @@ public:
// This method walks a binding document and removes any text nodes
// that contain only whitespace.
static nsresult StripWhitespaceNodes(nsIContent* aContent);
static nsresult ConstructPrototypeHandlers(nsIXBLDocumentInfo* aInfo);
// MEMBER VARIABLES
public:
@ -117,7 +118,7 @@ public:
// XBL Atoms
static nsIAtom* kExtendsAtom;
static nsIAtom* kHandlersAtom;
static nsIAtom* kScrollbarAtom;
static nsIAtom* kInputAtom;