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

📄 kjs_events.cpp

📁 最新Nokia手机浏览器全套源代码完美版。
💻 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::DocumentImpl;
using DOM::DOMString;
using DOM::EventImpl;
using DOM::KeyboardEvent;
using DOM::MouseRelatedEventImpl;
using DOM::NodeImpl;

using khtml::RenderObject;

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

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)
    return;

  if (listener.implementsCall()) {
    InterpreterLock lock;

    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
        thisObj = Object::dynamicCast(getDOMNode(exec,evt.currentTarget()));

    Value retval = listener.call(exec, thisObj, args);

    window->setCurrentEvent( 0 );
    interpreter->setCurrentEvent( 0 );

    if (exec->hadException()) {
        char *message = exec->exception().toObject(exec).get(exec, messagePropertyName).toString(exec).ascii();
        int lineNumber =  exec->exception().toObject(exec).get(exec, "line").toInt32(exec);
        QString sourceURL;
        {
          // put this in a block to make sure UString is deallocated inside the lock
          UString uSourceURL = exec->exception().toObject(exec).get(exec, "sourceURL").toString(exec);
          sourceURL = uSourceURL.qstring();
        }
        if (Interpreter::shouldPrintExceptions()) {
	    printf("(event handler):%s\n", message);
	}
        KWQ(part)->addMessageToConsole(message, lineNumber, sourceURL);

        if (Interpreter::shouldPrintExceptions())
            printf("(event handler):%s\n", message);
        exec->clearException();
      } else {
            if (!retval.isA(UndefinedType) && !retval.isA(NullType) && evt.handle()->storesResultAsString())
                evt.handle()->storeResult(retval.toString(exec).string());
            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()) {
        if (!win.isNull()) {
            static_cast<Window*>(win.imp())->jsUnprotectedEventListeners.remove(listener.imp());
        }
    }
}

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

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

void JSUnprotectedEventListener::clearWindowObj()
{
    win = Object();
}


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()) {
        if (!win.isNull()) {
          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;
}

void JSEventListener::clearWindowObj()
{
    win = Object();
}

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

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();

      InterpreterLock 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 ?

      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()) {
          static_cast<DOMNode*>(thisObj.imp())->pushEventHandlerScope(exec, scope);
          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);
}

namespace KJS {

Value 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	DOMEvent::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)
  : event(e), clipboard(0)
{
  setPrototype(DOMEventProto::self(exec));
}

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

// pass marks through to JS objects we hold during garbage collection
void DOMMouseEvent::mark()
{
    ObjectImp::mark();
    if (clipboard && !clipboard->marked())
        clipboard->mark();
}

Value DOMEvent::tryGet(ExecState *exec, const Identifier &p) const
{
#ifdef KJS_VERBOSE

⌨️ 快捷键说明

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