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 ¤t = (*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 }