📄 kjs_events.cpp
字号:
// -*- 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 KJS;using namespace DOM;// -------------------------------------------------------------------------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 EventConstructor::info = { "EventConstructor", 0, &EventConstructorTable, 0 };/*@begin EventConstructorTable 3 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*/EventConstructor::EventConstructor(ExecState *exec) : DOMObject(exec->interpreter()->builtinObjectPrototype()){}Value EventConstructor::tryGet(ExecState *exec, const Identifier &p) const{ return DOMObjectLookupGetValue<EventConstructor, DOMObject>(exec,p,&EventConstructorTable,this);}Value EventConstructor::getValueProperty(ExecState *, int token) const{ // We use the token as the value to return directly return Number(token);}Value KJS::getEventConstructor(ExecState *exec){ return cacheGlobalObject<EventConstructor>(exec, "[[event.constructor]]");}// -------------------------------------------------------------------------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*/DEFINE_PROTOTYPE("DOMEvent", DOMEventProto)IMPLEMENT_PROTOFUNC_DOM(DOMEventProtoFunc)IMPLEMENT_PROTOTYPE(DOMEventProto, DOMEventProtoFunc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -