File indexing completed on 2024-04-28 15:24:45

0001 /**
0002  * This file is part of the DOM implementation for KDE.
0003  *
0004  * Copyright (C) 2001 Peter Kelly (pmk@post.com)
0005  *           (C) 2001 Tobias Anton (anton@stud.fbi.fh-darmstadt.de)
0006  *           (C) 2003 Apple Computer, Inc.
0007  *           (C) 2006, 2010 Maksim Orlovich (maksim@kde.org)
0008  *
0009  * This library is free software; you can redistribute it and/or
0010  * modify it under the terms of the GNU Library General Public
0011  * License as published by the Free Software Foundation; either
0012  * version 2 of the License, or (at your option) any later version.
0013  *
0014  * This library is distributed in the hope that it will be useful,
0015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017  * Library General Public License for more details.
0018  *
0019  * You should have received a copy of the GNU Library General Public License
0020  * along with this library; see the file COPYING.LIB.  If not, write to
0021  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0022  * Boston, MA 02110-1301, USA.
0023 
0024  */
0025 
0026 #include "dom2_eventsimpl.h"
0027 
0028 #include <dom/dom2_views.h>
0029 
0030 #include "dom_stringimpl.h"
0031 #include "dom_nodeimpl.h"
0032 #include "dom_docimpl.h"
0033 #include "misc/translator.h"
0034 #include <rendering/render_layer.h>
0035 #include <khtmlview.h>
0036 #include <khtml_part.h>
0037 
0038 #include <QActionEvent>
0039 #include "khtml_debug.h"
0040 
0041 using namespace DOM;
0042 using namespace khtml;
0043 
0044 void EventTargetImpl::handleLocalEvents(EventImpl *evt, bool useCapture)
0045 {
0046     if (!m_regdListeners.listeners) {
0047         return;
0048     }
0049 
0050     Event ev = evt;
0051     // removeEventListener (e.g. called from a JS event listener) might
0052     // invalidate the item after the current iterator (which "it" is pointing to).
0053     // So we make a copy of the list.
0054     QList<RegisteredEventListener> listeners = *m_regdListeners.listeners;
0055     QList<RegisteredEventListener>::iterator it;
0056     for (it = listeners.begin(); it != listeners.end(); ++it) {
0057         //Check whether this got removed... TODO: use Java-style iterators
0058         if (!m_regdListeners.stillContainsListener(*it)) {
0059             continue;
0060         }
0061 
0062         RegisteredEventListener &current = (*it);
0063         if (current.eventName == evt->name() && current.useCapture == useCapture) {
0064             current.listener->handleEvent(ev);
0065         }
0066 
0067         // ECMA legacy hack
0068         if (current.useCapture == useCapture && evt->id() == EventImpl::CLICK_EVENT) {
0069             MouseEventImpl *me = static_cast<MouseEventImpl *>(evt);
0070             if (me->button() == 0) {
0071                 // To find whether to call onclick or ondblclick, we can't
0072                 // * use me->detail(), it's 2 when clicking twice w/o moving, even very slowly
0073                 // * use me->qEvent(), it's not available when using initMouseEvent/dispatchEvent
0074                 // So we currently store a bool in MouseEventImpl. If anyone needs to trigger
0075                 // dblclicks from the DOM API, we'll need a timer here (well in the doc).
0076                 if ((!me->isDoubleClick() && current.eventName.id() == EventImpl::KHTML_ECMA_CLICK_EVENT) ||
0077                         (me->isDoubleClick() && current.eventName.id() == EventImpl::KHTML_ECMA_DBLCLICK_EVENT)) {
0078                     current.listener->handleEvent(ev);
0079                 }
0080             }
0081         }
0082     }
0083 }
0084 
0085 void EventTargetImpl::defaultEventHandler(EventImpl *)
0086 {}
0087 
0088 DocumentImpl *EventTargetImpl::eventTargetDocument()
0089 {
0090     return nullptr;
0091 }
0092 
0093 void EventTargetImpl::setDocListenerFlag(unsigned flag)
0094 {
0095     DocumentImpl *doc = eventTargetDocument();
0096     if (doc) {
0097         doc->addListenerType(DocumentImpl::ListenerType(flag));
0098     }
0099 }
0100 
0101 void EventTargetImpl::addEventListener(EventName id, EventListener *listener, const bool useCapture)
0102 {
0103     switch (id.id()) {
0104     case EventImpl::DOMSUBTREEMODIFIED_EVENT:
0105         setDocListenerFlag(DocumentImpl::DOMSUBTREEMODIFIED_LISTENER);
0106         break;
0107     case EventImpl::DOMNODEINSERTED_EVENT:
0108         setDocListenerFlag(DocumentImpl::DOMNODEINSERTED_LISTENER);
0109         break;
0110     case EventImpl::DOMNODEREMOVED_EVENT:
0111         setDocListenerFlag(DocumentImpl::DOMNODEREMOVED_LISTENER);
0112         break;
0113     case EventImpl::DOMNODEREMOVEDFROMDOCUMENT_EVENT:
0114         setDocListenerFlag(DocumentImpl::DOMNODEREMOVEDFROMDOCUMENT_LISTENER);
0115         break;
0116     case EventImpl::DOMNODEINSERTEDINTODOCUMENT_EVENT:
0117         setDocListenerFlag(DocumentImpl::DOMNODEINSERTEDINTODOCUMENT_LISTENER);
0118         break;
0119     case EventImpl::DOMATTRMODIFIED_EVENT:
0120         setDocListenerFlag(DocumentImpl::DOMATTRMODIFIED_LISTENER);
0121         break;
0122     case EventImpl::DOMCHARACTERDATAMODIFIED_EVENT:
0123         setDocListenerFlag(DocumentImpl::DOMCHARACTERDATAMODIFIED_LISTENER);
0124         break;
0125     default:
0126         break;
0127     }
0128 
0129     m_regdListeners.addEventListener(id, listener, useCapture);
0130 }
0131 
0132 void EventTargetImpl::removeEventListener(EventName id, EventListener *listener, bool useCapture)
0133 {
0134     m_regdListeners.removeEventListener(id, listener, useCapture);
0135 }
0136 
0137 void EventTargetImpl::setHTMLEventListener(EventName id, EventListener *listener)
0138 {
0139     m_regdListeners.setHTMLEventListener(id, listener);
0140 }
0141 
0142 void EventTargetImpl::setHTMLEventListener(unsigned id, EventListener *listener)
0143 {
0144     m_regdListeners.setHTMLEventListener(EventName::fromId(id), listener);
0145 }
0146 
0147 EventListener *EventTargetImpl::getHTMLEventListener(EventName id)
0148 {
0149     return m_regdListeners.getHTMLEventListener(id);
0150 }
0151 
0152 EventListener *EventTargetImpl::getHTMLEventListener(unsigned id)
0153 {
0154     return m_regdListeners.getHTMLEventListener(EventName::fromId(id));
0155 }
0156 // -----------------------------------------------------------------------------
0157 
0158 void RegisteredListenerList::addEventListener(EventName id, EventListener *listener, const bool useCapture)
0159 {
0160     if (!listener) {
0161         return;
0162     }
0163     RegisteredEventListener rl(id, listener, useCapture);
0164     if (!listeners) {
0165         listeners = new QList<RegisteredEventListener>;
0166     }
0167 
0168     // if this id/listener/useCapture combination is already registered, do nothing.
0169     // the DOM2 spec says that "duplicate instances are discarded", and this keeps
0170     // the listener order intact.
0171     QList<RegisteredEventListener>::iterator it;
0172     for (it = listeners->begin(); it != listeners->end(); ++it)
0173         if (*it == rl) {
0174             return;
0175         }
0176 
0177     listeners->append(rl);
0178 }
0179 
0180 void RegisteredListenerList::removeEventListener(EventName id, EventListener *listener, bool useCapture)
0181 {
0182     if (!listeners) { // nothing to remove
0183         return;
0184     }
0185 
0186     RegisteredEventListener rl(id, listener, useCapture);
0187 
0188     QList<RegisteredEventListener>::iterator it;
0189     for (it = listeners->begin(); it != listeners->end(); ++it)
0190         if (*it == rl) {
0191             listeners->erase(it);
0192             return;
0193         }
0194 }
0195 
0196 bool RegisteredListenerList::isHTMLEventListener(EventListener *listener)
0197 {
0198     return (listener->eventListenerType() == "_khtml_HTMLEventListener");
0199 }
0200 
0201 void RegisteredListenerList::setHTMLEventListener(EventName name, EventListener *listener)
0202 {
0203     if (!listeners) {
0204         listeners = new QList<RegisteredEventListener>;
0205     }
0206 
0207     QList<RegisteredEventListener>::iterator it;
0208     if (!listener) {
0209         for (it = listeners->begin(); it != listeners->end(); ++it) {
0210             if ((*it).eventName == name && isHTMLEventListener((*it).listener)) {
0211                 listeners->erase(it);
0212                 break;
0213             }
0214         }
0215         return;
0216     }
0217 
0218     // if this event already has a registered handler, insert the new one in
0219     // place of the old one, to preserve the order.
0220     RegisteredEventListener rl(name, listener, false);
0221 
0222     for (int i = 0; i < listeners->size(); ++i) {
0223         const RegisteredEventListener &listener = listeners->at(i);
0224         if (listener.eventName == name && isHTMLEventListener(listener.listener)) {
0225             listeners->replace(i, rl);
0226             return;
0227         }
0228     }
0229 
0230     listeners->append(rl);
0231 }
0232 
0233 EventListener *RegisteredListenerList::getHTMLEventListener(EventName name)
0234 {
0235     if (!listeners) {
0236         return nullptr;
0237     }
0238 
0239     QList<RegisteredEventListener>::iterator it;
0240     for (it = listeners->begin(); it != listeners->end(); ++it)
0241         if ((*it).eventName == name && isHTMLEventListener((*it).listener)) {
0242             return (*it).listener;
0243         }
0244     return nullptr;
0245 }
0246 
0247 bool RegisteredListenerList::hasEventListener(EventName name)
0248 {
0249     if (!listeners) {
0250         return false;
0251     }
0252 
0253     QList<RegisteredEventListener>::iterator it;
0254     for (it = listeners->begin(); it != listeners->end(); ++it)
0255         if ((*it).eventName == name) {
0256             return true;
0257         }
0258 
0259     return false;
0260 }
0261 
0262 void RegisteredListenerList::clear()
0263 {
0264     delete listeners;
0265     listeners = nullptr;
0266 }
0267 
0268 bool RegisteredListenerList::stillContainsListener(const RegisteredEventListener &listener)
0269 {
0270     if (!listeners) {
0271         return false;
0272     }
0273     return listeners->contains(listener);
0274 }
0275 
0276 RegisteredListenerList::~RegisteredListenerList()
0277 {
0278     delete listeners; listeners = nullptr;
0279 }
0280 
0281 // -----------------------------------------------------------------------------
0282 
0283 EventImpl::EventImpl()
0284 {
0285     m_canBubble = false;
0286     m_cancelable = false;
0287 
0288     m_propagationStopped = false;
0289     m_defaultPrevented = false;
0290     m_currentTarget = nullptr;
0291     m_eventPhase = 0;
0292     m_target = nullptr;
0293     m_createTime = QDateTime::currentDateTime();
0294     m_defaultHandled = false;
0295 }
0296 
0297 EventImpl::EventImpl(EventId _id, bool canBubbleArg, bool cancelableArg)
0298 {
0299     m_eventName = EventName::fromId(_id);
0300     m_canBubble = canBubbleArg;
0301     m_cancelable = cancelableArg;
0302 
0303     m_propagationStopped = false;
0304     m_defaultPrevented = false;
0305     m_currentTarget = nullptr;
0306     m_eventPhase = 0;
0307     m_target = nullptr;
0308     m_createTime = QDateTime::currentDateTime();
0309     m_defaultHandled = false;
0310 }
0311 
0312 EventImpl::~EventImpl()
0313 {
0314     if (m_target) {
0315         m_target->deref();
0316     }
0317 }
0318 
0319 void EventImpl::setTarget(EventTargetImpl *_target)
0320 {
0321     if (m_target) {
0322         m_target->deref();
0323     }
0324     m_target = _target;
0325     if (m_target) {
0326         m_target->ref();
0327     }
0328 }
0329 
0330 DOMTimeStamp EventImpl::timeStamp()
0331 {
0332     QDateTime epoch(QDate(1970, 1, 1), QTime(0, 0));
0333     // ### kjs does not yet support long long (?) so the value wraps around
0334     return epoch.secsTo(m_createTime) * 1000 + m_createTime.time().msec();
0335 }
0336 
0337 void EventImpl::initEvent(const DOMString &eventTypeArg, bool canBubbleArg, bool cancelableArg)
0338 {
0339     // ### ensure this is not called after we have been dispatched (also for subclasses)
0340 
0341     m_eventName = EventName::fromString(eventTypeArg);
0342 
0343     m_canBubble = canBubbleArg;
0344     m_cancelable = cancelableArg;
0345 }
0346 
0347 khtml::IDTable<EventImpl> *EventImpl::s_idTable;
0348 
0349 khtml::IDTable<EventImpl> *EventImpl::initIdTable()
0350 {
0351     s_idTable = new khtml::IDTable<EventImpl>();
0352     s_idTable->addStaticMapping(DOMFOCUSIN_EVENT, "DOMFocusIn");
0353     s_idTable->addStaticMapping(DOMFOCUSOUT_EVENT, "DOMFocusOut");
0354     s_idTable->addStaticMapping(DOMACTIVATE_EVENT, "DOMActivate");
0355     s_idTable->addStaticMapping(CLICK_EVENT, "click");
0356     s_idTable->addStaticMapping(MOUSEDOWN_EVENT, "mousedown");
0357     s_idTable->addStaticMapping(MOUSEUP_EVENT, "mouseup");
0358     s_idTable->addStaticMapping(MOUSEOVER_EVENT, "mouseover");
0359     s_idTable->addStaticMapping(MOUSEMOVE_EVENT, "mousemove");
0360     s_idTable->addStaticMapping(MOUSEOUT_EVENT, "mouseout");
0361     s_idTable->addStaticMapping(DOMSUBTREEMODIFIED_EVENT, "DOMSubtreeModified");
0362     s_idTable->addStaticMapping(DOMNODEINSERTED_EVENT, "DOMNodeInserted");
0363     s_idTable->addStaticMapping(DOMNODEREMOVED_EVENT, "DOMNodeRemoved");
0364     s_idTable->addStaticMapping(DOMNODEREMOVEDFROMDOCUMENT_EVENT, "DOMNodeRemovedFromDocument");
0365     s_idTable->addStaticMapping(DOMNODEINSERTEDINTODOCUMENT_EVENT, "DOMNodeInsertedIntoDocument");
0366     s_idTable->addStaticMapping(DOMATTRMODIFIED_EVENT, "DOMAttrModified");
0367     s_idTable->addStaticMapping(DOMCHARACTERDATAMODIFIED_EVENT, "DOMCharacterDataModified");
0368     s_idTable->addStaticMapping(LOAD_EVENT, "load");
0369     s_idTable->addStaticMapping(UNLOAD_EVENT, "unload");
0370     s_idTable->addStaticMapping(ABORT_EVENT, "abort");
0371     s_idTable->addStaticMapping(ERROR_EVENT, "error");
0372     s_idTable->addStaticMapping(SELECT_EVENT, "select");
0373     s_idTable->addStaticMapping(CHANGE_EVENT, "change");
0374     s_idTable->addStaticMapping(SUBMIT_EVENT, "submit");
0375     s_idTable->addStaticMapping(RESET_EVENT, "reset");
0376     s_idTable->addStaticMapping(FOCUS_EVENT, "focus");
0377     s_idTable->addStaticMapping(BLUR_EVENT, "blur");
0378     s_idTable->addStaticMapping(RESIZE_EVENT, "resize");
0379     s_idTable->addStaticMapping(SCROLL_EVENT, "scroll");
0380     s_idTable->addStaticMapping(KEYDOWN_EVENT, "keydown");
0381     s_idTable->addStaticMapping(KEYUP_EVENT, "keyup");
0382     s_idTable->addStaticMapping(KEYPRESS_EVENT, "keypress");
0383     //DOM3 ev. suggests textInput, but it's better for compat this way
0384     s_idTable->addStaticMapping(HASHCHANGE_EVENT, "hashchange");
0385 
0386     //khtml extensions
0387     s_idTable->addStaticMapping(KHTML_ECMA_DBLCLICK_EVENT, "dblclick");
0388     s_idTable->addHiddenMapping(KHTML_ECMA_CLICK_EVENT, "click");
0389     s_idTable->addStaticMapping(KHTML_DRAGDROP_EVENT, "khtml_dragdrop");
0390     s_idTable->addStaticMapping(KHTML_MOVE_EVENT, "khtml_move");
0391     s_idTable->addStaticMapping(KHTML_MOUSEWHEEL_EVENT, "DOMMouseScroll");
0392     // adopt the mozilla name for compatibility
0393     s_idTable->addStaticMapping(KHTML_CONTENTLOADED_EVENT, "DOMContentLoaded");
0394     // idem
0395     s_idTable->addStaticMapping(KHTML_READYSTATECHANGE_EVENT, "readystatechange");
0396 
0397     s_idTable->addStaticMapping(MESSAGE_EVENT, "message");
0398 
0399     return s_idTable;
0400 }
0401 
0402 bool EventImpl::isUIEvent() const
0403 {
0404     return false;
0405 }
0406 
0407 bool EventImpl::isMouseEvent() const
0408 {
0409     return false;
0410 }
0411 
0412 bool EventImpl::isMutationEvent() const
0413 {
0414     return false;
0415 }
0416 
0417 bool EventImpl::isTextInputEvent() const
0418 {
0419     return false;
0420 }
0421 
0422 bool EventImpl::isKeyboardEvent() const
0423 {
0424     return false;
0425 }
0426 
0427 bool EventImpl::isMessageEvent() const
0428 {
0429     return false;
0430 }
0431 
0432 bool EventImpl::isHashChangeEvent() const
0433 {
0434     return false;
0435 }
0436 
0437 // -----------------------------------------------------------------------------
0438 
0439 UIEventImpl::UIEventImpl(EventId _id, bool canBubbleArg, bool cancelableArg,
0440                          AbstractViewImpl *viewArg, long detailArg)
0441     : EventImpl(_id, canBubbleArg, cancelableArg)
0442 {
0443     m_view = viewArg;
0444     if (m_view) {
0445         m_view->ref();
0446     }
0447     m_detail = detailArg;
0448 }
0449 
0450 UIEventImpl::~UIEventImpl()
0451 {
0452     if (m_view) {
0453         m_view->deref();
0454     }
0455 }
0456 
0457 void UIEventImpl::initUIEvent(const DOMString &typeArg,
0458                               bool canBubbleArg,
0459                               bool cancelableArg,
0460                               AbstractViewImpl *viewArg,
0461                               long detailArg)
0462 {
0463     EventImpl::initEvent(typeArg, canBubbleArg, cancelableArg);
0464 
0465     if (viewArg) {
0466         viewArg->ref();
0467     }
0468 
0469     if (m_view) {
0470         m_view->deref();
0471     }
0472 
0473     m_view = viewArg;
0474 
0475     m_detail = detailArg;
0476 }
0477 
0478 bool UIEventImpl::isUIEvent() const
0479 {
0480     return true;
0481 }
0482 
0483 // -----------------------------------------------------------------------------
0484 
0485 MouseEventImpl::MouseEventImpl()
0486 {
0487     m_screenX = 0;
0488     m_screenY = 0;
0489     m_clientX = 0;
0490     m_clientY = 0;
0491     m_pageX = 0;
0492     m_pageY = 0;
0493     m_ctrlKey = false;
0494     m_altKey = false;
0495     m_shiftKey = false;
0496     m_metaKey = false;
0497     m_button = 0;
0498     m_relatedTarget = nullptr;
0499     m_qevent = nullptr;
0500     m_isDoubleClick = false;
0501 }
0502 
0503 MouseEventImpl::MouseEventImpl(EventId _id,
0504                                bool canBubbleArg,
0505                                bool cancelableArg,
0506                                AbstractViewImpl *viewArg,
0507                                long detailArg,
0508                                long screenXArg,
0509                                long screenYArg,
0510                                long clientXArg,
0511                                long clientYArg,
0512                                long pageXArg,
0513                                long pageYArg,
0514                                bool ctrlKeyArg,
0515                                bool altKeyArg,
0516                                bool shiftKeyArg,
0517                                bool metaKeyArg,
0518                                unsigned short buttonArg,
0519                                NodeImpl *relatedTargetArg,
0520                                QMouseEvent *qe,
0521                                bool isDoubleClick,
0522                                Orientation orient)
0523     : UIEventImpl(_id, canBubbleArg, cancelableArg, viewArg, detailArg)
0524 {
0525     m_screenX = screenXArg;
0526     m_screenY = screenYArg;
0527     m_clientX = clientXArg;
0528     m_clientY = clientYArg;
0529     m_pageX = pageXArg;
0530     m_pageY = pageYArg;
0531     m_ctrlKey = ctrlKeyArg;
0532     m_altKey = altKeyArg;
0533     m_shiftKey = shiftKeyArg;
0534     m_metaKey = metaKeyArg;
0535     m_button = buttonArg;
0536     m_relatedTarget = relatedTargetArg;
0537     if (m_relatedTarget) {
0538         m_relatedTarget->ref();
0539     }
0540     computeLayerPos();
0541     m_qevent = qe;
0542     m_isDoubleClick = isDoubleClick;
0543     m_orientation = orient;
0544 }
0545 
0546 MouseEventImpl::~MouseEventImpl()
0547 {
0548     if (m_relatedTarget) {
0549         m_relatedTarget->deref();
0550     }
0551 }
0552 
0553 void MouseEventImpl::computeLayerPos()
0554 {
0555     m_layerX = m_pageX;
0556     m_layerY = m_pageY;
0557 
0558     DocumentImpl *doc = view() ? view()->document() : nullptr;
0559     if (doc && doc->renderer()) {
0560         khtml::RenderObject::NodeInfo renderInfo(true, false);
0561         doc->renderer()->layer()->nodeAtPoint(renderInfo, m_pageX, m_pageY);
0562 
0563         NodeImpl *node = renderInfo.innerNonSharedNode();
0564         while (node && !node->renderer()) {
0565             node = node->parent();
0566         }
0567 
0568         if (node) {
0569             RenderLayer *layer = node->renderer()->enclosingLayer();
0570             if (layer) {
0571                 layer->updateLayerPosition();
0572             }
0573 
0574             while (layer) {
0575                 m_layerX -= layer->xPos();
0576                 m_layerY -= layer->yPos();
0577                 layer = layer->parent();
0578             }
0579         }
0580     }
0581 }
0582 
0583 void MouseEventImpl::initMouseEvent(const DOMString &typeArg,
0584                                     bool canBubbleArg,
0585                                     bool cancelableArg,
0586                                     AbstractViewImpl *viewArg,
0587                                     long detailArg,
0588                                     long screenXArg,
0589                                     long screenYArg,
0590                                     long clientXArg,
0591                                     long clientYArg,
0592                                     bool ctrlKeyArg,
0593                                     bool altKeyArg,
0594                                     bool shiftKeyArg,
0595                                     bool metaKeyArg,
0596                                     unsigned short buttonArg,
0597                                     const Node &relatedTargetArg,
0598                                     Orientation orient)
0599 {
0600     UIEventImpl::initUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, detailArg);
0601 
0602     if (m_relatedTarget) {
0603         m_relatedTarget->deref();
0604     }
0605 
0606     m_screenX = screenXArg;
0607     m_screenY = screenYArg;
0608     m_clientX = clientXArg;
0609     m_clientY = clientYArg;
0610     m_pageX   = clientXArg;
0611     m_pageY   = clientYArg;
0612     KHTMLView *v;
0613     if (view() && view()->document() && (v = view()->document()->view())) {
0614         m_pageX += v->contentsX();
0615         m_pageY += v->contentsY();
0616     }
0617     m_ctrlKey = ctrlKeyArg;
0618     m_altKey = altKeyArg;
0619     m_shiftKey = shiftKeyArg;
0620     m_metaKey = metaKeyArg;
0621     m_button = buttonArg;
0622     m_relatedTarget = relatedTargetArg.handle();
0623     if (m_relatedTarget) {
0624         m_relatedTarget->ref();
0625     }
0626     m_orientation = orient;
0627 
0628     // ### make this on-demand. it is soo sloooow
0629     computeLayerPos();
0630     m_qevent = nullptr;
0631 }
0632 
0633 bool MouseEventImpl::isMouseEvent() const
0634 {
0635     return true;
0636 }
0637 
0638 //---------------------------------------------------------------------------------------------
0639 
0640 /* Mapping between special Qt keycodes and virtual DOM codes */
0641 IDTranslator<unsigned, unsigned, unsigned>::Info virtKeyToQtKeyTable[] = {
0642     {KeyEventBaseImpl::DOM_VK_BACK_SPACE, Qt::Key_Backspace},
0643     {KeyEventBaseImpl::DOM_VK_ENTER, Qt::Key_Enter},
0644     {KeyEventBaseImpl::DOM_VK_ENTER, Qt::Key_Return},
0645     {KeyEventBaseImpl::DOM_VK_NUM_LOCK,  Qt::Key_NumLock},
0646     {KeyEventBaseImpl::DOM_VK_RIGHT_ALT,    Qt::Key_Alt},
0647     {KeyEventBaseImpl::DOM_VK_LEFT_CONTROL, Qt::Key_Control},
0648     {KeyEventBaseImpl::DOM_VK_LEFT_SHIFT,   Qt::Key_Shift},
0649     {KeyEventBaseImpl::DOM_VK_META,         Qt::Key_Meta},
0650     {KeyEventBaseImpl::DOM_VK_CAPS_LOCK,    Qt::Key_CapsLock},
0651     {KeyEventBaseImpl::DOM_VK_DELETE,       Qt::Key_Delete},
0652     {KeyEventBaseImpl::DOM_VK_INSERT,       Qt::Key_Insert},
0653     {KeyEventBaseImpl::DOM_VK_END,          Qt::Key_End},
0654     {KeyEventBaseImpl::DOM_VK_ESCAPE,       Qt::Key_Escape},
0655     {KeyEventBaseImpl::DOM_VK_HOME,         Qt::Key_Home},
0656     {KeyEventBaseImpl::DOM_VK_PAUSE,        Qt::Key_Pause},
0657     {KeyEventBaseImpl::DOM_VK_PRINTSCREEN,  Qt::Key_Print},
0658     {KeyEventBaseImpl::DOM_VK_SCROLL_LOCK,  Qt::Key_ScrollLock},
0659     {KeyEventBaseImpl::DOM_VK_LEFT,         Qt::Key_Left},
0660     {KeyEventBaseImpl::DOM_VK_RIGHT,        Qt::Key_Right},
0661     {KeyEventBaseImpl::DOM_VK_UP,           Qt::Key_Up},
0662     {KeyEventBaseImpl::DOM_VK_DOWN,         Qt::Key_Down},
0663     {KeyEventBaseImpl::DOM_VK_PAGE_DOWN,    Qt::Key_PageDown},
0664     {KeyEventBaseImpl::DOM_VK_PAGE_UP,      Qt::Key_PageUp},
0665     {KeyEventBaseImpl::DOM_VK_F1,           Qt::Key_F1},
0666     {KeyEventBaseImpl::DOM_VK_F2,           Qt::Key_F2},
0667     {KeyEventBaseImpl::DOM_VK_F3,           Qt::Key_F3},
0668     {KeyEventBaseImpl::DOM_VK_F4,           Qt::Key_F4},
0669     {KeyEventBaseImpl::DOM_VK_F5,           Qt::Key_F5},
0670     {KeyEventBaseImpl::DOM_VK_F6,           Qt::Key_F6},
0671     {KeyEventBaseImpl::DOM_VK_F7,           Qt::Key_F7},
0672     {KeyEventBaseImpl::DOM_VK_F8,           Qt::Key_F8},
0673     {KeyEventBaseImpl::DOM_VK_F9,           Qt::Key_F9},
0674     {KeyEventBaseImpl::DOM_VK_F10,          Qt::Key_F10},
0675     {KeyEventBaseImpl::DOM_VK_F11,          Qt::Key_F11},
0676     {KeyEventBaseImpl::DOM_VK_F12,          Qt::Key_F12},
0677     {KeyEventBaseImpl::DOM_VK_F13,          Qt::Key_F13},
0678     {KeyEventBaseImpl::DOM_VK_F14,          Qt::Key_F14},
0679     {KeyEventBaseImpl::DOM_VK_F15,          Qt::Key_F15},
0680     {KeyEventBaseImpl::DOM_VK_F16,          Qt::Key_F16},
0681     {KeyEventBaseImpl::DOM_VK_F17,          Qt::Key_F17},
0682     {KeyEventBaseImpl::DOM_VK_F18,          Qt::Key_F18},
0683     {KeyEventBaseImpl::DOM_VK_F19,          Qt::Key_F19},
0684     {KeyEventBaseImpl::DOM_VK_F20,          Qt::Key_F20},
0685     {KeyEventBaseImpl::DOM_VK_F21,          Qt::Key_F21},
0686     {KeyEventBaseImpl::DOM_VK_F22,          Qt::Key_F22},
0687     {KeyEventBaseImpl::DOM_VK_F23,          Qt::Key_F23},
0688     {KeyEventBaseImpl::DOM_VK_F24,          Qt::Key_F24},
0689     {0,                   0}
0690 };
0691 
0692 MAKE_TRANSLATOR(virtKeyToQtKey, unsigned, unsigned, unsigned, virtKeyToQtKeyTable)
0693 
0694 KeyEventBaseImpl::KeyEventBaseImpl(EventId id, bool canBubbleArg, bool cancelableArg, AbstractViewImpl *viewArg,
0695                                    QKeyEvent *key) :
0696     UIEventImpl(id, canBubbleArg, cancelableArg, viewArg, 0)
0697 {
0698     m_synthetic = false;
0699 
0700     m_keyEvent = new QKeyEvent(key->type(), key->key(), key->modifiers(), key->text(), key->isAutoRepeat(), key->count());
0701 
0702     //Here, we need to map Qt's internal info to browser-style info.
0703     m_detail = key->count();
0704     m_keyVal = 0; // Set below unless virtual...
0705     m_virtKeyVal = virtKeyToQtKey()->toLeft(key->key());
0706 
0707     // m_keyVal should contain the unicode value
0708     // of the pressed key if available, including case distinction
0709     if (m_virtKeyVal == DOM_VK_UNDEFINED && !key->text().isEmpty()) {
0710         // ... unfortunately, this value is useless if ctrl+ or alt+ are used.
0711         if (key->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) {
0712             // Try to recover the case... Not quite right with caps lock involved, hence proving again its evilness
0713             if (key->modifiers() & (Qt::ShiftModifier)) {
0714                 m_keyVal = key->key();    // The original is upper case anyway
0715             } else {
0716                 m_keyVal = QChar(key->key()).toLower().unicode();
0717             }
0718         } else {
0719             m_keyVal = key->text().unicode()[0].unicode();
0720         }
0721     }
0722 
0723     // key->state returns enum ButtonState, which is ShiftButton, ControlButton and AltButton or'ed together.
0724     m_modifier = key->modifiers();
0725 }
0726 
0727 KeyEventBaseImpl::~KeyEventBaseImpl()
0728 {
0729     delete m_keyEvent;
0730 }
0731 
0732 void KeyEventBaseImpl::initKeyBaseEvent(const DOMString &typeArg,
0733                                         bool canBubbleArg,
0734                                         bool cancelableArg,
0735                                         AbstractViewImpl *viewArg,
0736                                         unsigned long keyValArg,
0737                                         unsigned long virtKeyValArg,
0738                                         unsigned long modifiersArg)
0739 {
0740     m_synthetic = true;
0741     delete m_keyEvent;
0742     m_keyEvent = nullptr;
0743     initUIEvent(typeArg, canBubbleArg, cancelableArg, viewArg, 1);
0744     m_virtKeyVal = virtKeyValArg;
0745     m_keyVal     = keyValArg;
0746     m_modifier   = modifiersArg;
0747 }
0748 
0749 bool KeyEventBaseImpl::checkModifier(unsigned long modifierArg)
0750 {
0751     return ((m_modifier & modifierArg) == modifierArg);
0752 }
0753 
0754 void KeyEventBaseImpl::buildQKeyEvent() const
0755 {
0756     delete m_keyEvent;
0757 
0758     assert(m_synthetic);
0759     //IMPORTANT: we ignore modifers on purpose.
0760     //this is to prevent a website from synthesizing something
0761     //like Ctrl-V or Shift-Insert and stealing contents of the user's clipboard.
0762     Qt::KeyboardModifiers modifiers = nullptr;
0763 
0764     if (m_modifier & Qt::KeypadModifier) {
0765         modifiers |= Qt::KeypadModifier;
0766     }
0767 
0768     int key   = 0;
0769     QString text;
0770     if (m_virtKeyVal) {
0771         key = virtKeyToQtKey()->toRight(m_virtKeyVal);
0772     }
0773     if (!key) {
0774         key   = m_keyVal;
0775         text  = QChar(key);
0776     }
0777 
0778     //Neuter F keys as well.
0779     if (key >= Qt::Key_F1 && key <= Qt::Key_F35) {
0780         key = Qt::Key_ScrollLock;
0781     }
0782 
0783     m_keyEvent = new QKeyEvent(id() == KEYUP_EVENT ? QEvent::KeyRelease : QEvent::KeyPress,
0784                                key, modifiers, text);
0785 }
0786 
0787 //------------------------------------------------------------------------------
0788 
0789 static const IDTranslator<QByteArray, unsigned, const char *>::Info keyIdentifiersToVirtKeysTable[] = {
0790     {"Alt",         KeyEventBaseImpl::DOM_VK_LEFT_ALT},
0791     {"Control",     KeyEventBaseImpl::DOM_VK_LEFT_CONTROL},
0792     {"Shift",       KeyEventBaseImpl::DOM_VK_LEFT_SHIFT},
0793     {"Meta",        KeyEventBaseImpl::DOM_VK_META},
0794     {"\0x08",       KeyEventBaseImpl::DOM_VK_SPACE},           //1-char virt!
0795     {"CapsLock",    KeyEventBaseImpl::DOM_VK_CAPS_LOCK},
0796     {"\x7F",        KeyEventBaseImpl::DOM_VK_DELETE},          //1-char virt!
0797     {"End",         KeyEventBaseImpl::DOM_VK_END},
0798     {"Enter",       KeyEventBaseImpl::DOM_VK_ENTER},
0799     {"\x1b",        KeyEventBaseImpl::DOM_VK_ESCAPE},          //1-char virt!
0800     {"Home",        KeyEventBaseImpl::DOM_VK_HOME},
0801     {"NumLock",     KeyEventBaseImpl::DOM_VK_NUM_LOCK},
0802     {"Pause",       KeyEventBaseImpl::DOM_VK_PAUSE},
0803     {"PrintScreen", KeyEventBaseImpl::DOM_VK_PRINTSCREEN},
0804     {"Scroll",   KeyEventBaseImpl::DOM_VK_SCROLL_LOCK},
0805     {" ",        KeyEventBaseImpl::DOM_VK_SPACE},               //1-char virt!
0806     {"\t",       KeyEventBaseImpl::DOM_VK_TAB},                 //1-char virt!
0807     {"Left",     KeyEventBaseImpl::DOM_VK_LEFT},
0808     {"Left",     KeyEventBaseImpl::DOM_VK_LEFT},
0809     {"Right",    KeyEventBaseImpl::DOM_VK_RIGHT},
0810     {"Up",       KeyEventBaseImpl::DOM_VK_UP},
0811     {"Down",     KeyEventBaseImpl::DOM_VK_DOWN},
0812     {"PageDown", KeyEventBaseImpl::DOM_VK_PAGE_DOWN},
0813     {"PageUp", KeyEventBaseImpl::DOM_VK_PAGE_UP},
0814     {"F1", KeyEventBaseImpl::DOM_VK_F1},
0815     {"F2", KeyEventBaseImpl::DOM_VK_F2},
0816     {"F3", KeyEventBaseImpl::DOM_VK_F3},
0817     {"F4", KeyEventBaseImpl::DOM_VK_F4},
0818     {"F5", KeyEventBaseImpl::DOM_VK_F5},
0819     {"F6", KeyEventBaseImpl::DOM_VK_F6},
0820     {"F7", KeyEventBaseImpl::DOM_VK_F7},
0821     {"F8", KeyEventBaseImpl::DOM_VK_F8},
0822     {"F9", KeyEventBaseImpl::DOM_VK_F9},
0823     {"F10", KeyEventBaseImpl::DOM_VK_F10},
0824     {"F11", KeyEventBaseImpl::DOM_VK_F11},
0825     {"F12", KeyEventBaseImpl::DOM_VK_F12},
0826     {"F13", KeyEventBaseImpl::DOM_VK_F13},
0827     {"F14", KeyEventBaseImpl::DOM_VK_F14},
0828     {"F15", KeyEventBaseImpl::DOM_VK_F15},
0829     {"F16", KeyEventBaseImpl::DOM_VK_F16},
0830     {"F17", KeyEventBaseImpl::DOM_VK_F17},
0831     {"F18", KeyEventBaseImpl::DOM_VK_F18},
0832     {"F19", KeyEventBaseImpl::DOM_VK_F19},
0833     {"F20", KeyEventBaseImpl::DOM_VK_F20},
0834     {"F21", KeyEventBaseImpl::DOM_VK_F21},
0835     {"F22", KeyEventBaseImpl::DOM_VK_F22},
0836     {"F23", KeyEventBaseImpl::DOM_VK_F23},
0837     {"F24", KeyEventBaseImpl::DOM_VK_F24},
0838     {nullptr, 0}
0839 };
0840 
0841 MAKE_TRANSLATOR(keyIdentifiersToVirtKeys, QByteArray, unsigned, const char *, keyIdentifiersToVirtKeysTable)
0842 
0843 /** These are the modifiers we currently support */
0844 static const IDTranslator<QByteArray, unsigned, const char *>::Info keyModifiersToCodeTable[] = {
0845     {"Alt",         Qt::AltModifier},
0846     {"Control",     Qt::ControlModifier},
0847     {"Shift",       Qt::ShiftModifier},
0848     {"Meta",        Qt::MetaModifier},
0849     {nullptr,             0}
0850 };
0851 
0852 MAKE_TRANSLATOR(keyModifiersToCode, QByteArray, unsigned, const char *, keyModifiersToCodeTable)
0853 
0854 KeyboardEventImpl::KeyboardEventImpl() : m_keyLocation(KeyboardEvent::DOM_KEY_LOCATION_STANDARD)
0855 {}
0856 
0857 DOMString KeyboardEventImpl::keyIdentifier() const
0858 {
0859     if (unsigned special = virtKeyVal())
0860         if (const char *id = keyIdentifiersToVirtKeys()->toLeft(special)) {
0861             return QString::fromLatin1(id);
0862         }
0863 
0864     if (unsigned unicode = keyVal()) {
0865         return QString(QChar(unicode));
0866     }
0867 
0868     return "Unidentified";
0869 }
0870 
0871 bool KeyboardEventImpl::getModifierState(const DOMString &keyIdentifierArg) const
0872 {
0873     unsigned mask = keyModifiersToCode()->toRight(keyIdentifierArg.string().toLatin1());
0874     return m_modifier & mask;
0875 }
0876 
0877 bool KeyboardEventImpl::isKeyboardEvent() const
0878 {
0879     return true;
0880 }
0881 
0882 void KeyboardEventImpl::initKeyboardEvent(const DOMString &typeArg,
0883         bool canBubbleArg,
0884         bool cancelableArg,
0885         AbstractViewImpl *viewArg,
0886         const DOMString &keyIdentifierArg,
0887         unsigned long keyLocationArg,
0888         const DOMString &modifiersList)
0889 {
0890     unsigned keyVal     = 0;
0891     unsigned virtKeyVal = 0;
0892 
0893     m_keyLocation = keyLocationArg;
0894 
0895     //Figure out the code information from the key identifier.
0896     if (keyIdentifierArg.length() == 1) {
0897         //Likely to be normal unicode id, unless it's one of the few
0898         //special values.
0899         unsigned short code = keyIdentifierArg.unicode()[0].unicode();
0900         if (code > 0x20 && code != 0x7F) {
0901             keyVal = code;
0902         }
0903     }
0904 
0905     if (!keyVal) { //One of special keys, likely.
0906         virtKeyVal = keyIdentifiersToVirtKeys()->toRight(keyIdentifierArg.string().toLatin1());
0907     }
0908 
0909     //Process modifier list.
0910     const QStringList mods = modifiersList.string().trimmed().simplified().split(' ');
0911 
0912     unsigned modifiers = 0;
0913     for (QStringList::ConstIterator i = mods.begin(); i != mods.end(); ++i)
0914         if (unsigned mask = keyModifiersToCode()->toRight((*i).toLatin1())) {
0915             modifiers |= mask;
0916         }
0917 
0918     initKeyBaseEvent(typeArg, canBubbleArg, cancelableArg, viewArg,
0919                      keyVal, virtKeyVal, modifiers);
0920 }
0921 
0922 KeyboardEventImpl::KeyboardEventImpl(QKeyEvent *key, DOM::AbstractViewImpl *view) :
0923     KeyEventBaseImpl(key->type() == QEvent::KeyRelease ? KEYUP_EVENT : KEYDOWN_EVENT, true, true, view, key)
0924 {
0925     if (key->modifiers() & Qt::KeypadModifier) {
0926         m_keyLocation = KeyboardEvent::DOM_KEY_LOCATION_NUMPAD;
0927     } else {
0928         //It's generally standard, but for the modifiers,
0929         //it should be left/right, so guess left.
0930         m_keyLocation = KeyboardEvent::DOM_KEY_LOCATION_STANDARD;
0931         switch (m_virtKeyVal) {
0932         case DOM_VK_LEFT_ALT:
0933         case DOM_VK_LEFT_SHIFT:
0934         case DOM_VK_LEFT_CONTROL:
0935         case DOM_VK_META:
0936             m_keyLocation = KeyboardEvent::DOM_KEY_LOCATION_LEFT;
0937         }
0938     }
0939 }
0940 
0941 int KeyboardEventImpl::keyCode() const
0942 {
0943     //Keycode on key events always identifies the -key- and not the input,
0944     //so e.g. 'a' will get 'A'
0945     if (m_virtKeyVal != DOM_VK_UNDEFINED) {
0946         return m_virtKeyVal;
0947     } else {
0948         unsigned char code = QChar((unsigned short)m_keyVal).toUpper().unicode();
0949         // Some codes we get from Qt are things like ( which conflict with
0950         // browser scancodes. Remap them to what's on their keycaps in a US
0951         // layout.
0952         if (virtKeyToQtKey()->hasLeft(code)) {
0953             switch (code) {
0954             case '!': return '1';
0955             case '@': return '2';
0956             case '#': return '3';
0957             case '$': return '4';
0958             case '%': return '5';
0959             case '^': return '6';
0960             case '&': return '7';
0961             case '*': return '8';
0962             case '(': return '9';
0963             case ')': return '0';
0964             default:
0965                 qCWarning(KHTML_LOG) << "Don't know how resolve conflict of code:" << code
0966                            << " with a virtKey";
0967             }
0968         }
0969         return code;
0970     }
0971 }
0972 
0973 int KeyboardEventImpl::charCode() const
0974 {
0975     //IE doesn't support charCode at all, and mozilla returns 0
0976     //on key events. So return 0 here
0977     return 0;
0978 }
0979 
0980 // -----------------------------------------------------------------------------
0981 TextEventImpl::TextEventImpl()
0982 {}
0983 
0984 bool TextEventImpl::isTextInputEvent() const
0985 {
0986     return true;
0987 }
0988 
0989 TextEventImpl::TextEventImpl(QKeyEvent *key, DOM::AbstractViewImpl *view) :
0990     KeyEventBaseImpl(KEYPRESS_EVENT, true, true, view, key)
0991 {
0992     m_outputString = key->text();
0993 }
0994 
0995 void TextEventImpl::initTextEvent(const DOMString &typeArg,
0996                                   bool canBubbleArg,
0997                                   bool cancelableArg,
0998                                   AbstractViewImpl *viewArg,
0999                                   const DOMString &text)
1000 {
1001     m_outputString = text;
1002 
1003     //See whether we can get a key out of this.
1004     unsigned keyCode = 0;
1005     if (text.length() == 1) {
1006         keyCode = text.unicode()[0].unicode();
1007     }
1008     initKeyBaseEvent(typeArg, canBubbleArg, cancelableArg, viewArg,
1009                      keyCode, 0, 0);
1010 }
1011 
1012 int TextEventImpl::keyCode() const
1013 {
1014     //Mozilla returns 0 here unless this is a non-unicode key.
1015     //IE stuffs everything here, and so we try to match it..
1016     if (m_keyVal) {
1017         return m_keyVal;
1018     }
1019     return m_virtKeyVal;
1020 }
1021 
1022 int TextEventImpl::charCode() const
1023 {
1024     //On text events, in Mozilla charCode is 0 for non-unicode keys,
1025     //and the unicode key otherwise... IE doesn't support this.
1026     if (m_virtKeyVal) {
1027         return 0;
1028     }
1029     return m_keyVal;
1030 }
1031 
1032 // -----------------------------------------------------------------------------
1033 MutationEventImpl::MutationEventImpl()
1034 {
1035     m_relatedNode = nullptr;
1036     m_prevValue = nullptr;
1037     m_newValue = nullptr;
1038     m_attrName = nullptr;
1039     m_attrChange = 0;
1040 }
1041 
1042 MutationEventImpl::MutationEventImpl(EventId _id,
1043                                      bool canBubbleArg,
1044                                      bool cancelableArg,
1045                                      const Node &relatedNodeArg,
1046                                      const DOMString &prevValueArg,
1047                                      const DOMString &newValueArg,
1048                                      const DOMString &attrNameArg,
1049                                      unsigned short attrChangeArg)
1050     : EventImpl(_id, canBubbleArg, cancelableArg)
1051 {
1052     m_relatedNode = relatedNodeArg.handle();
1053     if (m_relatedNode) {
1054         m_relatedNode->ref();
1055     }
1056     m_prevValue = prevValueArg.implementation();
1057     if (m_prevValue) {
1058         m_prevValue->ref();
1059     }
1060     m_newValue = newValueArg.implementation();
1061     if (m_newValue) {
1062         m_newValue->ref();
1063     }
1064     m_attrName = attrNameArg.implementation();
1065     if (m_attrName) {
1066         m_attrName->ref();
1067     }
1068     m_attrChange = attrChangeArg;
1069 }
1070 
1071 MutationEventImpl::~MutationEventImpl()
1072 {
1073     if (m_relatedNode) {
1074         m_relatedNode->deref();
1075     }
1076     if (m_prevValue) {
1077         m_prevValue->deref();
1078     }
1079     if (m_newValue) {
1080         m_newValue->deref();
1081     }
1082     if (m_attrName) {
1083         m_attrName->deref();
1084     }
1085 }
1086 
1087 void MutationEventImpl::initMutationEvent(const DOMString &typeArg,
1088         bool canBubbleArg,
1089         bool cancelableArg,
1090         const Node &relatedNodeArg,
1091         const DOMString &prevValueArg,
1092         const DOMString &newValueArg,
1093         const DOMString &attrNameArg,
1094         unsigned short attrChangeArg)
1095 {
1096     EventImpl::initEvent(typeArg, canBubbleArg, cancelableArg);
1097 
1098     if (m_relatedNode) {
1099         m_relatedNode->deref();
1100     }
1101     if (m_prevValue) {
1102         m_prevValue->deref();
1103     }
1104     if (m_newValue) {
1105         m_newValue->deref();
1106     }
1107     if (m_attrName) {
1108         m_attrName->deref();
1109     }
1110 
1111     m_relatedNode = relatedNodeArg.handle();
1112     if (m_relatedNode) {
1113         m_relatedNode->ref();
1114     }
1115     m_prevValue = prevValueArg.implementation();
1116     if (m_prevValue) {
1117         m_prevValue->ref();
1118     }
1119     m_newValue = newValueArg.implementation();
1120     if (m_newValue) {
1121         m_newValue->ref();
1122     }
1123     m_attrName = attrNameArg.implementation();
1124     if (m_newValue) {
1125         m_newValue->ref();
1126     }
1127     m_attrChange = attrChangeArg;
1128 }
1129 
1130 bool MutationEventImpl::isMutationEvent() const
1131 {
1132     return true;
1133 }
1134 
1135 // -----------------------------------------------------------------------------
1136 
1137 MessageEventImpl::MessageEventImpl()
1138 {}
1139 
1140 bool MessageEventImpl::isMessageEvent() const
1141 {
1142     return true;
1143 }
1144 
1145 void MessageEventImpl::initMessageEvent(const DOMString &typeArg,
1146                                         bool  canBubbleArg,
1147                                         bool  cancelableArg,
1148                                         const RefPtr<Data> &dataArg,
1149                                         const DOMString &originArg,
1150                                         const DOMString &lastEventIdArg,
1151                                         KHTMLPart *sourceArg)
1152 {
1153     EventImpl::initEvent(typeArg, canBubbleArg, cancelableArg);
1154     m_data   = dataArg;
1155     m_origin = originArg;
1156     m_lastEventId = lastEventIdArg;
1157     m_source      = sourceArg;
1158 }
1159 
1160 // -----------------------------------------------------------------------------
1161 
1162 HashChangeEventImpl::HashChangeEventImpl()
1163 {
1164 }
1165 
1166 bool HashChangeEventImpl::isHashChangeEvent() const
1167 {
1168     return true;
1169 }
1170 
1171 void HashChangeEventImpl::initHashChangeEvent(const DOMString &eventTypeArg, bool canBubbleArg, bool cancelableArg, const DOMString &oldUrl, const DOMString &newUrl)
1172 {
1173     EventImpl::initEvent(eventTypeArg, canBubbleArg, cancelableArg);
1174     m_oldUrl = oldUrl;
1175     m_newUrl = newUrl;
1176 }