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 DOMEvent::info = { "Event", 0, &DOMEventTable, 0 };
00227 /*
00228 @begin DOMEventTable 7
00229   type      DOMEvent::Type      DontDelete|ReadOnly
00230   target    DOMEvent::Target    DontDelete|ReadOnly
00231   currentTarget DOMEvent::CurrentTarget DontDelete|ReadOnly
00232   srcElement    DOMEvent::SrcElement    DontDelete|ReadOnly
00233   eventPhase    DOMEvent::EventPhase    DontDelete|ReadOnly
00234   bubbles   DOMEvent::Bubbles   DontDelete|ReadOnly
00235   cancelable    DOMEvent::Cancelable    DontDelete|ReadOnly
00236   timeStamp DOMEvent::TimeStamp DontDelete|ReadOnly
00237   returnValue   DOMEvent::ReturnValue   DontDelete
00238   cancelBubble  DOMEvent::CancelBubble  DontDelete
00239 @end
00240 @begin DOMEventProtoTable 3
00241   stopPropagation   DOMEvent::StopPropagation   DontDelete|Function 0
00242   preventDefault    DOMEvent::PreventDefault    DontDelete|Function 0
00243   initEvent     DOMEvent::InitEvent     DontDelete|Function 3
00244 @end
00245 */
00246 DEFINE_PROTOTYPE("DOMEvent", DOMEventProto)
00247 IMPLEMENT_PROTOFUNC_DOM(DOMEventProtoFunc)
00248 IMPLEMENT_PROTOTYPE(DOMEventProto, DOMEventProtoFunc)
00249 
00250 DOMEvent::DOMEvent(ExecState *exec, DOM::Event e)
00251   : DOMObject(DOMEventProto::self(exec)), event(e) { }
00252 
00253 DOMEvent::DOMEvent(const Object &proto, DOM::Event e)
00254   : DOMObject(proto), event(e) { }
00255 
00256 DOMEvent::~DOMEvent()
00257 {
00258   ScriptInterpreter::forgetDOMObject(event.handle());
00259 }
00260 
00261 Value DOMEvent::tryGet(ExecState *exec, const Identifier &p) const
00262 {
00263 #ifdef KJS_VERBOSE
00264   kdDebug() << "KJS::DOMEvent::tryGet " << p.qstring() << endl;
00265 #endif
00266   return DOMObjectLookupGetValue<DOMEvent,DOMObject>(exec, p, &DOMEventTable, this );
00267 }
00268 
00269 Value DOMEvent::getValueProperty(ExecState *exec, int token) const
00270 {
00271   switch (token) {
00272   case Type:
00273     return String(event.type());
00274   case Target:
00275   case SrcElement: /*MSIE extension - "the object that fired the event"*/
00276     return getDOMNode(exec,event.target());
00277   case CurrentTarget:
00278     return getDOMNode(exec,event.currentTarget());
00279   case EventPhase:
00280     return Number((unsigned int)event.eventPhase());
00281   case Bubbles:
00282     return Boolean(event.bubbles());
00283   case Cancelable:
00284     return Boolean(event.cancelable());
00285   case TimeStamp:
00286     return Number((long unsigned int)event.timeStamp()); // ### long long ?
00287   case ReturnValue: // MSIE extension
00288     return Boolean(event.handle()->defaultPrevented());
00289   case CancelBubble: // MSIE extension
00290     return Boolean(event.handle()->propagationStopped());
00291   default:
00292     kdDebug(6070) << "WARNING: Unhandled token in DOMEvent::getValueProperty : " << token << endl;
00293     return Value();
00294   }
00295 }
00296 
00297 Value DOMEvent::defaultValue(ExecState *exec, KJS::Type hint) const
00298 {
00299   if (event.handle()->id() == EventImpl::ERROR_EVENT && !event.handle()->message().isNull()) {
00300     return String(event.handle()->message());
00301   }
00302   else
00303     return DOMObject::defaultValue(exec,hint);
00304 }
00305 
00306 void DOMEvent::tryPut(ExecState *exec, const Identifier &propertyName,
00307                       const Value& value, int attr)
00308 {
00309   DOMObjectLookupPut<DOMEvent, DOMObject>(exec, propertyName, value, attr,
00310                                           &DOMEventTable, this);
00311 }
00312 
00313 void DOMEvent::putValueProperty(ExecState *exec, int token, const Value& value, int)
00314 {
00315   switch (token) {
00316   case ReturnValue: // MSIE equivalent for "preventDefault" (but with a way to reset it)
00317     // returnValue=false means "default action of the event on the source object is canceled",
00318     // which means preventDefault(true). Hence the '!'.
00319     event.handle()->preventDefault(!value.toBoolean(exec));
00320     break;
00321   case CancelBubble: // MSIE equivalent for "stopPropagation" (but with a way to reset it)
00322     event.handle()->stopPropagation(value.toBoolean(exec));
00323     break;
00324   default:
00325     break;
00326   }
00327 }
00328 
00329 Value DOMEventProtoFunc::tryCall(ExecState *exec, Object & thisObj, const List &args)
00330 {
00331   KJS_CHECK_THIS( KJS::DOMEvent, thisObj );
00332   DOM::Event event = static_cast<DOMEvent *>( thisObj.imp() )->toEvent();
00333   switch (id) {
00334     case DOMEvent::StopPropagation:
00335       event.stopPropagation();
00336       return Undefined();
00337     case DOMEvent::PreventDefault:
00338       event.preventDefault();
00339       return Undefined();
00340     case DOMEvent::InitEvent:
00341       event.initEvent(args[0].toString(exec).string(),args[1].toBoolean(exec),args[2].toBoolean(exec));
00342       return Undefined();
00343   };
00344   return Undefined();
00345 }
00346 
00347 Value KJS::getDOMEvent(ExecState *exec, DOM::Event e)
00348 {
00349   DOM::EventImpl *ei = e.handle();
00350   if (!ei)
00351     return Null();
00352   ScriptInterpreter* interp = static_cast<ScriptInterpreter *>(exec->interpreter());
00353   DOMObject *ret = interp->getDOMObject(ei);
00354   if (!ret) {
00355     if (ei->isTextInputEvent())
00356       ret = new DOMTextEvent(exec, e);
00357     else if (ei->isKeyboardEvent())
00358       ret = new DOMKeyboardEvent(exec, e);
00359     else if (ei->isMouseEvent())
00360       ret = new DOMMouseEvent(exec, e);
00361     else if (ei->isUIEvent())
00362       ret = new DOMUIEvent(exec, e);
00363     else if (ei->isMutationEvent())
00364       ret = new DOMMutationEvent(exec, e);
00365     else
00366       ret = new DOMEvent(exec, e);
00367 
00368     interp->putDOMObject(ei, ret);
00369   }
00370 
00371   return Value(ret);
00372 }
00373 
00374 DOM::Event KJS::toEvent(const Value& val)
00375 {
00376   Object obj = Object::dynamicCast(val);
00377   if (!obj.isValid() || !obj.inherits(&DOMEvent::info))
00378     return DOM::Event();
00379 
00380   const DOMEvent *dobj = static_cast<const DOMEvent*>(obj.imp());
00381   return dobj->toEvent();
00382 }
00383 
00384 // -------------------------------------------------------------------------
00385 /*
00386 @begin EventConstantsTable 23
00387   CAPTURING_PHASE   DOM::Event::CAPTURING_PHASE DontDelete|ReadOnly
00388   AT_TARGET     DOM::Event::AT_TARGET       DontDelete|ReadOnly
00389   BUBBLING_PHASE    DOM::Event::BUBBLING_PHASE  DontDelete|ReadOnly
00390 # Reverse-engineered from Netscape
00391   MOUSEDOWN     1               DontDelete|ReadOnly
00392   MOUSEUP       2               DontDelete|ReadOnly
00393   MOUSEOVER     4               DontDelete|ReadOnly
00394   MOUSEOUT      8               DontDelete|ReadOnly
00395   MOUSEMOVE     16              DontDelete|ReadOnly
00396   MOUSEDRAG     32              DontDelete|ReadOnly
00397   CLICK         64              DontDelete|ReadOnly
00398   DBLCLICK      128             DontDelete|ReadOnly
00399   KEYDOWN       256             DontDelete|ReadOnly
00400   KEYUP         512             DontDelete|ReadOnly
00401   KEYPRESS      1024                DontDelete|ReadOnly
00402   DRAGDROP      2048                DontDelete|ReadOnly
00403   FOCUS         4096                DontDelete|ReadOnly
00404   BLUR          8192                DontDelete|ReadOnly
00405   SELECT        16384               DontDelete|ReadOnly
00406   CHANGE        32768               DontDelete|ReadOnly
00407 @end
00408 */
00409 CREATE_CONSTANT_TABLE(EventConstants, "EventConstants")
00410 
00411 IMPLEMENT_PSEUDO_CONSTRUCTOR_WITH_PARENT(EventConstructor, "EventConstructor", DOMEventProto, EventConstants)
00412 // -------------------------------------------------------------------------
00413 
00414 
00415 const ClassInfo EventExceptionConstructor::info = { "EventExceptionConstructor", 0, &EventExceptionConstructorTable, 0 };
00416 /*
00417 @begin EventExceptionConstructorTable 1
00418   UNSPECIFIED_EVENT_TYPE_ERR    DOM::EventException::UNSPECIFIED_EVENT_TYPE_ERR DontDelete|ReadOnly
00419 @end
00420 */
00421 EventExceptionConstructor::EventExceptionConstructor(ExecState *exec)
00422   : DOMObject(exec->interpreter()->builtinObjectPrototype())
00423 {
00424 }
00425 
00426 Value EventExceptionConstructor::tryGet(ExecState *exec, const Identifier &p) const
00427 {
00428   return DOMObjectLookupGetValue<EventExceptionConstructor, DOMObject>(exec,p,&EventExceptionConstructorTable,this);
00429 }
00430 
00431 Value EventExceptionConstructor::getValueProperty(ExecState *, int token) const
00432 {
00433   // We use the token as the value to return directly
00434   return Number(token);
00435 }
00436 
00437 Value KJS::getEventExceptionConstructor(ExecState *exec)
00438 {
00439   return cacheGlobalObject<EventExceptionConstructor>(exec, "[[eventException.constructor]]");
00440 }
00441 
00442 // -------------------------------------------------------------------------
00443 
00444 const ClassInfo DOMUIEvent::info = { "UIEvent", &DOMEvent::info, &DOMUIEventTable, 0 };
00445 /*
00446 @begin DOMUIEventTable 7
00447   view      DOMUIEvent::View    DontDelete|ReadOnly
00448   detail    DOMUIEvent::Detail  DontDelete|ReadOnly
00449   keyCode   DOMUIEvent::KeyCode DontDelete|ReadOnly
00450   charCode  DOMUIEvent::CharCode    DontDelete|ReadOnly
00451   layerX    DOMUIEvent::LayerX  DontDelete|ReadOnly
00452   layerY    DOMUIEvent::LayerY  DontDelete|ReadOnly
00453   pageX     DOMUIEvent::PageX   DontDelete|ReadOnly
00454   pageY     DOMUIEvent::PageY   DontDelete|ReadOnly
00455   which     DOMUIEvent::Which   DontDelete|ReadOnly
00456 @end
00457 @begin DOMUIEventProtoTable 1
00458   initUIEvent   DOMUIEvent::InitUIEvent DontDelete|Function 5
00459 @end
00460 */
00461 DEFINE_PROTOTYPE("DOMUIEvent",DOMUIEventProto)
00462 IMPLEMENT_PROTOFUNC_DOM(DOMUIEventProtoFunc)
00463 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMUIEventProto,DOMUIEventProtoFunc,DOMEventProto)
00464 
00465 DOMUIEvent::DOMUIEvent(ExecState *exec, DOM::UIEvent ue) :
00466   DOMEvent(DOMUIEventProto::self(exec), ue) {}
00467 
00468 DOMUIEvent::DOMUIEvent(const Object &proto, DOM::UIEvent ue) :
00469   DOMEvent(proto, ue) {}
00470 
00471 DOMUIEvent::~DOMUIEvent()
00472 {
00473 }
00474 
00475 Value DOMUIEvent::tryGet(ExecState *exec, const Identifier &p) const
00476 {
00477   return DOMObjectLookupGetValue<DOMUIEvent,DOMEvent>(exec,p,&DOMUIEventTable,this);
00478 }
00479 
00480 Value DOMUIEvent::getValueProperty(ExecState *exec, int token) const
00481 {
00482   switch (token) {
00483   case View:
00484     return getDOMAbstractView(exec,static_cast<DOM::UIEvent>(event).view());
00485   case Detail:
00486     return Number(static_cast<DOM::UIEvent>(event).detail());
00487   case KeyCode:
00488     // IE-compatibility
00489     return Number(static_cast<DOM::UIEvent>(event).keyCode());
00490   case CharCode:
00491     // IE-compatibility
00492     return Number(static_cast<DOM::UIEvent>(event).charCode());
00493   case LayerX:
00494     // NS-compatibility
00495     return Number(static_cast<DOM::UIEvent>(event).layerX());
00496   case LayerY:
00497     // NS-compatibility
00498     return Number(static_cast<DOM::UIEvent>(event).layerY());
00499   case PageX:
00500     // NS-compatibility
00501     return Number(static_cast<DOM::UIEvent>(event).pageX());
00502   case PageY:
00503     // NS-compatibility
00504     return Number(static_cast<DOM::UIEvent>(event).pageY());
00505   case Which:
00506     // NS-compatibility
00507     return Number(static_cast<DOM::UIEvent>(event).which());
00508   default:
00509     kdDebug(6070) << "WARNING: Unhandled token in DOMUIEvent::getValueProperty : " << token << endl;
00510     return Undefined();
00511   }
00512 }
00513 
00514 Value DOMUIEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00515 {
00516   KJS_CHECK_THIS( KJS::DOMUIEvent, thisObj );
00517   DOM::UIEvent uiEvent = static_cast<DOMUIEvent *>(thisObj.imp())->toUIEvent();
00518   switch (id) {
00519     case DOMUIEvent::InitUIEvent: {
00520       DOM::AbstractView v = toAbstractView(args[3]);
00521       static_cast<DOM::UIEvent>(uiEvent).initUIEvent(args[0].toString(exec).string(),
00522                                                      args[1].toBoolean(exec),
00523                                                      args[2].toBoolean(exec),
00524                                                      v,
00525                                                      args[4].toInteger(exec));
00526       }
00527       return Undefined();
00528   }
00529   return Undefined();
00530 }
00531 
00532 // -------------------------------------------------------------------------
00533 
00534 const ClassInfo DOMMouseEvent::info = { "MouseEvent", &DOMUIEvent::info, &DOMMouseEventTable, 0 };
00535 
00536 /*
00537 @begin DOMMouseEventTable 2
00538   screenX   DOMMouseEvent::ScreenX  DontDelete|ReadOnly
00539   screenY   DOMMouseEvent::ScreenY  DontDelete|ReadOnly
00540   clientX   DOMMouseEvent::ClientX  DontDelete|ReadOnly
00541   x     DOMMouseEvent::X    DontDelete|ReadOnly
00542   clientY   DOMMouseEvent::ClientY  DontDelete|ReadOnly
00543   y     DOMMouseEvent::Y    DontDelete|ReadOnly
00544   offsetX   DOMMouseEvent::OffsetX  DontDelete|ReadOnly
00545   offsetY   DOMMouseEvent::OffsetY  DontDelete|ReadOnly
00546   ctrlKey   DOMMouseEvent::CtrlKey  DontDelete|ReadOnly
00547   shiftKey  DOMMouseEvent::ShiftKey DontDelete|ReadOnly
00548   altKey    DOMMouseEvent::AltKey   DontDelete|ReadOnly
00549   metaKey   DOMMouseEvent::MetaKey  DontDelete|ReadOnly
00550   button    DOMMouseEvent::Button   DontDelete|ReadOnly
00551   relatedTarget DOMMouseEvent::RelatedTarget DontDelete|ReadOnly
00552   fromElement   DOMMouseEvent::FromElement DontDelete|ReadOnly
00553   toElement DOMMouseEvent::ToElement    DontDelete|ReadOnly
00554 @end
00555 @begin DOMMouseEventProtoTable 1
00556   initMouseEvent    DOMMouseEvent::InitMouseEvent   DontDelete|Function 15
00557 @end
00558 */
00559 DEFINE_PROTOTYPE("DOMMouseEvent",DOMMouseEventProto)
00560 IMPLEMENT_PROTOFUNC_DOM(DOMMouseEventProtoFunc)
00561 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMMouseEventProto,DOMMouseEventProtoFunc,DOMUIEventProto)
00562 
00563 DOMMouseEvent::DOMMouseEvent(ExecState *exec, DOM::MouseEvent me) :
00564   DOMUIEvent(DOMMouseEventProto::self(exec), me) {}
00565 
00566 DOMMouseEvent::~DOMMouseEvent()
00567 {
00568 }
00569 
00570 Value DOMMouseEvent::tryGet(ExecState *exec, const Identifier &p) const
00571 {
00572 #ifdef KJS_VERBOSE
00573   kdDebug(6070) << "DOMMouseEvent::tryGet " << p.qstring() << endl;
00574 #endif
00575   return DOMObjectLookupGetValue<DOMMouseEvent,DOMUIEvent>(exec,p,&DOMMouseEventTable,this);
00576 }
00577 
00578 Value DOMMouseEvent::getValueProperty(ExecState *exec, int token) const
00579 {
00580   switch (token) {
00581   case ScreenX:
00582     return Number(static_cast<DOM::MouseEvent>(event).screenX());
00583   case ScreenY:
00584     return Number(static_cast<DOM::MouseEvent>(event).screenY());
00585   case ClientX:
00586   case X:
00587     return Number(static_cast<DOM::MouseEvent>(event).clientX());
00588   case ClientY:
00589   case Y:
00590     return Number(static_cast<DOM::MouseEvent>(event).clientY());
00591   case OffsetX:
00592   case OffsetY: // MSIE extension
00593   {
00594     DOM::Node node = event.target();
00595     khtml::RenderObject *rend = 0;
00596     if (node.handle()) {
00597         node.handle()->getDocument()->updateRendering();
00598         rend = node.handle()->renderer();
00599     }
00600     int x = static_cast<DOM::MouseEvent>(event).clientX();
00601     int y = static_cast<DOM::MouseEvent>(event).clientY();
00602     if ( rend ) {
00603       int xPos, yPos;
00604       if ( rend->absolutePosition( xPos, yPos ) ) {
00605         kdDebug() << "DOMMouseEvent::getValueProperty rend=" << rend << "  xPos=" << xPos << "  yPos=" << yPos << endl;
00606         x -= xPos;
00607         y -= yPos;
00608       }
00609       if ( rend->canvas() ) {
00610         int cYPos, cXPos;
00611         rend->canvas()->absolutePosition( cXPos,  cYPos,  true );
00612         x += cXPos;
00613         y += cYPos;
00614       }
00615     }
00616     return Number( token == OffsetX ? x : y );
00617   }
00618   case CtrlKey:
00619     return Boolean(static_cast<DOM::MouseEvent>(event).ctrlKey());
00620   case ShiftKey:
00621     return Boolean(static_cast<DOM::MouseEvent>(event).shiftKey());
00622   case AltKey:
00623     return Boolean(static_cast<DOM::MouseEvent>(event).altKey());
00624   case MetaKey:
00625     return Boolean(static_cast<DOM::MouseEvent>(event).metaKey());
00626   case Button:
00627   {
00628     if ( exec->interpreter()->compatMode() == Interpreter::NetscapeCompat ) {
00629         return Number(static_cast<DOM::MouseEvent>(event).button());
00630     }
00631     // Tricky. The DOM (and khtml) use 0 for LMB, 1 for MMB and 2 for RMB
00632     // but MSIE uses 1=LMB, 2=RMB, 4=MMB, as a bitfield
00633     int domButton = static_cast<DOM::MouseEvent>(event).button();
00634     int button = domButton==0 ? 1 : domButton==1 ? 4 : domButton==2 ? 2 : 0;
00635     return Number( (unsigned int)button );
00636   }
00637   case ToElement:
00638     // MSIE extension - "the object toward which the user is moving the mouse pointer"
00639     if (event.handle()->id() == DOM::EventImpl::MOUSEOUT_EVENT)
00640       return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).relatedTarget());
00641     return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).target());
00642   case FromElement:
00643     // MSIE extension - "object from which activation
00644     // or the mouse pointer is exiting during the event" (huh?)
00645     if (event.handle()->id() == DOM::EventImpl::MOUSEOUT_EVENT)
00646       return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).target());
00647     /* fall through */
00648   case RelatedTarget:
00649     return getDOMNode(exec,static_cast<DOM::MouseEvent>(event).relatedTarget());
00650   default:
00651     kdDebug(6070) << "WARNING: Unhandled token in DOMMouseEvent::getValueProperty : " << token << endl;
00652     return Value();
00653   }
00654 }
00655 
00656 Value DOMMouseEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00657 {
00658   KJS_CHECK_THIS( KJS::DOMMouseEvent, thisObj );
00659   DOM::MouseEvent mouseEvent = static_cast<DOMMouseEvent *>(thisObj.imp())->toMouseEvent();
00660   switch (id) {
00661     case DOMMouseEvent::InitMouseEvent:
00662       mouseEvent.initMouseEvent(args[0].toString(exec).string(), // typeArg
00663                                 args[1].toBoolean(exec), // canBubbleArg
00664                                 args[2].toBoolean(exec), // cancelableArg
00665                                 toAbstractView(args[3]), // viewArg
00666                                 args[4].toInteger(exec), // detailArg
00667                                 args[5].toInteger(exec), // screenXArg
00668                                 args[6].toInteger(exec), // screenYArg
00669                                 args[7].toInteger(exec), // clientXArg
00670                                 args[8].toInteger(exec), // clientYArg
00671                                 args[9].toBoolean(exec), // ctrlKeyArg
00672                                 args[10].toBoolean(exec), // altKeyArg
00673                                 args[11].toBoolean(exec), // shiftKeyArg
00674                                 args[12].toBoolean(exec), // metaKeyArg
00675                                 args[13].toInteger(exec), // buttonArg
00676                                 toNode(args[14])); // relatedTargetArg
00677       return Undefined();
00678   }
00679   return Undefined();
00680 }
00681 
00682 // -------------------------------------------------------------------------
00683 
00684 const ClassInfo DOMKeyEventBase::info = { "KeyEventBase", &DOMUIEvent::info, &DOMKeyEventBaseTable, 0 };
00685 
00686 /*
00687 @begin DOMKeyEventBaseTable 5
00688   keyVal     DOMKeyEventBase::Key         DontDelete|ReadOnly
00689   virtKeyVal     DOMKeyEventBase::VirtKey     DontDelete|ReadOnly
00690   ctrlKey        DOMKeyEventBase::CtrlKey     DontDelete|ReadOnly
00691   altKey         DOMKeyEventBase::AltKey      DontDelete|ReadOnly
00692   shiftKey       DOMKeyEventBase::ShiftKey    DontDelete|ReadOnly
00693   altKey         DOMKeyEventBase::AltKey      DontDelete|ReadOnly
00694 @end
00695 */
00696 
00697 DOMKeyEventBase::DOMKeyEventBase(const Object &proto, DOM::TextEvent ke) :
00698   DOMUIEvent(proto, ke) {}
00699 
00700 DOMKeyEventBase::~DOMKeyEventBase()
00701 {}
00702 
00703 Value DOMKeyEventBase::tryGet(ExecState *exec,const Identifier &p) const
00704 {
00705 #ifdef KJS_VERBOSE
00706   kdDebug(6070) << "DOMKeyEventBase::tryGet " << p.qstring() << endl;
00707 #endif
00708   return DOMObjectLookupGetValue<DOMKeyEventBase,DOMUIEvent>(exec,p,&DOMKeyEventBaseTable,this);
00709 }
00710 
00711 Value DOMKeyEventBase::getValueProperty(ExecState *, int token) const
00712 {
00713   DOM::KeyEventBaseImpl* tevent = impl();
00714   switch (token) {
00715   case Key:
00716     return Number(tevent->keyVal());
00717   case VirtKey:
00718     return Number(tevent->virtKeyVal());
00719   // these modifier attributes actually belong into a KeyboardEvent interface,
00720   // but we want them on "keypress" as well.
00721   case CtrlKey:
00722     return Boolean(tevent->ctrlKey());
00723   case ShiftKey:
00724     return Boolean(tevent->shiftKey());
00725   case AltKey:
00726     return Boolean(tevent->altKey());
00727   case MetaKey:
00728     return Boolean(tevent->metaKey());
00729   default:
00730     kdDebug(6070) << "WARNING: Unhandled token in DOMTextEvent::getValueProperty : " << token << endl;
00731     return KJS::Undefined();
00732   }
00733 }
00734 
00735 // -------------------------------------------------------------------------
00736 const ClassInfo DOMTextEvent::info = { "TextEvent", &DOMKeyEventBase::info, &DOMTextEventTable, 0 };
00737 
00738 /*
00739 @begin DOMTextEventTable 1
00740   data           DOMTextEvent::Data          DontDelete|ReadOnly
00741 @end
00742 @begin DOMTextEventProtoTable 1
00743   initTextEvent DOMTextEvent::InitTextEvent DontDelete|Function 5
00744   # Missing: initTextEventNS
00745 @end
00746 */
00747 DEFINE_PROTOTYPE("DOMTextEvent",DOMTextEventProto)
00748 IMPLEMENT_PROTOFUNC_DOM(DOMTextEventProtoFunc)
00749 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMTextEventProto,DOMTextEventProtoFunc,DOMUIEventProto) //Note: no proto in KeyBase
00750 
00751 DOMTextEvent::DOMTextEvent(ExecState *exec, DOM::TextEvent ke) :
00752   DOMKeyEventBase(DOMTextEventProto::self(exec), ke) {}
00753 
00754 DOMTextEvent::~DOMTextEvent()
00755 {
00756 }
00757 
00758 Value DOMTextEvent::tryGet(ExecState *exec, const Identifier &p) const
00759 {
00760 #ifdef KJS_VERBOSE
00761   kdDebug(6070) << "DOMTextEvent::tryGet " << p.qstring() << endl;
00762 #endif
00763   return DOMObjectLookupGetValue<DOMTextEvent,DOMKeyEventBase>(exec,p,&DOMTextEventTable,this);
00764 }
00765 
00766 Value DOMTextEvent::getValueProperty(ExecState *, int token) const
00767 {
00768   DOM::TextEventImpl* tevent = impl();
00769   switch (token) {
00770   case Data:
00771     return String(tevent->data());
00772   default:
00773     kdDebug(6070) << "WARNING: Unhandled token in DOMTextEvent::getValueProperty : " << token << endl;
00774     return KJS::Undefined();
00775   }
00776 }
00777 
00778 Value DOMTextEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00779 {
00780   KJS_CHECK_THIS( KJS::DOMTextEvent, thisObj );
00781   DOM::TextEventImpl* keyEvent = static_cast<DOMTextEvent *>(thisObj.imp())->impl();
00782   switch (id) {
00783     case DOMTextEvent::InitTextEvent:
00784       keyEvent->initTextEvent(args[0].toString(exec).string(), // typeArg
00785                             args[1].toBoolean(exec), // canBubbleArg
00786                             args[2].toBoolean(exec), // cancelableArg
00787                             toAbstractView(args[3]), // viewArg
00788                             args[4].toString(exec).string()); // dataArg
00789 
00790       return Undefined();
00791   }
00792   return Undefined();
00793 }
00794 // -------------------------------------------------------------------------
00795 const ClassInfo DOMKeyboardEvent::info = { "KeyboardEvent", &DOMKeyEventBase::info, &DOMKeyboardEventTable, 0 };
00796 
00797 /*
00798 @begin DOMKeyboardEventTable 2
00799   keyIdentifier  DOMKeyboardEvent::KeyIdentifier  DontDelete|ReadOnly
00800   keyLocation    DOMKeyboardEvent::KeyLocation    DontDelete|ReadOnly
00801 @end
00802 @begin DOMKeyboardEventProtoTable 2
00803   initKeyboardEvent DOMKeyboardEvent::InitKeyboardEvent DontDelete|Function 7
00804   getModifierState      DOMKeyboardEvent::GetModifierState      DontDelete|Function 1
00805 @end
00806 */
00807 DEFINE_PROTOTYPE("DOMKeyboardEvent",DOMKeyboardEventProto)
00808 IMPLEMENT_PROTOFUNC_DOM(DOMKeyboardEventProtoFunc)
00809 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMKeyboardEventProto,DOMKeyboardEventProtoFunc,DOMUIEventProto) //Note: no proto in KeyBase
00810 
00811 DOMKeyboardEvent::DOMKeyboardEvent(ExecState *exec, DOM::TextEvent ke) :
00812   DOMKeyEventBase(DOMKeyboardEventProto::self(exec), ke) {}
00813 
00814 DOMKeyboardEvent::~DOMKeyboardEvent()
00815 {
00816 }
00817 
00818 Value DOMKeyboardEvent::tryGet(ExecState *exec, const Identifier &p) const
00819 {
00820 #ifdef KJS_VERBOSE
00821   kdDebug(6070) << "DOMKeyboardEvent::tryGet " << p.qstring() << endl;
00822 #endif
00823   return DOMObjectLookupGetValue<DOMKeyboardEvent,DOMKeyEventBase>(exec,p,&DOMKeyboardEventTable,this);
00824 }
00825 
00826 Value DOMKeyboardEvent::getValueProperty(ExecState *, int token) const
00827 {
00828   DOM::KeyboardEventImpl* tevent = impl();
00829   switch (token) {
00830   case KeyIdentifier:
00831     return String(tevent->keyIdentifier());
00832   case KeyLocation:
00833     return Number(tevent->keyLocation());
00834   default:
00835     kdDebug(6070) << "WARNING: Unhandled token in DOMKeyboardEvent::getValueProperty : " << token << endl;
00836     return KJS::Undefined();
00837   }
00838 }
00839 
00840 Value DOMKeyboardEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00841 {
00842   KJS_CHECK_THIS( KJS::DOMKeyboardEvent, thisObj );
00843   DOM::KeyboardEventImpl* keyEvent = static_cast<DOMKeyboardEvent *>(thisObj.imp())->impl();
00844   switch (id) {
00845     case DOMKeyboardEvent::InitKeyboardEvent:
00846       keyEvent->initKeyboardEvent(args[0].toString(exec).string(), // typeArg
00847                             args[1].toBoolean(exec), // canBubbleArg
00848                             args[2].toBoolean(exec), // cancelableArg
00849                             toAbstractView(args[3]), // viewArg
00850                             args[4].toString(exec).string(), // keyIdentifierArg
00851                             args[5].toInteger(exec),         // keyLocationArg
00852                             args[6].toString(exec).string()); //modifiersList
00853       break;
00854     case DOMKeyboardEvent::GetModifierState:
00855       return Boolean(keyEvent->getModifierState(args[0].toString(exec).string()));
00856   }
00857   return Undefined();
00858 }
00859 
00860 // -------------------------------------------------------------------------
00861 const ClassInfo KeyboardEventConstructor::info = { "KeyboardEventConstructor", 0, &KeyboardEventConstructorTable, 0 };
00862 /*
00863 @begin KeyboardEventConstructorTable 4
00864   DOM_KEY_LOCATION_STANDARD  DOM::KeyboardEventImpl::DOM_KEY_LOCATION_STANDARD DontDelete|ReadOnly
00865   DOM_KEY_LOCATION_LEFT      DOM::KeyboardEventImpl::DOM_KEY_LOCATION_LEFT     DontDelete|ReadOnly
00866   DOM_KEY_LOCATION_RIGHT     DOM::KeyboardEventImpl::DOM_KEY_LOCATION_RIGHT    DontDelete|ReadOnly
00867   DOM_KEY_LOCATION_NUMPAD    DOM::KeyboardEventImpl::DOM_KEY_LOCATION_NUMPAD   DontDelete|ReadOnly
00868 @end
00869 */
00870 KeyboardEventConstructor::KeyboardEventConstructor(ExecState* exec)
00871   : DOMObject(exec->interpreter()->builtinObjectPrototype())
00872 {}
00873 
00874 Value KeyboardEventConstructor::tryGet(ExecState *exec, const Identifier &p) const
00875 {
00876   return DOMObjectLookupGetValue<KeyboardEventConstructor,DOMObject>(exec,p,&KeyboardEventConstructorTable,this);
00877 }
00878 
00879 Value KeyboardEventConstructor::getValueProperty(ExecState *, int token) const
00880 {
00881   // We use the token as the value to return directly
00882   return Number(token);
00883 }
00884 
00885 Value KJS::getKeyboardEventConstructor(ExecState *exec)
00886 {
00887   return cacheGlobalObject<KeyboardEventConstructor>(exec, "[[keyboardEvent.constructor]]");
00888 }
00889 
00890 
00891 // -------------------------------------------------------------------------
00892 const ClassInfo MutationEventConstructor::info = { "MutationEventConstructor", 0, &MutationEventConstructorTable, 0 };
00893 /*
00894 @begin MutationEventConstructorTable 3
00895   MODIFICATION  DOM::MutationEvent::MODIFICATION    DontDelete|ReadOnly
00896   ADDITION  DOM::MutationEvent::ADDITION        DontDelete|ReadOnly
00897   REMOVAL   DOM::MutationEvent::REMOVAL     DontDelete|ReadOnly
00898 @end
00899 */
00900 MutationEventConstructor::MutationEventConstructor(ExecState* exec)
00901   : DOMObject(exec->interpreter()->builtinObjectPrototype())
00902 {
00903 }
00904 
00905 Value MutationEventConstructor::tryGet(ExecState *exec, const Identifier &p) const
00906 {
00907   return DOMObjectLookupGetValue<MutationEventConstructor,DOMObject>(exec,p,&MutationEventConstructorTable,this);
00908 }
00909 
00910 Value MutationEventConstructor::getValueProperty(ExecState *, int token) const
00911 {
00912   // We use the token as the value to return directly
00913   return Number(token);
00914 }
00915 
00916 Value KJS::getMutationEventConstructor(ExecState *exec)
00917 {
00918   return cacheGlobalObject<MutationEventConstructor>(exec, "[[mutationEvent.constructor]]");
00919 }
00920 
00921 // -------------------------------------------------------------------------
00922 
00923 const ClassInfo DOMMutationEvent::info = { "MutationEvent", &DOMEvent::info, &DOMMutationEventTable, 0 };
00924 /*
00925 @begin DOMMutationEventTable 5
00926   relatedNode   DOMMutationEvent::RelatedNode   DontDelete|ReadOnly
00927   prevValue DOMMutationEvent::PrevValue DontDelete|ReadOnly
00928   newValue  DOMMutationEvent::NewValue  DontDelete|ReadOnly
00929   attrName  DOMMutationEvent::AttrName  DontDelete|ReadOnly
00930   attrChange    DOMMutationEvent::AttrChange    DontDelete|ReadOnly
00931 @end
00932 @begin DOMMutationEventProtoTable 1
00933   initMutationEvent DOMMutationEvent::InitMutationEvent DontDelete|Function 8
00934 @end
00935 */
00936 DEFINE_PROTOTYPE("DOMMutationEvent",DOMMutationEventProto)
00937 IMPLEMENT_PROTOFUNC_DOM(DOMMutationEventProtoFunc)
00938 IMPLEMENT_PROTOTYPE_WITH_PARENT(DOMMutationEventProto,DOMMutationEventProtoFunc,DOMEventProto)
00939 
00940 DOMMutationEvent::DOMMutationEvent(ExecState *exec, DOM::MutationEvent me) :
00941   DOMEvent(DOMMutationEventProto::self(exec), me) {}
00942 
00943 DOMMutationEvent::~DOMMutationEvent()
00944 {
00945 }
00946 
00947 Value DOMMutationEvent::tryGet(ExecState *exec, const Identifier &p) const
00948 {
00949   return DOMObjectLookupGetValue<DOMMutationEvent,DOMEvent>(exec,p,&DOMMutationEventTable,this);
00950 }
00951 
00952 Value DOMMutationEvent::getValueProperty(ExecState *exec, int token) const
00953 {
00954   switch (token) {
00955   case RelatedNode:
00956     return getDOMNode(exec,static_cast<DOM::MutationEvent>(event).relatedNode());
00957   case PrevValue:
00958     return String(static_cast<DOM::MutationEvent>(event).prevValue());
00959   case NewValue:
00960     return String(static_cast<DOM::MutationEvent>(event).newValue());
00961   case AttrName:
00962     return String(static_cast<DOM::MutationEvent>(event).attrName());
00963   case AttrChange:
00964     return Number((unsigned int)static_cast<DOM::MutationEvent>(event).attrChange());
00965   default:
00966     kdDebug(6070) << "WARNING: Unhandled token in DOMMutationEvent::getValueProperty : " << token << endl;
00967     return Value();
00968   }
00969 }
00970 
00971 Value DOMMutationEventProtoFunc::tryCall(ExecState *exec, Object &thisObj, const List &args)
00972 {
00973   KJS_CHECK_THIS( KJS::DOMMutationEvent, thisObj );
00974   DOM::MutationEvent mutationEvent = static_cast<DOMMutationEvent *>(thisObj.imp())->toMutationEvent();
00975   switch (id) {
00976     case DOMMutationEvent::InitMutationEvent:
00977       mutationEvent.initMutationEvent(args[0].toString(exec).string(), // typeArg,
00978                                       args[1].toBoolean(exec), // canBubbleArg
00979                                       args[2].toBoolean(exec), // cancelableArg
00980                                       toNode(args[3]), // relatedNodeArg
00981                                       args[4].toString(exec).string(), // prevValueArg
00982                                       args[5].toString(exec).string(), // newValueArg
00983                                       args[6].toString(exec).string(), // attrNameArg
00984                                       args[7].toInteger(exec)); // attrChangeArg
00985       return Undefined();
00986   }
00987   return Undefined();
00988 }
KDE Home | KDE Accessibility Home | Description of Access Keys