summaryrefslogtreecommitdiffstats
path: root/khtml/ecma/kjs_events.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'khtml/ecma/kjs_events.cpp')
-rw-r--r--khtml/ecma/kjs_events.cpp993
1 files changed, 993 insertions, 0 deletions
diff --git a/khtml/ecma/kjs_events.cpp b/khtml/ecma/kjs_events.cpp
new file mode 100644
index 000000000..8ebda7193
--- /dev/null
+++ b/khtml/ecma/kjs_events.cpp
@@ -0,0 +1,993 @@
+// -*- c-basic-offset: 2 -*-
+/*
+ * This file is part of the KDE libraries
+ * Copyright (C) 2001 Peter Kelly (pmk@post.com)
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "kjs_window.h"
+#include "kjs_events.h"
+#include "kjs_events.lut.h"
+#include "kjs_views.h"
+#include "kjs_proxy.h"
+#include "xml/dom_nodeimpl.h"
+#include "xml/dom_docimpl.h"
+#include "xml/dom2_eventsimpl.h"
+#include "rendering/render_object.h"
+#include "rendering/render_canvas.h"
+#include "xml/dom2_eventsimpl.h"
+#include "khtml_part.h"
+
+#include <kdebug.h>
+
+using namespace DOM;
+
+namespace KJS {
+
+// -------------------------------------------------------------------------
+
+JSEventListener::JSEventListener(Object _listener, ObjectImp *_compareListenerImp, const Object &_win, bool _html)
+ : listener( _listener ), compareListenerImp( _compareListenerImp ), html( _html ), win( _win )
+{
+ //fprintf(stderr,"JSEventListener::JSEventListener this=%p listener=%p\n",this,listener.imp());
+ if (compareListenerImp) {
+ static_cast<Window*>(win.imp())->jsEventListeners.insert(compareListenerImp, this);
+ }
+}
+
+JSEventListener::~JSEventListener()
+{
+ if (compareListenerImp) {
+ static_cast<Window*>(win.imp())->jsEventListeners.remove(compareListenerImp);
+ }
+ //fprintf(stderr,"JSEventListener::~JSEventListener this=%p listener=%p\n",this,listener.imp());
+}
+
+void JSEventListener::handleEvent(DOM::Event &evt)
+{
+#ifdef KJS_DEBUGGER
+ if (KJSDebugWin::debugWindow() && KJSDebugWin::debugWindow()->inSession())
+ return;
+#endif
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(static_cast<Window*>(win.imp())->part());
+ KJSProxy *proxy = 0L;
+ if (part)
+ proxy = part->jScript();
+
+ if (proxy && listener.isValid() && listener.implementsCall()) {
+ ref();
+
+ KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
+ ExecState *exec = interpreter->globalExec();
+
+ List args;
+ args.append(getDOMEvent(exec,evt));
+
+ // Set "this" to the event's current target
+ Object thisObj = Object::dynamicCast(getDOMNode(exec,evt.currentTarget()));
+ if ( !thisObj.isValid() ) {
+ // Window events (window.onload/window.onresize etc.) must have 'this' set to the window.
+ // DocumentImpl::defaultEventHandler sets currentTarget to 0 to mean 'window'.
+ thisObj = win;
+ }
+
+ Window *window = static_cast<Window*>(win.imp());
+ // Set the event we're handling in the Window object
+ window->setCurrentEvent( &evt );
+ // ... and in the interpreter
+ interpreter->setCurrentEvent( &evt );
+
+ KJSCPUGuard guard;
+ guard.start();
+ Value retval = listener.call(exec, thisObj, args);
+ guard.stop();
+
+ window->setCurrentEvent( 0 );
+ interpreter->setCurrentEvent( 0 );
+ if ( exec->hadException() )
+ exec->clearException();
+ else if (html)
+ {
+ QVariant ret = ValueToVariant(exec, retval);
+ if (ret.type() == QVariant::Bool && ret.toBool() == false)
+ evt.preventDefault();
+ }
+ window->afterScriptExecution();
+ deref();
+ }
+}
+
+DOM::DOMString JSEventListener::eventListenerType()
+{
+ if (html)
+ return "_khtml_HTMLEventListener";
+ else
+ return "_khtml_JSEventListener";
+}
+
+Object JSEventListener::listenerObj() const
+{
+ return listener;
+}
+
+JSLazyEventListener::JSLazyEventListener(const QString &_code, const QString &_name, const Object &_win, DOM::NodeImpl* _originalNode)
+ : JSEventListener(Object(), 0, _win, true),
+ code(_code), name(_name),
+ parsed(false)
+{
+ // We don't retain the original node, because we assume it
+ // will stay alive as long as this handler object is around
+ // and we need to avoid a reference cycle. If JS transfers
+ // this handler to another node, parseCode will be called and
+ // then originalNode is no longer needed.
+
+ originalNode = _originalNode;
+}
+
+JSLazyEventListener::~JSLazyEventListener()
+{
+ if (listener.isValid()) {
+ static_cast<Window*>(win.imp())->jsEventListeners.remove(listener.imp());
+ }
+}
+
+void JSLazyEventListener::handleEvent(DOM::Event &evt)
+{
+ parseCode();
+ if (listener.isValid()) {
+ JSEventListener::handleEvent(evt);
+ }
+}
+
+
+Object JSLazyEventListener::listenerObj() const
+{
+ parseCode();
+ return listener;
+}
+
+void JSLazyEventListener::parseCode() const
+{
+ if (!parsed) {
+ KHTMLPart *part = ::qt_cast<KHTMLPart *>(static_cast<Window*>(win.imp())->part());
+ KJSProxy *proxy = 0L;
+ if (part)
+ proxy = part->jScript();
+
+ if (proxy) {
+ KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
+ ExecState *exec = interpreter->globalExec();
+
+ //KJS::Constructor constr(KJS::Global::current().get("Function").imp());
+ KJS::Object constr = interpreter->builtinFunction();
+ KJS::List args;
+
+ static KJS::String eventString("event");
+
+ args.append(eventString);
+ args.append(KJS::String(code));
+ listener = constr.construct(exec, args); // ### is globalExec ok ?
+
+ if (exec->hadException()) {
+ exec->clearException();
+
+ // failed to parse, so let's just make this listener a no-op
+ listener = Object();
+ } else if (!listener.inherits(&DeclaredFunctionImp::info)) {
+ listener = Object();// Error creating function
+ } else {
+ DeclaredFunctionImp *declFunc = static_cast<DeclaredFunctionImp*>(listener.imp());
+ declFunc->setName(Identifier(name));
+
+ if (originalNode)
+ {
+ // Add the event's home element to the scope
+ // (and the document, and the form - see KJS::HTMLElement::eventHandlerScope)
+ ScopeChain scope = listener.scope();
+
+ Object thisObj = Object::dynamicCast(getDOMNode(exec, originalNode));
+
+ if (thisObj.isValid()) {
+ static_cast<DOMNode*>(thisObj.imp())->pushEventHandlerScope(exec, scope);
+
+ listener.setScope(scope);
+ }
+ }
+ }
+ }
+
+ // no more need to keep the unparsed code around
+ code = QString();
+
+ if (listener.isValid()) {
+ static_cast<Window*>(win.imp())->jsEventListeners.insert(listener.imp(),
+ (KJS::JSEventListener *)(this));
+ }
+
+ parsed = true;
+ }
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMEvent::info = { "Event", 0, &DOMEventTable, 0 };
+/*
+@begin DOMEventTable 7
+ type DOMEvent::Type DontDelete|ReadOnly
+ target DOMEvent::Target DontDelete|ReadOnly
+ currentTarget DOMEvent::CurrentTarget DontDelete|ReadOnly
+ srcElement DOMEvent::SrcElement DontDelete|ReadOnly
+ eventPhase DOMEvent::EventPhase DontDelete|ReadOnly
+ bubbles DOMEvent::Bubbles DontDelete|ReadOnly
+ cancelable DOMEvent::Cancelable DontDelete|ReadOnly
+ timeStamp DOMEvent::TimeStamp DontDelete|ReadOnly
+ returnValue DOMEvent::ReturnValue DontDelete
+ cancelBubble DOMEvent::CancelBubble DontDelete
+@end
+@begin DOMEventProtoTable 3
+ stopPropagation DOMEvent::StopPropagation DontDelete|Function 0
+ preventDefault DOMEvent::PreventDefault DontDelete|Function 0
+ initEvent DOMEvent::InitEvent DontDelete|Function 3
+@end
+*/
+KJS_DEFINE_PROTOTYPE(DOMEventProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMEvent", DOMEventProto, DOMEventProtoFunc)
+
+DOMEvent::DOMEvent(ExecState *exec, DOM::Event e)
+ : DOMObject(DOMEventProto::self(exec)), event(e) { }
+
+DOMEvent::DOMEvent(const Object &proto, DOM::Event e)
+ : DOMObject(proto), event(e) { }
+
+DOMEvent::~DOMEvent()
+{
+ ScriptInterpreter::forgetDOMObject(event.handle());
+}
+
+Value DOMEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug() << "KJS::DOMEvent::tryGet " << p.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMEvent,DOMObject>(exec, p, &DOMEventTable, this );
+}
+
+Value DOMEvent::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case Type:
+ return String(event.type());
+ case Target:
+ case SrcElement: /*MSIE extension - "the object that fired the event"*/
+ return getDOMNode(exec,event.target());
+ case CurrentTarget:
+ return getDOMNode(exec,event.currentTarget());
+ case EventPhase:
+ return Number((unsigned int)event.eventPhase());
+ case Bubbles:
+ return Boolean(event.bubbles());
+ case Cancelable:
+ return Boolean(event.cancelable());
+ case TimeStamp:
+ return Number((long unsigned int)event.timeStamp()); // ### long long ?
+ case ReturnValue: // MSIE extension
+ // return false == cancel, so this returns the -opposite- of defaultPrevented
+ return Boolean(!event.handle()->defaultPrevented());
+ case CancelBubble: // MSIE extension
+ return Boolean(event.handle()->propagationStopped());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMEvent::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+Value DOMEvent::defaultValue(ExecState *exec, KJS::Type hint) const
+{
+ if (event.handle()->id() == EventImpl::ERROR_EVENT && !event.handle()->message().isNull()) {
+ return String(event.handle()->message());
+ }
+ else
+ return DOMObject::defaultValue(exec,hint);
+}
+
+void DOMEvent::tryPut(ExecState *exec, const Identifier &propertyName,
+ const Value& value, int attr)
+{
+ DOMObjectLookupPut<DOMEvent, DOMObject>(exec, propertyName, value, attr,
+ &DOMEventTable, this);
+}
+
+void DOMEvent::putValueProperty(ExecState *exec, int token, const Value& value, int)
+{
+ switch (token) {
+ case ReturnValue: // MSIE equivalent for "preventDefault" (but with a way to reset it)
+ // returnValue=false means "default action of the event on the source object is canceled",
+ // which means preventDefault(true). Hence the '!'.
+ event.handle()->preventDefault(!value.toBoolean(exec));
+ break;
+ case CancelBubble: // MSIE equivalent for "stopPropagation" (but with a way to reset it)
+ event.handle()->stopPropagation(value.toBoolean(exec));
+ break;
+ default:
+ break;
+ }
+}
+
+Value DOMEventProtoFunc::tryCall(ExecState *exec, Object & thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMEvent, thisObj );
+ DOM::Event event = static_cast<DOMEvent *>( thisObj.imp() )->toEvent();
+ switch (id) {
+ case DOMEvent::StopPropagation:
+ event.stopPropagation();
+ return Undefined();
+ case DOMEvent::PreventDefault:
+ event.preventDefault();
+ return Undefined();
+ case DOMEvent::InitEvent:
+ event.initEvent(args[0].toString(exec).string(),args[1].toBoolean(exec),args[2].toBoolean(exec));
+ return Undefined();
+ };
+ return Undefined();
+}
+
+Value getDOMEvent(ExecState *exec, DOM::Event e)
+{
+ DOM::EventImpl *ei = e.handle();
+ if (!ei)
+ return Null();
+ ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
+ DOMObject *ret = interp->getDOMObject(ei);
+ if (!ret) {
+ if (ei->isTextInputEvent())
+ ret = new DOMTextEvent(exec, e);
+ else if (ei->isKeyboardEvent())
+ ret = new DOMKeyboardEvent(exec, e);
+ else if (ei->isMouseEvent())
+ ret = new DOMMouseEvent(exec, e);
+ else if (ei->isUIEvent())
+ ret = new DOMUIEvent(exec, e);
+ else if (ei->isMutationEvent())
+ ret = new DOMMutationEvent(exec, e);
+ else
+ ret = new DOMEvent(exec, e);
+
+ interp->putDOMObject(ei, ret);
+ }
+
+ return Value(ret);
+}
+
+DOM::Event toEvent(const Value& val)
+{
+ Object obj = Object::dynamicCast(val);
+ if (!obj.isValid() || !obj.inherits(&DOMEvent::info))
+ return DOM::Event();
+
+ const DOMEvent *dobj = static_cast<const DOMEvent*>(obj.imp());
+ return dobj->toEvent();
+}
+
+// -------------------------------------------------------------------------
+/*
+@begin EventConstantsTable 23
+ CAPTURING_PHASE DOM::Event::CAPTURING_PHASE DontDelete|ReadOnly
+ AT_TARGET DOM::Event::AT_TARGET DontDelete|ReadOnly
+ BUBBLING_PHASE DOM::Event::BUBBLING_PHASE DontDelete|ReadOnly
+# Reverse-engineered from Netscape
+ MOUSEDOWN 1 DontDelete|ReadOnly
+ MOUSEUP 2 DontDelete|ReadOnly
+ MOUSEOVER 4 DontDelete|ReadOnly
+ MOUSEOUT 8 DontDelete|ReadOnly
+ MOUSEMOVE 16 DontDelete|ReadOnly
+ MOUSEDRAG 32 DontDelete|ReadOnly
+ CLICK 64 DontDelete|ReadOnly
+ DBLCLICK 128 DontDelete|ReadOnly
+ KEYDOWN 256 DontDelete|ReadOnly
+ KEYUP 512 DontDelete|ReadOnly
+ KEYPRESS 1024 DontDelete|ReadOnly
+ DRAGDROP 2048 DontDelete|ReadOnly
+ FOCUS 4096 DontDelete|ReadOnly
+ BLUR 8192 DontDelete|ReadOnly
+ SELECT 16384 DontDelete|ReadOnly
+ CHANGE 32768 DontDelete|ReadOnly
+@end
+*/
+DEFINE_CONSTANT_TABLE(EventConstants)
+IMPLEMENT_CONSTANT_TABLE(EventConstants, "EventConstants")
+
+IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(EventConstructor, "EventConstructor", DOMEventProto, EventConstants)
+// -------------------------------------------------------------------------
+
+
+const ClassInfo EventExceptionConstructor::info = { "EventExceptionConstructor", 0, &EventExceptionConstructorTable, 0 };
+/*
+@begin EventExceptionConstructorTable 1
+ UNSPECIFIED_EVENT_TYPE_ERR DOM::EventException::UNSPECIFIED_EVENT_TYPE_ERR DontDelete|ReadOnly
+@end
+*/
+EventExceptionConstructor::EventExceptionConstructor(ExecState *exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype())
+{
+}
+
+Value EventExceptionConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<EventExceptionConstructor, DOMObject>(exec,p,&EventExceptionConstructorTable,this);
+}
+
+Value EventExceptionConstructor::getValueProperty(ExecState *, int token) const
+{
+ // We use the token as the value to return directly
+ return Number(token);
+}
+
+Value getEventExceptionConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<EventExceptionConstructor>(exec, "[[eventException.constructor]]");
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMUIEvent::info = { "UIEvent", &DOMEvent::info, &DOMUIEventTable, 0 };
+/*
+@begin DOMUIEventTable 7
+ view DOMUIEvent::View DontDelete|ReadOnly
+ detail DOMUIEvent::Detail DontDelete|ReadOnly
+ keyCode DOMUIEvent::KeyCode DontDelete|ReadOnly
+ charCode DOMUIEvent::CharCode DontDelete|ReadOnly
+ layerX DOMUIEvent::LayerX DontDelete|ReadOnly
+ layerY DOMUIEvent::LayerY DontDelete|ReadOnly
+ pageX DOMUIEvent::PageX DontDelete|ReadOnly
+ pageY DOMUIEvent::PageY DontDelete|ReadOnly
+ which DOMUIEvent::Which DontDelete|ReadOnly
+@end
+@begin DOMUIEventProtoTable 1
+ initUIEvent DOMUIEvent::InitUIEvent DontDelete|Function 5
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMUIEventProto, DOMEventProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMUIEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMUIEvent", DOMUIEventProto, DOMUIEventProtoFunc)
+
+DOMUIEvent::DOMUIEvent(ExecState *exec, DOM::UIEvent ue) :
+ DOMEvent(DOMUIEventProto::self(exec), ue) {}
+
+DOMUIEvent::DOMUIEvent(const Object &proto, DOM::UIEvent ue) :
+ DOMEvent(proto, ue) {}
+
+DOMUIEvent::~DOMUIEvent()
+{
+}
+
+Value DOMUIEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<DOMUIEvent,DOMEvent>(exec,p,&DOMUIEventTable,this);
+}
+
+Value DOMUIEvent::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case View:
+ return getDOMAbstractView(exec,static_cast<DOM::UIEvent>(event).view());
+ case Detail:
+ return Number(static_cast<DOM::UIEvent>(event).detail());
+ case KeyCode:
+ // IE-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).keyCode());
+ case CharCode:
+ // IE-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).charCode());
+ case LayerX:
+ // NS-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).layerX());
+ case LayerY:
+ // NS-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).layerY());
+ case PageX:
+ // NS-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).pageX());
+ case PageY:
+ // NS-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).pageY());
+ case Which:
+ // NS-compatibility
+ return Number(static_cast<DOM::UIEvent>(event).which());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMUIEvent::getValueProperty : " << token << endl;
+ return Undefined();
+ }
+}
+
+Value DOMUIEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMUIEvent, thisObj );
+ DOM::UIEvent uiEvent = static_cast<DOMUIEvent *>(thisObj.imp())->toUIEvent();
+ switch (id) {
+ case DOMUIEvent::InitUIEvent: {
+ DOM::AbstractView v = toAbstractView(args[3]);
+ static_cast<DOM::UIEvent>(uiEvent).initUIEvent(args[0].toString(exec).string(),
+ args[1].toBoolean(exec),
+ args[2].toBoolean(exec),
+ v,
+ args[4].toInteger(exec));
+ }
+ return Undefined();
+ }
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMMouseEvent::info = { "MouseEvent", &DOMUIEvent::info, &DOMMouseEventTable, 0 };
+
+/*
+@begin DOMMouseEventTable 2
+ screenX DOMMouseEvent::ScreenX DontDelete|ReadOnly
+ screenY DOMMouseEvent::ScreenY DontDelete|ReadOnly
+ clientX DOMMouseEvent::ClientX DontDelete|ReadOnly
+ x DOMMouseEvent::X DontDelete|ReadOnly
+ clientY DOMMouseEvent::ClientY DontDelete|ReadOnly
+ y DOMMouseEvent::Y DontDelete|ReadOnly
+ offsetX DOMMouseEvent::OffsetX DontDelete|ReadOnly
+ offsetY DOMMouseEvent::OffsetY DontDelete|ReadOnly
+ ctrlKey DOMMouseEvent::CtrlKey DontDelete|ReadOnly
+ shiftKey DOMMouseEvent::ShiftKey DontDelete|ReadOnly
+ altKey DOMMouseEvent::AltKey DontDelete|ReadOnly
+ metaKey DOMMouseEvent::MetaKey DontDelete|ReadOnly
+ button DOMMouseEvent::Button DontDelete|ReadOnly
+ relatedTarget DOMMouseEvent::RelatedTarget DontDelete|ReadOnly
+ fromElement DOMMouseEvent::FromElement DontDelete|ReadOnly
+ toElement DOMMouseEvent::ToElement DontDelete|ReadOnly
+@end
+@begin DOMMouseEventProtoTable 1
+ initMouseEvent DOMMouseEvent::InitMouseEvent DontDelete|Function 15
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMMouseEventProto, DOMUIEventProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMMouseEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMMouseEvent", DOMMouseEventProto, DOMMouseEventProtoFunc)
+
+DOMMouseEvent::DOMMouseEvent(ExecState *exec, DOM::MouseEvent me) :
+ DOMUIEvent(DOMMouseEventProto::self(exec), me) {}
+
+DOMMouseEvent::~DOMMouseEvent()
+{
+}
+
+Value DOMMouseEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMMouseEvent::tryGet " << p.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMMouseEvent,DOMUIEvent>(exec,p,&DOMMouseEventTable,this);
+}
+
+Value DOMMouseEvent::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case ScreenX:
+ return Number(static_cast<DOM::MouseEvent>(event).screenX());
+ case ScreenY:
+ return Number(static_cast<DOM::MouseEvent>(event).screenY());
+ case ClientX:
+ case X:
+ return Number(static_cast<DOM::MouseEvent>(event).clientX());
+ case ClientY:
+ case Y:
+ return Number(static_cast<DOM::MouseEvent>(event).clientY());
+ case OffsetX:
+ case OffsetY: // MSIE extension
+ {
+ DOM::Node node = event.target();
+ khtml::RenderObject *rend = 0;
+ if (node.handle()) {
+ node.handle()->getDocument()->updateRendering();
+ rend = node.handle()->renderer();
+ }
+ int x = static_cast<DOM::MouseEvent>(event).clientX();
+ int y = static_cast<DOM::MouseEvent>(event).clientY();
+ if ( rend ) {
+ int xPos, yPos;
+ if ( rend->absolutePosition( xPos, yPos ) ) {
+ //kdDebug() << "DOMMouseEvent::getValueProperty rend=" << rend << " xPos=" << xPos << " yPos=" << yPos << endl;
+ x -= xPos;
+ y -= yPos;
+ }
+ if ( rend->canvas() ) {
+ int cYPos, cXPos;
+ rend->canvas()->absolutePosition( cXPos, cYPos, true );
+ x += cXPos;
+ y += cYPos;
+ }
+ }
+ return Number( token == OffsetX ? x : y );
+ }
+ case CtrlKey:
+ return Boolean(static_cast<DOM::MouseEvent>(event).ctrlKey());
+ case ShiftKey:
+ return Boolean(static_cast<DOM::MouseEvent>(event).shiftKey());
+ case AltKey:
+ return Boolean(static_cast<DOM::MouseEvent>(event).altKey());
+ case MetaKey:
+ return Boolean(static_cast<DOM::MouseEvent>(event).metaKey());
+ case Button:
+ {
+ if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat ) {
+ return Number(static_cast<DOM::MouseEvent>(event).button());
+ }
+ // Tricky. The DOM (and khtml) use 0 for LMB, 1 for MMB and 2 for RMB
+ // but MSIE uses 1=LMB, 2=RMB, 4=MMB, as a bitfield
+ int domButton = static_cast<DOM::MouseEvent>(event).button();
+ int button = domButton==0 ? 1 : domButton==1 ? 4 : domButton==2 ? 2 : 0;
+ return Number( (unsigned int)button );
+ }
+ case ToElement:
+ // MSIE extension - "the object toward which the user is moving the mouse pointer"
+ if (event.handle()->id() == DOM::EventImpl::MOUSEOUT_EVENT)
+ return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).relatedTarget());
+ return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).target());
+ case FromElement:
+ // MSIE extension - "object from which activation
+ // or the mouse pointer is exiting during the event" (huh?)
+ if (event.handle()->id() == DOM::EventImpl::MOUSEOUT_EVENT)
+ return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).target());
+ /* fall through */
+ case RelatedTarget:
+ return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).relatedTarget());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMMouseEvent::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+Value DOMMouseEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMMouseEvent, thisObj );
+ DOM::MouseEvent mouseEvent = static_cast<DOMMouseEvent *>(thisObj.imp())->toMouseEvent();
+ switch (id) {
+ case DOMMouseEvent::InitMouseEvent:
+ mouseEvent.initMouseEvent(args[0].toString(exec).string(), // typeArg
+ args[1].toBoolean(exec), // canBubbleArg
+ args[2].toBoolean(exec), // cancelableArg
+ toAbstractView(args[3]), // viewArg
+ args[4].toInteger(exec), // detailArg
+ args[5].toInteger(exec), // screenXArg
+ args[6].toInteger(exec), // screenYArg
+ args[7].toInteger(exec), // clientXArg
+ args[8].toInteger(exec), // clientYArg
+ args[9].toBoolean(exec), // ctrlKeyArg
+ args[10].toBoolean(exec), // altKeyArg
+ args[11].toBoolean(exec), // shiftKeyArg
+ args[12].toBoolean(exec), // metaKeyArg
+ args[13].toInteger(exec), // buttonArg
+ toNode(args[14])); // relatedTargetArg
+ return Undefined();
+ }
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMKeyEventBase::info = { "KeyEventBase", &DOMUIEvent::info, &DOMKeyEventBaseTable, 0 };
+
+/*
+@begin DOMKeyEventBaseTable 5
+ keyVal DOMKeyEventBase::Key DontDelete|ReadOnly
+ virtKeyVal DOMKeyEventBase::VirtKey DontDelete|ReadOnly
+ ctrlKey DOMKeyEventBase::CtrlKey DontDelete|ReadOnly
+ altKey DOMKeyEventBase::AltKey DontDelete|ReadOnly
+ shiftKey DOMKeyEventBase::ShiftKey DontDelete|ReadOnly
+ altKey DOMKeyEventBase::AltKey DontDelete|ReadOnly
+@end
+*/
+
+DOMKeyEventBase::DOMKeyEventBase(const Object &proto, DOM::TextEvent ke) :
+ DOMUIEvent(proto, ke) {}
+
+DOMKeyEventBase::~DOMKeyEventBase()
+{}
+
+Value DOMKeyEventBase::tryGet(ExecState *exec,const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMKeyEventBase::tryGet " << p.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMKeyEventBase,DOMUIEvent>(exec,p,&DOMKeyEventBaseTable,this);
+}
+
+Value DOMKeyEventBase::getValueProperty(ExecState *, int token) const
+{
+ DOM::KeyEventBaseImpl* tevent = impl();
+ switch (token) {
+ case Key:
+ return Number(tevent->keyVal());
+ case VirtKey:
+ return Number(tevent->virtKeyVal());
+ // these modifier attributes actually belong into a KeyboardEvent interface,
+ // but we want them on "keypress" as well.
+ case CtrlKey:
+ return Boolean(tevent->ctrlKey());
+ case ShiftKey:
+ return Boolean(tevent->shiftKey());
+ case AltKey:
+ return Boolean(tevent->altKey());
+ case MetaKey:
+ return Boolean(tevent->metaKey());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMTextEvent::getValueProperty : " << token << endl;
+ return KJS::Undefined();
+ }
+}
+
+// -------------------------------------------------------------------------
+const ClassInfo DOMTextEvent::info = { "TextEvent", &DOMKeyEventBase::info, &DOMTextEventTable, 0 };
+
+/*
+@begin DOMTextEventTable 1
+ data DOMTextEvent::Data DontDelete|ReadOnly
+@end
+@begin DOMTextEventProtoTable 1
+ initTextEvent DOMTextEvent::InitTextEvent DontDelete|Function 5
+ # Missing: initTextEventNS
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMTextEventProto, DOMUIEventProto) //Note: no proto in KeyBase
+IMPLEMENT_PROTOFUNC_DOM(DOMTextEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMTextEvent", DOMTextEventProto, DOMTextEventProtoFunc)
+
+DOMTextEvent::DOMTextEvent(ExecState *exec, DOM::TextEvent ke) :
+ DOMKeyEventBase(DOMTextEventProto::self(exec), ke) {}
+
+DOMTextEvent::~DOMTextEvent()
+{
+}
+
+Value DOMTextEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMTextEvent::tryGet " << p.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMTextEvent,DOMKeyEventBase>(exec,p,&DOMTextEventTable,this);
+}
+
+Value DOMTextEvent::getValueProperty(ExecState *, int token) const
+{
+ DOM::TextEventImpl* tevent = impl();
+ switch (token) {
+ case Data:
+ return String(tevent->data());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMTextEvent::getValueProperty : " << token << endl;
+ return KJS::Undefined();
+ }
+}
+
+Value DOMTextEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMTextEvent, thisObj );
+ DOM::TextEventImpl* keyEvent = static_cast<DOMTextEvent *>(thisObj.imp())->impl();
+ switch (id) {
+ case DOMTextEvent::InitTextEvent:
+ keyEvent->initTextEvent(args[0].toString(exec).string(), // typeArg
+ args[1].toBoolean(exec), // canBubbleArg
+ args[2].toBoolean(exec), // cancelableArg
+ toAbstractView(args[3]), // viewArg
+ args[4].toString(exec).string()); // dataArg
+
+ return Undefined();
+ }
+ return Undefined();
+}
+// -------------------------------------------------------------------------
+const ClassInfo DOMKeyboardEvent::info = { "KeyboardEvent", &DOMKeyEventBase::info, &DOMKeyboardEventTable, 0 };
+
+/*
+@begin DOMKeyboardEventTable 2
+ keyIdentifier DOMKeyboardEvent::KeyIdentifier DontDelete|ReadOnly
+ keyLocation DOMKeyboardEvent::KeyLocation DontDelete|ReadOnly
+@end
+@begin DOMKeyboardEventProtoTable 2
+ initKeyboardEvent DOMKeyboardEvent::InitKeyboardEvent DontDelete|Function 7
+ getModifierState DOMKeyboardEvent::GetModifierState DontDelete|Function 1
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMKeyboardEventProto, DOMUIEventProto) //Note: no proto in KeyBase
+IMPLEMENT_PROTOFUNC_DOM(DOMKeyboardEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMKeyboardEvent", DOMKeyboardEventProto, DOMKeyboardEventProtoFunc)
+
+DOMKeyboardEvent::DOMKeyboardEvent(ExecState *exec, DOM::TextEvent ke) :
+ DOMKeyEventBase(DOMKeyboardEventProto::self(exec), ke) {}
+
+DOMKeyboardEvent::~DOMKeyboardEvent()
+{
+}
+
+Value DOMKeyboardEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+#ifdef KJS_VERBOSE
+ kdDebug(6070) << "DOMKeyboardEvent::tryGet " << p.qstring() << endl;
+#endif
+ return DOMObjectLookupGetValue<DOMKeyboardEvent,DOMKeyEventBase>(exec,p,&DOMKeyboardEventTable,this);
+}
+
+Value DOMKeyboardEvent::getValueProperty(ExecState *, int token) const
+{
+ DOM::KeyboardEventImpl* tevent = impl();
+ switch (token) {
+ case KeyIdentifier:
+ return String(tevent->keyIdentifier());
+ case KeyLocation:
+ return Number(tevent->keyLocation());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMKeyboardEvent::getValueProperty : " << token << endl;
+ return KJS::Undefined();
+ }
+}
+
+Value DOMKeyboardEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMKeyboardEvent, thisObj );
+ DOM::KeyboardEventImpl* keyEvent = static_cast<DOMKeyboardEvent *>(thisObj.imp())->impl();
+ switch (id) {
+ case DOMKeyboardEvent::InitKeyboardEvent:
+ keyEvent->initKeyboardEvent(args[0].toString(exec).string(), // typeArg
+ args[1].toBoolean(exec), // canBubbleArg
+ args[2].toBoolean(exec), // cancelableArg
+ toAbstractView(args[3]), // viewArg
+ args[4].toString(exec).string(), // keyIdentifierArg
+ args[5].toInteger(exec), // keyLocationArg
+ args[6].toString(exec).string()); //modifiersList
+ break;
+ case DOMKeyboardEvent::GetModifierState:
+ return Boolean(keyEvent->getModifierState(args[0].toString(exec).string()));
+ }
+ return Undefined();
+}
+
+// -------------------------------------------------------------------------
+const ClassInfo KeyboardEventConstructor::info = { "KeyboardEventConstructor", 0, &KeyboardEventConstructorTable, 0 };
+/*
+@begin KeyboardEventConstructorTable 4
+ DOM_KEY_LOCATION_STANDARD DOM::KeyboardEventImpl::DOM_KEY_LOCATION_STANDARD DontDelete|ReadOnly
+ DOM_KEY_LOCATION_LEFT DOM::KeyboardEventImpl::DOM_KEY_LOCATION_LEFT DontDelete|ReadOnly
+ DOM_KEY_LOCATION_RIGHT DOM::KeyboardEventImpl::DOM_KEY_LOCATION_RIGHT DontDelete|ReadOnly
+ DOM_KEY_LOCATION_NUMPAD DOM::KeyboardEventImpl::DOM_KEY_LOCATION_NUMPAD DontDelete|ReadOnly
+@end
+*/
+KeyboardEventConstructor::KeyboardEventConstructor(ExecState* exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype())
+{}
+
+Value KeyboardEventConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<KeyboardEventConstructor,DOMObject>(exec,p,&KeyboardEventConstructorTable,this);
+}
+
+Value KeyboardEventConstructor::getValueProperty(ExecState *, int token) const
+{
+ // We use the token as the value to return directly
+ return Number(token);
+}
+
+Value getKeyboardEventConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<KeyboardEventConstructor>(exec, "[[keyboardEvent.constructor]]");
+}
+
+
+// -------------------------------------------------------------------------
+const ClassInfo MutationEventConstructor::info = { "MutationEventConstructor", 0, &MutationEventConstructorTable, 0 };
+/*
+@begin MutationEventConstructorTable 3
+ MODIFICATION DOM::MutationEvent::MODIFICATION DontDelete|ReadOnly
+ ADDITION DOM::MutationEvent::ADDITION DontDelete|ReadOnly
+ REMOVAL DOM::MutationEvent::REMOVAL DontDelete|ReadOnly
+@end
+*/
+MutationEventConstructor::MutationEventConstructor(ExecState* exec)
+ : DOMObject(exec->interpreter()->builtinObjectPrototype())
+{
+}
+
+Value MutationEventConstructor::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<MutationEventConstructor,DOMObject>(exec,p,&MutationEventConstructorTable,this);
+}
+
+Value MutationEventConstructor::getValueProperty(ExecState *, int token) const
+{
+ // We use the token as the value to return directly
+ return Number(token);
+}
+
+Value getMutationEventConstructor(ExecState *exec)
+{
+ return cacheGlobalObject<MutationEventConstructor>(exec, "[[mutationEvent.constructor]]");
+}
+
+// -------------------------------------------------------------------------
+
+const ClassInfo DOMMutationEvent::info = { "MutationEvent", &DOMEvent::info, &DOMMutationEventTable, 0 };
+/*
+@begin DOMMutationEventTable 5
+ relatedNode DOMMutationEvent::RelatedNode DontDelete|ReadOnly
+ prevValue DOMMutationEvent::PrevValue DontDelete|ReadOnly
+ newValue DOMMutationEvent::NewValue DontDelete|ReadOnly
+ attrName DOMMutationEvent::AttrName DontDelete|ReadOnly
+ attrChange DOMMutationEvent::AttrChange DontDelete|ReadOnly
+@end
+@begin DOMMutationEventProtoTable 1
+ initMutationEvent DOMMutationEvent::InitMutationEvent DontDelete|Function 8
+@end
+*/
+KJS_DEFINE_PROTOTYPE_WITH_PROTOTYPE(DOMMutationEventProto, DOMEventProto)
+IMPLEMENT_PROTOFUNC_DOM(DOMMutationEventProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("DOMMutationEvent", DOMMutationEventProto, DOMMutationEventProtoFunc)
+
+DOMMutationEvent::DOMMutationEvent(ExecState *exec, DOM::MutationEvent me) :
+ DOMEvent(DOMMutationEventProto::self(exec), me) {}
+
+DOMMutationEvent::~DOMMutationEvent()
+{
+}
+
+Value DOMMutationEvent::tryGet(ExecState *exec, const Identifier &p) const
+{
+ return DOMObjectLookupGetValue<DOMMutationEvent,DOMEvent>(exec,p,&DOMMutationEventTable,this);
+}
+
+Value DOMMutationEvent::getValueProperty(ExecState *exec, int token) const
+{
+ switch (token) {
+ case RelatedNode:
+ return getDOMNode(exec,static_cast<DOM::MutationEvent>(event).relatedNode());
+ case PrevValue:
+ return String(static_cast<DOM::MutationEvent>(event).prevValue());
+ case NewValue:
+ return String(static_cast<DOM::MutationEvent>(event).newValue());
+ case AttrName:
+ return String(static_cast<DOM::MutationEvent>(event).attrName());
+ case AttrChange:
+ return Number((unsigned int)static_cast<DOM::MutationEvent>(event).attrChange());
+ default:
+ kdDebug(6070) << "WARNING: Unhandled token in DOMMutationEvent::getValueProperty : " << token << endl;
+ return Value();
+ }
+}
+
+Value DOMMutationEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
+{
+ KJS_CHECK_THIS( KJS::DOMMutationEvent, thisObj );
+ DOM::MutationEvent mutationEvent = static_cast<DOMMutationEvent *>(thisObj.imp())->toMutationEvent();
+ switch (id) {
+ case DOMMutationEvent::InitMutationEvent:
+ mutationEvent.initMutationEvent(args[0].toString(exec).string(), // typeArg,
+ args[1].toBoolean(exec), // canBubbleArg
+ args[2].toBoolean(exec), // cancelableArg
+ toNode(args[3]), // relatedNodeArg
+ args[4].toString(exec).string(), // prevValueArg
+ args[5].toString(exec).string(), // newValueArg
+ args[6].toString(exec).string(), // attrNameArg
+ args[7].toInteger(exec)); // attrChangeArg
+ return Undefined();
+ }
+ return Undefined();
+}
+
+} //namespace KJS