⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kjs_events.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// -*- 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 Lesser 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
#include "khtml_part.h"
#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 "misc/loader.h"

#include <kdebug.h>

using namespace KJS;

using DOM::KeyboardEvent;
using DOM::EventImpl;
using DOM::NodeImpl;

// -------------------------------------------------------------------------

JSAbstractEventListener::JSAbstractEventListener(bool _html)
  : html(_html)
{
}

JSAbstractEventListener::~JSAbstractEventListener()
{
}

void JSAbstractEventListener::handleEvent(DOM::Event &evt, bool isWindowEvent)
{
#ifdef KJS_DEBUGGER
  if (KJSDebugWin::instance() && KJSDebugWin::instance()->inSession())
    return;
#endif
  Object listener = listenerObj();
  Object win = windowObj();

  KHTMLPart *part = static_cast<Window*>(win.imp())->part();
  KJSProxy *proxy = 0;
  if (part)
      proxy = KJSProxy::proxy( part );

  if (proxy && listener.implementsCall()) {
    ref();

    KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
    ExecState *exec = interpreter->globalExec();

    List args;
    args.append(getDOMEvent(exec,evt));

    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 );
#ifdef NOKIA_CHANGES
	interpreter->resetStatementCount();
#endif

    Object thisObj;
    if (isWindowEvent) {
        thisObj = win;
    } else {
        KJS::Interpreter::lock();
        thisObj = Object::dynamicCast(getDOMNode(exec,evt.currentTarget()));
        KJS::Interpreter::unlock();
    }

    KJS::Interpreter::lock();
    Value retval = listener.call(exec, thisObj, args);
    KJS::Interpreter::unlock();

    window->setCurrentEvent( 0 );
    interpreter->setCurrentEvent( 0 );
#if APPLE_CHANGES
    if ( exec->hadException() ) {
        KJS::Interpreter::lock();
        char *message = exec->exception().toObject(exec).get(exec, messagePropertyName).toString(exec).ascii();
        int lineNumber =  exec->exception().toObject(exec).get(exec, "line").toInt32(exec);
        UString sourceURL = exec->exception().toObject(exec).get(exec, "sourceURL").toString(exec);
        KJS::Interpreter::unlock();
        if (Interpreter::shouldPrintExceptions()) {
	    printf("(event handler):%s\n", message);
	}
        KWQ(part)->addMessageToConsole(message, lineNumber, sourceURL.qstring());
        exec->clearException();
    }
#else
    if ( exec->hadException() )
        exec->clearException();
#endif

    else if (html)
    {
        QVariant ret = ValueToVariant(exec, retval);
        if (ret.type() == QVariant::Bool && ret.toBool() == false)
            evt.preventDefault();
    }
    DOM::DocumentImpl::updateDocumentsRendering();
    deref();
  }
}

DOM::DOMString JSAbstractEventListener::eventListenerType()
{
    if (html)
	return "_khtml_HTMLEventListener";
    else
	return "_khtml_JSEventListener";
}

// -------------------------------------------------------------------------

JSUnprotectedEventListener::JSUnprotectedEventListener(Object _listener, const Object &_win, bool _html)
  : JSAbstractEventListener(_html)
  , listener(_listener)
  , win(_win)
{
    if (_listener.imp()) {
      static_cast<Window*>(win.imp())->jsUnprotectedEventListeners.insert(_listener.imp(), this);
    }
}

JSUnprotectedEventListener::~JSUnprotectedEventListener()
{
    if (listener.imp()) {
      static_cast<Window*>(win.imp())->jsUnprotectedEventListeners.remove(listener.imp());
    }
}

Object JSUnprotectedEventListener::listenerObj() const
{ 
    return listener; 
}

Object JSUnprotectedEventListener::windowObj() const
{
    return win;
}

void JSUnprotectedEventListener::mark()
{
  ObjectImp *listenerImp = listener.imp();
  if (listenerImp && !listenerImp->marked())
    listenerImp->mark();
}

// -------------------------------------------------------------------------

JSEventListener::JSEventListener(Object _listener, const Object &_win, bool _html)
  : JSAbstractEventListener(_html)
  , listener(_listener)
  , win(_win)
{
    //fprintf(stderr,"JSEventListener::JSEventListener this=%p listener=%p\n",this,listener.imp());
    if (_listener.imp()) {
      static_cast<Window*>(win.imp())->jsEventListeners.insert(_listener.imp(), this);
    }
}

JSEventListener::~JSEventListener()
{
    if (listener.imp()) {
      static_cast<Window*>(win.imp())->jsEventListeners.remove(listener.imp());
    }
    //fprintf(stderr,"JSEventListener::~JSEventListener this=%p listener=%p\n",this,listener.imp());
}

Object JSEventListener::listenerObj() const
{ 
    return listener; 
}

Object JSEventListener::windowObj() const
{
    return win;
}

// -------------------------------------------------------------------------

JSLazyEventListener::JSLazyEventListener(QString _code, const Object &_win, NodeImpl *_originalNode, int lineno)
  : JSEventListener(Object(), _win, true),
    code(_code),
    parsed(false)
{
    lineNumber = lineno;

    // 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;
}

void JSLazyEventListener::handleEvent(DOM::Event &evt, bool isWindowEvent)
{
  parseCode();
  if (!listener.isNull()) { 
    JSEventListener::handleEvent(evt, isWindowEvent);
  }
}


Object JSLazyEventListener::listenerObj() const
{
  parseCode();
  return listener;
}

void JSLazyEventListener::parseCode() const
{
  if (!parsed) {
    KHTMLPart *part = static_cast<Window*>(win.imp())->part();
    KJSProxy *proxy = 0L;
    if (part)
      proxy = KJSProxy::proxy( part );

    if (proxy) {
      KJS::ScriptInterpreter *interpreter = static_cast<KJS::ScriptInterpreter *>(proxy->interpreter());
      ExecState *exec = interpreter->globalExec();

      KJS::Interpreter::lock();
      //KJS::Constructor constr(KJS::Global::current().get("Function").imp());
      KJS::Object constr = interpreter->builtinFunction();
      KJS::List args;

      static ProtectedValue eventString = KJS::String("event");
      UString sourceURL(part->m_url.url());
      args.append(eventString);
      args.append(KJS::String(code));
      listener = constr.construct(exec, args, sourceURL, lineNumber); // ### is globalExec ok ?

      KJS::Interpreter::unlock();

      if (exec->hadException()) {
	exec->clearException();

	// failed to parse, so let's just make this listener a no-op
	listener = Object();
      } else 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();
        
        KJS::Interpreter::lock();
        Object thisObj = Object::dynamicCast(getDOMNode(exec, originalNode));
        KJS::Interpreter::unlock();
        
        if (!thisObj.isNull()) {
          KJS::Interpreter::lock();
          static_cast<DOMNode*>(thisObj.imp())->pushEventHandlerScope(exec, scope);
          KJS::Interpreter::unlock();
          
          listener.setScope(scope);
        }
      }
    }

    // no more need to keep the unparsed code around
    code = QString();
    
    if (!listener.isNull()) {
      static_cast<Window*>(win.imp())->jsEventListeners.insert(listener.imp(), 
							       (KJS::JSEventListener *)(this));
    }
    
    parsed = true;
  }
}

Value KJS::getNodeEventListener(DOM::Node n, int eventId)
{
    DOM::EventListener *listener = n.handle()->getHTMLEventListener(eventId);
    JSEventListener *jsListener = static_cast<JSEventListener*>(listener);
    if ( jsListener && jsListener->listenerObjImp() )
	return jsListener->listenerObj();
    else
	return Null();
}



// -------------------------------------------------------------------------

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
*/

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 12
  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
  dataTransfer	DOMMouseEvent::DataTransfer DontDelete|ReadOnly
  clipboardData  DOMEvent::ClipboardData  DontDelete|ReadOnly
@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(DOMEventProtoFunc)
IMPLEMENT_PROTOTYPE(DOMEventProto, DOMEventProtoFunc)

DOMEvent::DOMEvent(ExecState *exec, DOM::Event e)
  : DOMObject(DOMEventProto::self(exec)), event(e), clipboard(0) { }

DOMEvent::~DOMEvent()
{
  ScriptInterpreter::forgetDOMObject(event.handle());
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -