kjs_events.cpp

00001 // -*- c-basic-offset: 2 -*-
00002 /*
00003  *  This file is part of the KDE libraries
00004  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
00005  *  Copyright (C) 2003 Apple Computer, Inc.
00006  *
00007  *  This library is free software; you can redistribute it and/or
00008  *  modify it under the terms of the GNU Library General Public
00009  *  License as published by the Free Software Foundation; either
00010  *  version 2 of the License, or (at your option) any later version.
00011  *
00012  *  This library is distributed in the hope that it will be useful,
00013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  *  Library General Public License for more details.
00016  *
00017  *  You should have received a copy of the GNU Library General Public
00018  *  License along with this library; if not, write to the Free Software
00019  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020  */
00021 
00022 #include "kjs_window.h"
00023 #include "kjs_events.h"
00024 #include "kjs_events.lut.h"
00025 #include "kjs_views.h"
00026 #include "kjs_proxy.h"
00027 #include "xml/dom_nodeimpl.h"
00028 #include "xml/dom_docimpl.h"
00029 #include "xml/dom2_eventsimpl.h"
00030 #include "rendering/render_object.h"
00031 #include "rendering/render_canvas.h"
00032 #include "xml/dom2_eventsimpl.h"
00033 #include "khtml_part.h"
00034 
00035 #include <kdebug.h>
00036 
00037 using namespace KJS;
00038 using namespace DOM;
00039 
00040 // -------------------------------------------------------------------------
00041 
00042 JSEventListener::JSEventListener(Object _listener, ObjectImp *_compareListenerImp, const Object &_win, bool _html)
00043   : listener( _listener ), compareListenerImp( _compareListenerImp ), html( _html ), win( _win )
00044 {
00045     //fprintf(stderr,"JSEventListener::JSEventListener this=%p listener=%p\n",this,listener.imp());
00046   if (compareListenerImp) {
00047     static_cast<Window*>(win.imp())->jsEventListeners.insert(compareListenerImp, this);
00048   }
00049 }
00050 
00051 JSEventListener::~JSEventListener()
00052 {
00053   if (compareListenerImp) {
00054     static_cast<Window*>(win.imp())->jsEventListeners.remove(compareListenerImp);
00055   }
00056   //fprintf(stderr,"JSEventListener::~JSEventListener this=%p listener=%p\n",this,listener.imp());
00057 }
00058 
00059 void JSEventListener::handleEvent(DOM::Event &evt)
00060 {
00061 #ifdef KJS_DEBUGGER
00062   if (KJSDebugWin::debugWindow() && KJSDebugWin::debugWindow()->inSession())
00063     return;
00064 #endif
00065   KHTMLPart *part = ::qt_cast<KHTMLPart *>(static_cast<Window*>(win.imp())->part());
00066   KJSProxy *proxy = 0L;
00067   if (part)
00068     proxy = part->jScript();
00069 
00070   if (proxy && listener.isValid() && listener.implementsCall()) {
00071     ref();
00072 
00073     KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
00074     ExecState *exec = interpreter->globalExec();
00075 
00076     List args;
00077     args.append(getDOMEvent(exec,evt));
00078 
00079     // Set "this" to the event's current target
00080     Object thisObj = Object::dynamicCast(getDOMNode(exec,evt.currentTarget()));
00081     if ( !thisObj.isValid() ) {
00082       // Window events (window.onload/window.onresize etc.) must have 'this' set to the window.
00083       // DocumentImpl::defaultEventHandler sets currentTarget to 0 to mean 'window'.
00084       thisObj = win;
00085     }
00086 
00087     Window *window = static_cast<Window*>(win.imp());
00088     // Set the event we're handling in the Window object
00089     window->setCurrentEvent( &evt );
00090     // ... and in the interpreter
00091     interpreter->setCurrentEvent( &evt );
00092 
00093     KJSCPUGuard guard;
00094     guard.start();
00095     Value retval = listener.call(exec, thisObj, args);
00096     guard.stop();
00097 
00098     window->setCurrentEvent( 0 );
00099     interpreter->setCurrentEvent( 0 );
00100     if ( exec->hadException() )
00101       exec->clearException();
00102     else if (html)
00103     {
00104       QVariant ret = ValueToVariant(exec, retval);
00105       if (ret.type() == QVariant::Bool && ret.toBool() == false)
00106         evt.preventDefault();
00107     }
00108     window->afterScriptExecution();
00109     deref();
00110   }
00111 }
00112 
00113 DOM::DOMString JSEventListener::eventListenerType()
00114 {
00115     if (html)
00116     return "_khtml_HTMLEventListener";
00117     else
00118     return "_khtml_JSEventListener";
00119 }
00120 
00121 Object JSEventListener::listenerObj() const
00122 {
00123   return listener;
00124 }
00125 
00126 JSLazyEventListener::JSLazyEventListener(const QString &_code, const QString &_name, const Object &_win, DOM::NodeImpl* _originalNode)
00127   : JSEventListener(Object(), 0, _win, true),
00128     code(_code), name(_name),
00129     parsed(false)
00130 {
00131   // We don't retain the original node, because we assume it
00132   // will stay alive as long as this handler object is around
00133   // and we need to avoid a reference cycle. If JS transfers
00134   // this handler to another node, parseCode will be called and
00135   // then originalNode is no longer needed.
00136 
00137   originalNode = _originalNode;
00138 }
00139 
00140 JSLazyEventListener::~JSLazyEventListener()
00141 {
00142   if (listener.isValid()) {
00143     static_cast<Window*>(win.imp())->jsEventListeners.remove(listener.imp());
00144   }
00145 }
00146 
00147 void JSLazyEventListener::handleEvent(DOM::Event &evt)
00148 {
00149   parseCode();
00150   if (listener.isValid()) {
00151     JSEventListener::handleEvent(evt);
00152   }
00153 }
00154 
00155 
00156 Object JSLazyEventListener::listenerObj() const
00157 {
00158   parseCode();
00159   return listener;
00160 }
00161 
00162 void JSLazyEventListener::parseCode() const
00163 {
00164   if (!parsed) {
00165     KHTMLPart *part = ::qt_cast<KHTMLPart *>(static_cast<Window*>(win.imp())->part());
00166     KJSProxy *proxy = 0L;
00167     if (part)
00168       proxy = part->jScript();
00169 
00170     if (proxy) {
00171       KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
00172       ExecState *exec = interpreter->globalExec();
00173 
00174       //KJS::Constructor constr(KJS::Global::current().get("Function").imp());
00175       KJS::Object constr = interpreter->builtinFunction();
00176       KJS::List args;
00177 
00178       static KJS::String eventString("event");
00179 
00180       args.append(eventString);
00181       args.append(KJS::String(code));
00182       listener = constr.construct(exec, args); // ### is globalExec ok ?
00183 
00184       if (exec->hadException()) {
00185         exec->clearException();
00186 
00187         // failed to parse, so let's just make this listener a no-op
00188         listener = Object();
00189       } else if (!listener.inherits(&DeclaredFunctionImp::info)) {
00190         listener = Object();// Error creating function
00191       } else {
00192         DeclaredFunctionImp *declFunc = static_cast<DeclaredFunctionImp*>(listener.imp());
00193         declFunc->setName(Identifier(name));
00194 
00195         if (originalNode)
00196         {
00197           // Add the event's home element to the scope
00198           // (and the document, and the form - see KJS::HTMLElement::eventHandlerScope)
00199           ScopeChain scope = listener.scope();
00200 
00201           Object thisObj = Object::dynamicCast(getDOMNode(exec, originalNode));
00202 
00203           if (thisObj.isValid()) {
00204             static_cast<DOMNode*>(thisObj.imp())->pushEventHandlerScope(exec, scope);
00205 
00206             listener.setScope(scope);
00207           }
00208         }
00209       }
00210     }
00211 
00212     // no more need to keep the unparsed code around
00213     code = QString();
00214 
00215     if (listener.isValid()) {
00216       static_cast<Window*>(win.imp())->jsEventListeners.insert(listener.imp(),
00217                                                                (KJS::JSEventListener *)(this));
00218     }
00219 
00220     parsed = true;
00221   }
00222 }
00223 
00224 // -------------------------------------------------------------------------
00225 
00226 const ClassInfo EventConstructor::info = { "EventConstructor", 0, &EventConstructorTable, 0 };
00227 /*
00228 @begin EventConstructorTable 3
00229   CAPTURING_PHASE   DOM::Event::CAPTURING_PHASE DontDelete|ReadOnly
00230   AT_TARGET     DOM::Event::AT_TARGET       DontDelete|ReadOnly
00231   BUBBLING_PHASE    DOM::Event::BUBBLING_PHASE  DontDelete|ReadOnly
00232 # Reverse-engineered from Netscape
00233   MOUSEDOWN     1               DontDelete|ReadOnly
00234   MOUSEUP       2               DontDelete|ReadOnly
00235   MOUSEOVER     4               DontDelete|ReadOnly
00236   MOUSEOUT      8               DontDelete|ReadOnly
00237   MOUSEMOVE     16              DontDelete|ReadOnly
00238   MOUSEDRAG     32              DontDelete|ReadOnly
00239   CLICK         64              DontDelete|ReadOnly
00240   DBLCLICK      128             DontDelete|ReadOnly
00241   KEYDOWN       256             DontDelete|ReadOnly
00242   KEYUP         512             DontDelete|ReadOnly
00243   KEYPRESS      1024                DontDelete|ReadOnly
00244   DRAGDROP      2048                DontDelete|ReadOnly
00245   FOCUS         4096                DontDelete|ReadOnly
00246   BLUR          8192                DontDelete|ReadOnly
00247   SELECT        16384               DontDelete|ReadOnly
00248   CHANGE        32768               DontDelete|ReadOnly
00249 @end
00250 */
00251 
00252 EventConstructor::EventConstructor(ExecState *exec)
00253   : DOMObject(exec->interpreter()->builtinObjectPrototype())
00254 {
00255 }
00256 
00257 Value EventConstructor::tryGet(ExecState *exec, const Identifier &p) const
00258 {
00259   return DOMObjectLookupGetValue<EventConstructor, DOMObject>(exec,p,&EventConstructorTable,this);
00260 }
00261 
00262 Value EventConstructor::getValueProperty(ExecState *, int token) const
00263 {
00264   // We use the token as the value to return directly
00265   return Number(token);
00266 }
00267 
00268 Value KJS::getEventConstructor(ExecState *exec)
00269 {
00270   return cacheGlobalObject<EventConstructor>(exec, "[[event.constructor]]");
00271 }
00272 
00273 // -------------------------------------------------------------------------
00274 
00275 const ClassInfo DOMEvent::info = { "Event", 0, &DOMEventTable, 0 };
00276 /*
00277 @begin DOMEventTable 7
00278   type      DOMEvent::Type      DontDelete|ReadOnly
00279   target    DOMEvent::Target    DontDelete|ReadOnly
00280   currentTarget DOMEvent::CurrentTarget DontDelete|ReadOnly
00281   srcElement    DOMEvent::SrcElement    DontDelete|ReadOnly
00282   eventPhase    DOMEvent::EventPhase    DontDelete|ReadOnly
00283   bubbles   DOMEvent::Bubbles   DontDelete|ReadOnly
00284   cancelable    DOMEvent::Cancelable    DontDelete|ReadOnly
00285   timeStamp DOMEvent::TimeStamp DontDelete|ReadOnly
00286   returnValue   DOMEvent::ReturnValue   DontDelete
00287   cancelBubble  DOMEvent::CancelBubble  DontDelete
00288 @end
00289 @begin DOMEventProtoTable 3
00290   stopPropagation   DOMEvent::StopPropagation   DontDelete|Function 0
00291   preventDefault    DOMEvent::PreventDefault    DontDelete|Function 0
00292   initEvent     DOMEvent::InitEvent     DontDelete|Function 3
00293 @end
00294 */
00295 DEFINE_PROTOTYPE("DOMEvent", DOMEventProto)
00296 IMPLEMENT_PROTOFUNC_DOM(DOMEventProtoFunc)
00297 IMPLEMENT_PROTOTYPE(DOMEventProto, DOMEventProtoFunc)
00298 
00299 DOMEvent::DOMEvent(ExecState *exec, DOM::Event e)
00300   : DOMObject(DOMEventProto::self(exec)), event(e) { }
00301 
00302 DOMEvent::DOMEvent(const Object &proto, DOM::Event e)
00303   : DOMObject(proto), event(e) { }
00304 
00305 DOMEvent::~DOMEvent()
00306 {
00307   ScriptInterpreter::forgetDOMObject(event.handle());
00308 }
00309 
00310 Value DOMEvent::tryGet(ExecState *exec, const Identifier &p) const
00311 {
00312 #ifdef KJS_VERBOSE
00313   kdDebug() << "KJS::DOMEvent::tryGet " << p.qstring() << endl;
00314 #endif
00315   return DOMObjectLookupGetValue<DOMEvent,DOMObject>(exec, p, &DOMEventTable, this );
00316 }
00317 
00318 Value DOMEvent::getValueProperty(ExecState *exec, int token) const
00319 {
00320   switch (token) {
00321   case Type:
00322     return String(event.type());
00323   case Target:
00324   case SrcElement: /*MSIE extension - "the object that fired the event"*/
00325     return getDOMNode(exec,event.target());
00326   case CurrentTarget:
00327     return getDOMNode(exec,event.currentTarget());
00328   case EventPhase:
00329     return Number((unsigned int)event.eventPhase());
00330   case Bubbles:
00331     return Boolean(event.bubbles());
00332   case Cancelable:
00333     return Boolean(event.cancelable());
00334   case TimeStamp:
00335     return Number((long unsigned int)event.timeStamp()); // ### long long ?
00336   case ReturnValue: // MSIE extension
00337     return Boolean(event.handle()->defaultPrevented());
00338   case CancelBubble: // MSIE extension
00339     return Boolean(event.handle()->propagationStopped());
00340   default:
00341     kdDebug(6070) << "WARNING: Unhandled token in DOMEvent::getValueProperty : " << token << endl;
00342     return Value();
00343   }
00344 }
00345 
00346 Value DOMEvent::defaultValue(ExecState *exec, KJS::Type hint) const
00347 {
00348   if (event.handle()->id() == EventImpl::ERROR_EVENT && !event.handle()->message().isNull()) {
00349     return String(event.handle()->message());
00350   }
00351   else
00352     return DOMObject::defaultValue(exec,hint);
00353 }
00354 
00355 void DOMEvent::tryPut(ExecState *exec, const Identifier &propertyName,
00356                       const Value& value, int attr)
00357 {
00358   DOMObjectLookupPut<DOMEvent, DOMObject>(exec, propertyName, value, attr,
00359                                           &DOMEventTable, this);
00360 }
00361 
00362 void DOMEvent::putValueProperty(ExecState *exec, int token, const Value& value, int)
00363 {
00364   switch (token) {
00365   case ReturnValue: // MSIE equivalent for "preventDefault" (but with a way to reset it)
00366     // returnValue=false means "default action of the event on the source object is canceled",
00367     // which means preventDefault(true). Hence the '!'.
00368     event.handle()->preventDefault(!value.toBoolean(exec));
00369     break;
00370   case CancelBubble: // MSIE equivalent for "stopPropagation" (but with a way to reset it)
00371     event.handle()->stopPropagation(value.toBoolean(exec));
00372     break;
00373   default:
00374     break;
00375   }
00376 }
00377 
00378 Value DOMEventProtoFunc::tryCall(ExecState *exec, Object & thisObj, const List &args)
00379 {
00380   KJS_CHECK_THIS( KJS::DOMEvent, thisObj );
00381   DOM::Event event = static_cast<DOMEvent *>( thisObj.imp() )->toEvent();
00382   switch (id) {
00383     case DOMEvent::StopPropagation:
00384       event.stopPropagation();
00385       return Undefined();
00386     case DOMEvent::PreventDefault:
00387       event.preventDefault();
00388       return Undefined();
00389     case DOMEvent::InitEvent:
00390       event.initEvent(args[0].toString(exec).string(),args[1].toBoolean(exec),args[2].toBoolean(exec));
00391       return Undefined();
00392   };
00393   return Undefined();
00394 }
00395 
00396 Value KJS::getDOMEvent(ExecState *exec, DOM::Event e)
00397 {
00398   DOM::EventImpl *ei = e.handle();
00399   if (!ei)
00400     return Null();
00401   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
00402   DOMObject *ret = interp->getDOMObject(ei);
00403   if (!ret) {
00404     if (ei->isTextInputEvent())
00405       ret = new DOMTextEvent(exec, e);
00406     else if (ei->isKeyboardEvent())
00407       ret = new DOMKeyboardEvent(exec, e);
00408     else if (ei->isMouseEvent())
00409       ret = new DOMMouseEvent(exec, e);
00410     else if (ei->isUIEvent())
00411       ret = new DOMUIEvent(exec, e);
00412     else if (ei->isMutationEvent())
00413       ret = new DOMMutationEvent(exec, e);
00414     else
00415       ret = new DOMEvent(exec, e);
00416 
00417     interp->putDOMObject(ei, ret);
00418   }
00419 
00420   return Value(ret);
00421 }
00422 
00423 DOM::Event KJS::toEvent(const Value& val)
00424 {
00425   Object obj = Object::dynamicCast(val);
00426   if (!obj.isValid() || !obj.inherits(&DOMEvent::info))
00427     return DOM::Event();
00428 
00429   const DOMEvent *dobj = static_cast<const DOMEvent*>(obj.imp());
00430   return dobj->toEvent();
00431 }
00432 
00433 // -------------------------------------------------------------------------
00434 
00435 
00436 const ClassInfo EventExceptionConstructor::info = { "EventExceptionConstructor", 0, &EventExceptionConstructorTable, 0 };
00437 /*
00438 @begin EventExceptionConstructorTable 1
00439   UNSPECIFIED_EVENT_TYPE_ERR    DOM::EventException::UNSPECIFIED_EVENT_TYPE_ERR DontDelete|ReadOnly
00440 @end
00441 */
00442 EventExceptionConstructor::EventExceptionConstructor(ExecState *exec)
00443   : DOMObject(exec->interpreter()->builtinObjectPrototype())
00444 {
00445 }
00446 
00447 Value EventExceptionConstructor::tryGet(ExecState *exec, const Identifier &p) const
00448 {
00449   return DOMObjectLookupGetValue<EventExceptionConstructor, DOMObject>(exec,p,&EventExceptionConstructorTable,this);
00450 }
00451 
00452 Value EventExceptionConstructor::getValueProperty(ExecState *, int token) const
00453 {
00454   // We use the token as the value to return directly
00455   return Number(token);
00456 }
00457 
00458 Value KJS::getEventExceptionConstructor(ExecState *exec)
00459 {
00460   return cacheGlobalObject<EventExceptionConstructor>(exec, "[[eventException.constructor]]");
00461 }
00462 
00463 // -------------------------------------------------------------------------
00464 
00465 const ClassInfo DOMUIEvent::info = { "UIEvent", &DOMEvent::info, &DOMUIEventTable, 0 };
00466 /*
00467 @begin DOMUIEventTable 7
00468   view      DOMUIEvent::View    DontDelete|ReadOnly
00469   detail    DOMUIEvent::Detail  DontDelete|ReadOnly
00470   keyCode   DOMUIEvent::KeyCode DontDelete|ReadOnly
00471   charCode  DOMUIEvent::CharCode    DontDelete|ReadOnly
00472   layerX    DOMUIEvent::LayerX  DontDelete|ReadOnly
00473   layerY    DOMUIEvent::LayerY  DontDelete|ReadOnly
00474   pageX     DOMUIEvent::PageX   DontDelete|ReadOnly
00475   pageY     DOMUIEvent::PageY   DontDelete|ReadOnly
00476   which     DOMUIEvent::Which   DontDelete|ReadOnly
00477 @end
00478 @begin DOMUIEventProtoTable 1
00479   initUIEvent   DOMUIEvent::InitUIEvent DontDelete|Function 5
00480 @end
00481 */
00482 DEFINE_PROTOTYPE("DOMUIEvent",DOMUIEventProto)
00483 IMPLEMENT_PROTOFUNC_DOM(DOMUIEventProtoFunc)
00484 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMUIEventProto,DOMUIEventProtoFunc,DOMEventProto)
00485 
00486 DOMUIEvent::DOMUIEvent(ExecState *exec, DOM::UIEvent ue) :
00487   DOMEvent(DOMUIEventProto::self(exec), ue) {}
00488 
00489 DOMUIEvent::DOMUIEvent(const Object &proto, DOM::UIEvent ue) :
00490   DOMEvent(proto, ue) {}
00491 
00492 DOMUIEvent::~DOMUIEvent()
00493 {
00494 }
00495 
00496 Value DOMUIEvent::tryGet(ExecState *exec, const Identifier &p) const
00497 {
00498   return DOMObjectLookupGetValue<DOMUIEvent,DOMEvent>(exec,p,&DOMUIEventTable,this);
00499 }
00500 
00501 Value DOMUIEvent::getValueProperty(ExecState *exec, int token) const
00502 {
00503   switch (token) {
00504   case View:
00505     return getDOMAbstractView(exec,static_cast<DOM::UIEvent>(event).view());
00506   case Detail:
00507     return Number(static_cast<DOM::UIEvent>(event).detail());
00508   case KeyCode:
00509     // IE-compatibility
00510     return Number(static_cast<DOM::UIEvent>(event).keyCode());
00511   case CharCode:
00512     // IE-compatibility
00513     return Number(static_cast<DOM::UIEvent>(event).charCode());
00514   case LayerX:
00515     // NS-compatibility
00516     return Number(static_cast<DOM::UIEvent>(event).layerX());
00517   case LayerY:
00518     // NS-compatibility
00519     return Number(static_cast<DOM::UIEvent>(event).layerY());
00520   case PageX:
00521     // NS-compatibility
00522     return Number(static_cast<DOM::UIEvent>(event).pageX());
00523   case PageY:
00524     // NS-compatibility
00525     return Number(static_cast<DOM::UIEvent>(event).pageY());
00526   case Which:
00527     // NS-compatibility
00528     return Number(static_cast<DOM::UIEvent>(event).which());
00529   default:
00530     kdDebug(6070) << "WARNING: Unhandled token in DOMUIEvent::getValueProperty : " << token << endl;
00531     return Undefined();
00532   }
00533 }
00534 
00535 Value DOMUIEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00536 {
00537   KJS_CHECK_THIS( KJS::DOMUIEvent, thisObj );
00538   DOM::UIEvent uiEvent = static_cast<DOMUIEvent *>(thisObj.imp())->toUIEvent();
00539   switch (id) {
00540     case DOMUIEvent::InitUIEvent: {
00541       DOM::AbstractView v = toAbstractView(args[3]);
00542       static_cast<DOM::UIEvent>(uiEvent).initUIEvent(args[0].toString(exec).string(),
00543                                                      args[1].toBoolean(exec),
00544                                                      args[2].toBoolean(exec),
00545                                                      v,
00546                                                      args[4].toInteger(exec));
00547       }
00548       return Undefined();
00549   }
00550   return Undefined();
00551 }
00552 
00553 // -------------------------------------------------------------------------
00554 
00555 const ClassInfo DOMMouseEvent::info = { "MouseEvent", &DOMUIEvent::info, &DOMMouseEventTable, 0 };
00556 
00557 /*
00558 @begin DOMMouseEventTable 2
00559   screenX   DOMMouseEvent::ScreenX  DontDelete|ReadOnly
00560   screenY   DOMMouseEvent::ScreenY  DontDelete|ReadOnly
00561   clientX   DOMMouseEvent::ClientX  DontDelete|ReadOnly
00562   x     DOMMouseEvent::X    DontDelete|ReadOnly
00563   clientY   DOMMouseEvent::ClientY  DontDelete|ReadOnly
00564   y     DOMMouseEvent::Y    DontDelete|ReadOnly
00565   offsetX   DOMMouseEvent::OffsetX  DontDelete|ReadOnly
00566   offsetY   DOMMouseEvent::OffsetY  DontDelete|ReadOnly
00567   ctrlKey   DOMMouseEvent::CtrlKey  DontDelete|ReadOnly
00568   shiftKey  DOMMouseEvent::ShiftKey DontDelete|ReadOnly
00569   altKey    DOMMouseEvent::AltKey   DontDelete|ReadOnly
00570   metaKey   DOMMouseEvent::MetaKey  DontDelete|ReadOnly
00571   button    DOMMouseEvent::Button   DontDelete|ReadOnly
00572   relatedTarget DOMMouseEvent::RelatedTarget DontDelete|ReadOnly
00573   fromElement   DOMMouseEvent::FromElement DontDelete|ReadOnly
00574   toElement DOMMouseEvent::ToElement    DontDelete|ReadOnly
00575 @end
00576 @begin DOMMouseEventProtoTable 1
00577   initMouseEvent    DOMMouseEvent::InitMouseEvent   DontDelete|Function 15
00578 @end
00579 */
00580 DEFINE_PROTOTYPE("DOMMouseEvent",DOMMouseEventProto)
00581 IMPLEMENT_PROTOFUNC_DOM(DOMMouseEventProtoFunc)
00582 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMMouseEventProto,DOMMouseEventProtoFunc,DOMUIEventProto)
00583 
00584 DOMMouseEvent::DOMMouseEvent(ExecState *exec, DOM::MouseEvent me) :
00585   DOMUIEvent(DOMMouseEventProto::self(exec), me) {}
00586 
00587 DOMMouseEvent::~DOMMouseEvent()
00588 {
00589 }
00590 
00591 Value DOMMouseEvent::tryGet(ExecState *exec, const Identifier &p) const
00592 {
00593 #ifdef KJS_VERBOSE
00594   kdDebug(6070) << "DOMMouseEvent::tryGet " << p.qstring() << endl;
00595 #endif
00596   return DOMObjectLookupGetValue<DOMMouseEvent,DOMUIEvent>(exec,p,&DOMMouseEventTable,this);
00597 }
00598 
00599 Value DOMMouseEvent::getValueProperty(ExecState *exec, int token) const
00600 {
00601   switch (token) {
00602   case ScreenX:
00603     return Number(static_cast<DOM::MouseEvent>(event).screenX());
00604   case ScreenY:
00605     return Number(static_cast<DOM::MouseEvent>(event).screenY());
00606   case ClientX:
00607   case X:
00608     return Number(static_cast<DOM::MouseEvent>(event).clientX());
00609   case ClientY:
00610   case Y:
00611     return Number(static_cast<DOM::MouseEvent>(event).clientY());
00612   case OffsetX:
00613   case OffsetY: // MSIE extension
00614   {
00615     DOM::Node node = event.target();
00616     node.handle()->getDocument()->updateRendering();
00617     khtml::RenderObject *rend = node.handle() ? node.handle()->renderer() : 0L;
00618     int x = static_cast<DOM::MouseEvent>(event).clientX();
00619     int y = static_cast<DOM::MouseEvent>(event).clientY();
00620     if ( rend ) {
00621       int xPos, yPos;
00622       if ( rend->absolutePosition( xPos, yPos ) ) {
00623         kdDebug() << "DOMMouseEvent::getValueProperty rend=" << rend << "  xPos=" << xPos << "  yPos=" << yPos << endl;
00624         x -= xPos;
00625         y -= yPos;
00626       }
00627       if ( rend->canvas() ) {
00628         int cYPos, cXPos;
00629         rend->canvas()->absolutePosition( cXPos,  cYPos,  true );
00630         x += cXPos;
00631         y += cYPos;
00632       }
00633     }
00634     return Number( token == OffsetX ? x : y );
00635   }
00636   case CtrlKey:
00637     return Boolean(static_cast<DOM::MouseEvent>(event).ctrlKey());
00638   case ShiftKey:
00639     return Boolean(static_cast<DOM::MouseEvent>(event).shiftKey());
00640   case AltKey:
00641     return Boolean(static_cast<DOM::MouseEvent>(event).altKey());
00642   case MetaKey:
00643     return Boolean(static_cast<DOM::MouseEvent>(event).metaKey());
00644   case Button:
00645   {
00646     if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat ) {
00647         return Number(static_cast<DOM::MouseEvent>(event).button());
00648     }
00649     // Tricky. The DOM (and khtml) use 0 for LMB, 1 for MMB and 2 for RMB
00650     // but MSIE uses 1=LMB, 2=RMB, 4=MMB, as a bitfield
00651     int domButton = static_cast<DOM::MouseEvent>(event).button();
00652     int button = domButton==0 ? 1 : domButton==1 ? 4 : domButton==2 ? 2 : 0;
00653     return Number( (unsigned int)button );
00654   }
00655   case ToElement:
00656     // MSIE extension - "the object toward which the user is moving the mouse pointer"
00657     if (event.handle()->id() == DOM::EventImpl::MOUSEOUT_EVENT)
00658       return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).relatedTarget());
00659     return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).target());
00660   case FromElement:
00661     // MSIE extension - "object from which activation
00662     // or the mouse pointer is exiting during the event" (huh?)
00663     if (event.handle()->id() == DOM::EventImpl::MOUSEOUT_EVENT)
00664       return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).target());
00665     /* fall through */
00666   case RelatedTarget:
00667     return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).relatedTarget());
00668   default:
00669     kdDebug(6070) << "WARNING: Unhandled token in DOMMouseEvent::getValueProperty : " << token << endl;
00670     return Value();
00671   }
00672 }
00673 
00674 Value DOMMouseEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00675 {
00676   KJS_CHECK_THIS( KJS::DOMMouseEvent, thisObj );
00677   DOM::MouseEvent mouseEvent = static_cast<DOMMouseEvent *>(thisObj.imp())->toMouseEvent();
00678   switch (id) {
00679     case DOMMouseEvent::InitMouseEvent:
00680       mouseEvent.initMouseEvent(args[0].toString(exec).string(), // typeArg
00681                                 args[1].toBoolean(exec), // canBubbleArg
00682                                 args[2].toBoolean(exec), // cancelableArg
00683                                 toAbstractView(args[3]), // viewArg
00684                                 args[4].toInteger(exec), // detailArg
00685                                 args[5].toInteger(exec), // screenXArg
00686                                 args[6].toInteger(exec), // screenYArg
00687                                 args[7].toInteger(exec), // clientXArg
00688                                 args[8].toInteger(exec), // clientYArg
00689                                 args[9].toBoolean(exec), // ctrlKeyArg
00690                                 args[10].toBoolean(exec), // altKeyArg
00691                                 args[11].toBoolean(exec), // shiftKeyArg
00692                                 args[12].toBoolean(exec), // metaKeyArg
00693                                 args[13].toInteger(exec), // buttonArg
00694                                 toNode(args[14])); // relatedTargetArg
00695       return Undefined();
00696   }
00697   return Undefined();
00698 }
00699 
00700 // -------------------------------------------------------------------------
00701 
00702 const ClassInfo DOMKeyEventBase::info = { "KeyEventBase", &DOMUIEvent::info, &DOMKeyEventBaseTable, 0 };
00703 
00704 /*
00705 @begin DOMKeyEventBaseTable 5
00706   keyVal     DOMKeyEventBase::Key         DontDelete|ReadOnly
00707   virtKeyVal     DOMKeyEventBase::VirtKey     DontDelete|ReadOnly
00708   ctrlKey        DOMKeyEventBase::CtrlKey     DontDelete|ReadOnly
00709   altKey         DOMKeyEventBase::AltKey      DontDelete|ReadOnly
00710   shiftKey       DOMKeyEventBase::ShiftKey    DontDelete|ReadOnly
00711   altKey         DOMKeyEventBase::AltKey      DontDelete|ReadOnly
00712 @end
00713 */
00714 
00715 DOMKeyEventBase::DOMKeyEventBase(const Object &proto, DOM::TextEvent ke) :
00716   DOMUIEvent(proto, ke) {}
00717 
00718 DOMKeyEventBase::~DOMKeyEventBase()
00719 {}
00720 
00721 Value DOMKeyEventBase::tryGet(ExecState *exec,const Identifier &p) const
00722 {
00723 #ifdef KJS_VERBOSE
00724   kdDebug(6070) << "DOMKeyEventBase::tryGet " << p.qstring() << endl;
00725 #endif
00726   return DOMObjectLookupGetValue<DOMKeyEventBase,DOMUIEvent>(exec,p,&DOMKeyEventBaseTable,this);
00727 }
00728 
00729 Value DOMKeyEventBase::getValueProperty(ExecState *, int token) const
00730 {
00731   DOM::KeyEventBaseImpl* tevent = impl();
00732   switch (token) {
00733   case Key:
00734     return Number(tevent->keyVal());
00735   case VirtKey:
00736     return Number(tevent->virtKeyVal());
00737   // these modifier attributes actually belong into a KeyboardEvent interface,
00738   // but we want them on "keypress" as well.
00739   case CtrlKey:
00740     return Boolean(tevent->ctrlKey());
00741   case ShiftKey:
00742     return Boolean(tevent->shiftKey());
00743   case AltKey:
00744     return Boolean(tevent->altKey());
00745   case MetaKey:
00746     return Boolean(tevent->metaKey());
00747   default:
00748     kdDebug(6070) << "WARNING: Unhandled token in DOMTextEvent::getValueProperty : " << token << endl;
00749     return KJS::Undefined();
00750   }
00751 }
00752 
00753 // -------------------------------------------------------------------------
00754 const ClassInfo DOMTextEvent::info = { "TextEvent", &DOMKeyEventBase::info, &DOMTextEventTable, 0 };
00755 
00756 /*
00757 @begin DOMTextEventTable 1
00758   data           DOMTextEvent::Data          DontDelete|ReadOnly
00759 @end
00760 @begin DOMTextEventProtoTable 1
00761   initTextEvent DOMTextEvent::InitTextEvent DontDelete|Function 5
00762   # Missing: initTextEventNS
00763 @end
00764 */
00765 DEFINE_PROTOTYPE("DOMTextEvent",DOMTextEventProto)
00766 IMPLEMENT_PROTOFUNC_DOM(DOMTextEventProtoFunc)
00767 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMTextEventProto,DOMTextEventProtoFunc,DOMUIEventProto) //Note: no proto in KeyBase
00768 
00769 DOMTextEvent::DOMTextEvent(ExecState *exec, DOM::TextEvent ke) :
00770   DOMKeyEventBase(DOMTextEventProto::self(exec), ke) {}
00771 
00772 DOMTextEvent::~DOMTextEvent()
00773 {
00774 }
00775 
00776 Value DOMTextEvent::tryGet(ExecState *exec, const Identifier &p) const
00777 {
00778 #ifdef KJS_VERBOSE
00779   kdDebug(6070) << "DOMTextEvent::tryGet " << p.qstring() << endl;
00780 #endif
00781   return DOMObjectLookupGetValue<DOMTextEvent,DOMKeyEventBase>(exec,p,&DOMTextEventTable,this);
00782 }
00783 
00784 Value DOMTextEvent::getValueProperty(ExecState *, int token) const
00785 {
00786   DOM::TextEventImpl* tevent = impl();
00787   switch (token) {
00788   case Data:
00789     return String(tevent->data());
00790   default:
00791     kdDebug(6070) << "WARNING: Unhandled token in DOMTextEvent::getValueProperty : " << token << endl;
00792     return KJS::Undefined();
00793   }
00794 }
00795 
00796 Value DOMTextEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00797 {
00798   KJS_CHECK_THIS( KJS::DOMTextEvent, thisObj );
00799   DOM::TextEventImpl* keyEvent = static_cast<DOMTextEvent *>(thisObj.imp())->impl();
00800   switch (id) {
00801     case DOMTextEvent::InitTextEvent:
00802       keyEvent->initTextEvent(args[0].toString(exec).string(), // typeArg
00803                             args[1].toBoolean(exec), // canBubbleArg
00804                             args[2].toBoolean(exec), // cancelableArg
00805                             toAbstractView(args[3]), // viewArg
00806                             args[4].toString(exec).string()); // dataArg
00807 
00808       return Undefined();
00809   }
00810   return Undefined();
00811 }
00812 // -------------------------------------------------------------------------
00813 const ClassInfo DOMKeyboardEvent::info = { "KeyboardEvent", &DOMKeyEventBase::info, &DOMKeyboardEventTable, 0 };
00814 
00815 /*
00816 @begin DOMKeyboardEventTable 2
00817   keyIdentifier  DOMKeyboardEvent::KeyIdentifier  DontDelete|ReadOnly
00818   keyLocation    DOMKeyboardEvent::KeyLocation    DontDelete|ReadOnly
00819 @end
00820 @begin DOMKeyboardEventProtoTable 2
00821   initKeyboardEvent DOMKeyboardEvent::InitKeyboardEvent DontDelete|Function 7
00822   getModifierState      DOMKeyboardEvent::GetModifierState      DontDelete|Function 1
00823 @end
00824 */
00825 DEFINE_PROTOTYPE("DOMKeyboardEvent",DOMKeyboardEventProto)
00826 IMPLEMENT_PROTOFUNC_DOM(DOMKeyboardEventProtoFunc)
00827 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMKeyboardEventProto,DOMKeyboardEventProtoFunc,DOMUIEventProto) //Note: no proto in KeyBase
00828 
00829 DOMKeyboardEvent::DOMKeyboardEvent(ExecState *exec, DOM::TextEvent ke) :
00830   DOMKeyEventBase(DOMKeyboardEventProto::self(exec), ke) {}
00831 
00832 DOMKeyboardEvent::~DOMKeyboardEvent()
00833 {
00834 }
00835 
00836 Value DOMKeyboardEvent::tryGet(ExecState *exec, const Identifier &p) const
00837 {
00838 #ifdef KJS_VERBOSE
00839   kdDebug(6070) << "DOMKeyboardEvent::tryGet " << p.qstring() << endl;
00840 #endif
00841   return DOMObjectLookupGetValue<DOMKeyboardEvent,DOMKeyEventBase>(exec,p,&DOMKeyboardEventTable,this);
00842 }
00843 
00844 Value DOMKeyboardEvent::getValueProperty(ExecState *, int token) const
00845 {
00846   DOM::KeyboardEventImpl* tevent = impl();
00847   switch (token) {
00848   case KeyIdentifier:
00849     return String(tevent->keyIdentifier());
00850   case KeyLocation:
00851     return Number(tevent->keyLocation());
00852   default:
00853     kdDebug(6070) << "WARNING: Unhandled token in DOMKeyboardEvent::getValueProperty : " << token << endl;
00854     return KJS::Undefined();
00855   }
00856 }
00857 
00858 Value DOMKeyboardEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00859 {
00860   KJS_CHECK_THIS( KJS::DOMKeyboardEvent, thisObj );
00861   DOM::KeyboardEventImpl* keyEvent = static_cast<DOMKeyboardEvent *>(thisObj.imp())->impl();
00862   switch (id) {
00863     case DOMKeyboardEvent::InitKeyboardEvent:
00864       keyEvent->initKeyboardEvent(args[0].toString(exec).string(), // typeArg
00865                             args[1].toBoolean(exec), // canBubbleArg
00866                             args[2].toBoolean(exec), // cancelableArg
00867                             toAbstractView(args[3]), // viewArg
00868                             args[4].toString(exec).string(), // keyIdentifierArg
00869                             args[5].toInteger(exec),         // keyLocationArg
00870                             args[6].toString(exec).string()); //modifiersList
00871       break;
00872     case DOMKeyboardEvent::GetModifierState:
00873       return Boolean(keyEvent->getModifierState(args[0].toString(exec).string()));
00874   }
00875   return Undefined();
00876 }
00877 
00878 // -------------------------------------------------------------------------
00879 const ClassInfo KeyboardEventConstructor::info = { "KeyboardEventConstructor", 0, &KeyboardEventConstructorTable, 0 };
00880 /*
00881 @begin KeyboardEventConstructorTable 4
00882   DOM_KEY_LOCATION_STANDARD  DOM::KeyboardEventImpl::DOM_KEY_LOCATION_STANDARD DontDelete|ReadOnly
00883   DOM_KEY_LOCATION_LEFT      DOM::KeyboardEventImpl::DOM_KEY_LOCATION_LEFT     DontDelete|ReadOnly
00884   DOM_KEY_LOCATION_RIGHT     DOM::KeyboardEventImpl::DOM_KEY_LOCATION_RIGHT    DontDelete|ReadOnly
00885   DOM_KEY_LOCATION_NUMPAD    DOM::KeyboardEventImpl::DOM_KEY_LOCATION_NUMPAD   DontDelete|ReadOnly
00886 @end
00887 */
00888 KeyboardEventConstructor::KeyboardEventConstructor(ExecState* exec)
00889   : DOMObject(exec->interpreter()->builtinObjectPrototype())
00890 {}
00891 
00892 Value KeyboardEventConstructor::tryGet(ExecState *exec, const Identifier &p) const
00893 {
00894   return DOMObjectLookupGetValue<KeyboardEventConstructor,DOMObject>(exec,p,&KeyboardEventConstructorTable,this);
00895 }
00896 
00897 Value KeyboardEventConstructor::getValueProperty(ExecState *, int token) const
00898 {
00899   // We use the token as the value to return directly
00900   return Number(token);
00901 }
00902 
00903 Value KJS::getKeyboardEventConstructor(ExecState *exec)
00904 {
00905   return cacheGlobalObject<KeyboardEventConstructor>(exec, "[[keyboardEvent.constructor]]");
00906 }
00907 
00908 
00909 // -------------------------------------------------------------------------
00910 const ClassInfo MutationEventConstructor::info = { "MutationEventConstructor", 0, &MutationEventConstructorTable, 0 };
00911 /*
00912 @begin MutationEventConstructorTable 3
00913   MODIFICATION  DOM::MutationEvent::MODIFICATION    DontDelete|ReadOnly
00914   ADDITION  DOM::MutationEvent::ADDITION        DontDelete|ReadOnly
00915   REMOVAL   DOM::MutationEvent::REMOVAL     DontDelete|ReadOnly
00916 @end
00917 */
00918 MutationEventConstructor::MutationEventConstructor(ExecState* exec)
00919   : DOMObject(exec->interpreter()->builtinObjectPrototype())
00920 {
00921 }
00922 
00923 Value MutationEventConstructor::tryGet(ExecState *exec, const Identifier &p) const
00924 {
00925   return DOMObjectLookupGetValue<MutationEventConstructor,DOMObject>(exec,p,&MutationEventConstructorTable,this);
00926 }
00927 
00928 Value MutationEventConstructor::getValueProperty(ExecState *, int token) const
00929 {
00930   // We use the token as the value to return directly
00931   return Number(token);
00932 }
00933 
00934 Value KJS::getMutationEventConstructor(ExecState *exec)
00935 {
00936   return cacheGlobalObject<MutationEventConstructor>(exec, "[[mutationEvent.constructor]]");
00937 }
00938 
00939 // -------------------------------------------------------------------------
00940 
00941 const ClassInfo DOMMutationEvent::info = { "MutationEvent", &DOMEvent::info, &DOMMutationEventTable, 0 };
00942 /*
00943 @begin DOMMutationEventTable 5
00944   relatedNode   DOMMutationEvent::RelatedNode   DontDelete|ReadOnly
00945   prevValue DOMMutationEvent::PrevValue DontDelete|ReadOnly
00946   newValue  DOMMutationEvent::NewValue  DontDelete|ReadOnly
00947   attrName  DOMMutationEvent::AttrName  DontDelete|ReadOnly
00948   attrChange    DOMMutationEvent::AttrChange    DontDelete|ReadOnly
00949 @end
00950 @begin DOMMutationEventProtoTable 1
00951   initMutationEvent DOMMutationEvent::InitMutationEvent DontDelete|Function 8
00952 @end
00953 */
00954 DEFINE_PROTOTYPE("DOMMutationEvent",DOMMutationEventProto)
00955 IMPLEMENT_PROTOFUNC_DOM(DOMMutationEventProtoFunc)
00956 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMMutationEventProto,DOMMutationEventProtoFunc,DOMEventProto)
00957 
00958 DOMMutationEvent::DOMMutationEvent(ExecState *exec, DOM::MutationEvent me) :
00959   DOMEvent(DOMMutationEventProto::self(exec), me) {}
00960 
00961 DOMMutationEvent::~DOMMutationEvent()
00962 {
00963 }
00964 
00965 Value DOMMutationEvent::tryGet(ExecState *exec, const Identifier &p) const
00966 {
00967   return DOMObjectLookupGetValue<DOMMutationEvent,DOMEvent>(exec,p,&DOMMutationEventTable,this);
00968 }
00969 
00970 Value DOMMutationEvent::getValueProperty(ExecState *exec, int token) const
00971 {
00972   switch (token) {
00973   case RelatedNode:
00974     return getDOMNode(exec,static_cast<DOM::MutationEvent>(event).relatedNode());
00975   case PrevValue:
00976     return String(static_cast<DOM::MutationEvent>(event).prevValue());
00977   case NewValue:
00978     return String(static_cast<DOM::MutationEvent>(event).newValue());
00979   case AttrName:
00980     return String(static_cast<DOM::MutationEvent>(event).attrName());
00981   case AttrChange:
00982     return Number((unsigned int)static_cast<DOM::MutationEvent>(event).attrChange());
00983   default:
00984     kdDebug(6070) << "WARNING: Unhandled token in DOMMutationEvent::getValueProperty : " << token << endl;
00985     return Value();
00986   }
00987 }
00988 
00989 Value DOMMutationEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00990 {
00991   KJS_CHECK_THIS( KJS::DOMMutationEvent, thisObj );
00992   DOM::MutationEvent mutationEvent = static_cast<DOMMutationEvent *>(thisObj.imp())->toMutationEvent();
00993   switch (id) {
00994     case DOMMutationEvent::InitMutationEvent:
00995       mutationEvent.initMutationEvent(args[0].toString(exec).string(), // typeArg,
00996                                       args[1].toBoolean(exec), // canBubbleArg
00997                                       args[2].toBoolean(exec), // cancelableArg
00998                                       toNode(args[3]), // relatedNodeArg
00999                                       args[4].toString(exec).string(), // prevValueArg
01000                                       args[5].toString(exec).string(), // newValueArg
01001                                       args[6].toString(exec).string(), // attrNameArg
01002                                       args[7].toInteger(exec)); // attrChangeArg
01003       return Undefined();
01004   }
01005   return Undefined();
01006 }
KDE Home | KDE Accessibility Home | Description of Access Keys