1 /* 2 Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> 3 4 This file is part of the KDE project 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Library General Public 8 License as published by the Free Software Foundation; either 9 version 2 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Library General Public License for more details. 15 16 You should have received a copy of the GNU Library General Public License 17 along with this library; see the file COPYING.LIB. If not, write to 18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 Boston, MA 02110-1301, USA. 20 */ 21 22 #include "config.h" 23 24 #if ENABLE(SVG) 25 #include "SVGElementInstance.h" 26 27 #include "ContainerNodeAlgorithms.h" 28 #include "Document.h" 29 #include "Event.h" 30 #include "EventException.h" 31 #include "EventListener.h" 32 #include "EventNames.h" 33 #include "FrameView.h" 34 #include "SVGElementInstanceList.h" 35 #include "SVGUseElement.h" 36 37 #include <wtf/RefCountedLeakCounter.h> 38 39 #if USE(JSC) 40 #include "GCController.h" 41 #endif 42 43 namespace WebCore { 44 45 #ifndef NDEBUG 46 static WTF::RefCountedLeakCounter instanceCounter("WebCoreSVGElementInstance"); 47 #endif 48 SVGElementInstance(SVGUseElement * useElement,SVGElement * originalElement)49 SVGElementInstance::SVGElementInstance(SVGUseElement* useElement, SVGElement* originalElement) 50 : m_needsUpdate(false) 51 , m_useElement(useElement) 52 , m_element(originalElement) 53 , m_previousSibling(0) 54 , m_nextSibling(0) 55 , m_firstChild(0) 56 , m_lastChild(0) 57 { 58 ASSERT(m_useElement); 59 ASSERT(m_element); 60 61 // Register as instance for passed element. 62 m_element->mapInstanceToElement(this); 63 64 #ifndef NDEBUG 65 instanceCounter.increment(); 66 #endif 67 } 68 ~SVGElementInstance()69 SVGElementInstance::~SVGElementInstance() 70 { 71 #ifndef NDEBUG 72 instanceCounter.decrement(); 73 #endif 74 75 // Deregister as instance for passed element. 76 m_element->removeInstanceMapping(this); 77 78 removeAllChildrenInContainer<SVGElementInstance, SVGElementInstance>(this); 79 } 80 childNodes()81 PassRefPtr<SVGElementInstanceList> SVGElementInstance::childNodes() 82 { 83 return SVGElementInstanceList::create(this); 84 } 85 setShadowTreeElement(SVGElement * element)86 void SVGElementInstance::setShadowTreeElement(SVGElement* element) 87 { 88 ASSERT(element); 89 m_shadowTreeElement = element; 90 } 91 forgetWrapper()92 void SVGElementInstance::forgetWrapper() 93 { 94 #if USE(JSC) 95 // FIXME: This is fragile, as discussed with Sam. Need to find a better solution. 96 // Think about the case where JS explicitely holds "var root = useElement.instanceRoot;". 97 // We still have to recreate this wrapper somehow. The gc collection below, won't catch it. 98 99 // If the use shadow tree has been rebuilt, just the JSSVGElementInstance objects 100 // are still holding RefPtrs of SVGElementInstance objects, which prevent us to 101 // be deleted (and the shadow tree is not destructed as well). Force JS GC. 102 gcController().garbageCollectNow(); 103 #endif 104 } 105 appendChild(PassRefPtr<SVGElementInstance> child)106 void SVGElementInstance::appendChild(PassRefPtr<SVGElementInstance> child) 107 { 108 appendChildToContainer<SVGElementInstance, SVGElementInstance>(child.get(), this); 109 } 110 invalidateAllInstancesOfElement(SVGElement * element)111 void SVGElementInstance::invalidateAllInstancesOfElement(SVGElement* element) 112 { 113 if (!element) 114 return; 115 116 HashSet<SVGElementInstance*> set = element->instancesForElement(); 117 if (set.isEmpty()) 118 return; 119 120 // Find all use elements referencing the instances - ask them _once_ to rebuild. 121 HashSet<SVGElementInstance*>::const_iterator it = set.begin(); 122 const HashSet<SVGElementInstance*>::const_iterator end = set.end(); 123 124 for (; it != end; ++it) 125 (*it)->setNeedsUpdate(true); 126 } 127 setNeedsUpdate(bool value)128 void SVGElementInstance::setNeedsUpdate(bool value) 129 { 130 m_needsUpdate = value; 131 132 if (m_needsUpdate) 133 correspondingUseElement()->setNeedsStyleRecalc(); 134 } 135 scriptExecutionContext() const136 ScriptExecutionContext* SVGElementInstance::scriptExecutionContext() const 137 { 138 if (SVGElement* element = correspondingElement()) 139 return element->document(); 140 return 0; 141 } 142 addEventListener(const AtomicString & eventType,PassRefPtr<EventListener> listener,bool useCapture)143 void SVGElementInstance::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) 144 { 145 if (SVGElement* element = correspondingElement()) 146 element->addEventListener(eventType, listener, useCapture); 147 } 148 removeEventListener(const AtomicString & eventType,EventListener * listener,bool useCapture)149 void SVGElementInstance::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) 150 { 151 if (SVGElement* element = correspondingElement()) 152 element->removeEventListener(eventType, listener, useCapture); 153 } 154 dispatchEvent(PassRefPtr<Event> e,ExceptionCode & ec)155 bool SVGElementInstance::dispatchEvent(PassRefPtr<Event> e, ExceptionCode& ec) 156 { 157 RefPtr<Event> evt(e); 158 ASSERT(!eventDispatchForbidden()); 159 if (!evt || evt->type().isEmpty()) { 160 ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR; 161 return false; 162 } 163 164 // The event has to be dispatched to the shadowTreeElement(), not the correspondingElement()! 165 SVGElement* element = shadowTreeElement(); 166 if (!element) 167 return false; 168 169 evt->setTarget(this); 170 171 RefPtr<FrameView> view = element->document()->view(); 172 return element->dispatchGenericEvent(evt.release()); 173 } 174 onabort() const175 EventListener* SVGElementInstance::onabort() const 176 { 177 return correspondingElement()->getAttributeEventListener(eventNames().abortEvent); 178 } 179 setOnabort(PassRefPtr<EventListener> eventListener)180 void SVGElementInstance::setOnabort(PassRefPtr<EventListener> eventListener) 181 { 182 correspondingElement()->setAttributeEventListener(eventNames().abortEvent, eventListener); 183 } 184 onblur() const185 EventListener* SVGElementInstance::onblur() const 186 { 187 return correspondingElement()->getAttributeEventListener(eventNames().blurEvent); 188 } 189 setOnblur(PassRefPtr<EventListener> eventListener)190 void SVGElementInstance::setOnblur(PassRefPtr<EventListener> eventListener) 191 { 192 correspondingElement()->setAttributeEventListener(eventNames().blurEvent, eventListener); 193 } 194 onchange() const195 EventListener* SVGElementInstance::onchange() const 196 { 197 return correspondingElement()->getAttributeEventListener(eventNames().changeEvent); 198 } 199 setOnchange(PassRefPtr<EventListener> eventListener)200 void SVGElementInstance::setOnchange(PassRefPtr<EventListener> eventListener) 201 { 202 correspondingElement()->setAttributeEventListener(eventNames().changeEvent, eventListener); 203 } 204 onclick() const205 EventListener* SVGElementInstance::onclick() const 206 { 207 return correspondingElement()->getAttributeEventListener(eventNames().clickEvent); 208 } 209 setOnclick(PassRefPtr<EventListener> eventListener)210 void SVGElementInstance::setOnclick(PassRefPtr<EventListener> eventListener) 211 { 212 correspondingElement()->setAttributeEventListener(eventNames().clickEvent, eventListener); 213 } 214 oncontextmenu() const215 EventListener* SVGElementInstance::oncontextmenu() const 216 { 217 return correspondingElement()->getAttributeEventListener(eventNames().contextmenuEvent); 218 } 219 setOncontextmenu(PassRefPtr<EventListener> eventListener)220 void SVGElementInstance::setOncontextmenu(PassRefPtr<EventListener> eventListener) 221 { 222 correspondingElement()->setAttributeEventListener(eventNames().contextmenuEvent, eventListener); 223 } 224 ondblclick() const225 EventListener* SVGElementInstance::ondblclick() const 226 { 227 return correspondingElement()->getAttributeEventListener(eventNames().dblclickEvent); 228 } 229 setOndblclick(PassRefPtr<EventListener> eventListener)230 void SVGElementInstance::setOndblclick(PassRefPtr<EventListener> eventListener) 231 { 232 correspondingElement()->setAttributeEventListener(eventNames().dblclickEvent, eventListener); 233 } 234 onerror() const235 EventListener* SVGElementInstance::onerror() const 236 { 237 return correspondingElement()->getAttributeEventListener(eventNames().errorEvent); 238 } 239 setOnerror(PassRefPtr<EventListener> eventListener)240 void SVGElementInstance::setOnerror(PassRefPtr<EventListener> eventListener) 241 { 242 correspondingElement()->setAttributeEventListener(eventNames().errorEvent, eventListener); 243 } 244 onfocus() const245 EventListener* SVGElementInstance::onfocus() const 246 { 247 return correspondingElement()->getAttributeEventListener(eventNames().focusEvent); 248 } 249 setOnfocus(PassRefPtr<EventListener> eventListener)250 void SVGElementInstance::setOnfocus(PassRefPtr<EventListener> eventListener) 251 { 252 correspondingElement()->setAttributeEventListener(eventNames().focusEvent, eventListener); 253 } 254 oninput() const255 EventListener* SVGElementInstance::oninput() const 256 { 257 return correspondingElement()->getAttributeEventListener(eventNames().inputEvent); 258 } 259 setOninput(PassRefPtr<EventListener> eventListener)260 void SVGElementInstance::setOninput(PassRefPtr<EventListener> eventListener) 261 { 262 correspondingElement()->setAttributeEventListener(eventNames().inputEvent, eventListener); 263 } 264 onkeydown() const265 EventListener* SVGElementInstance::onkeydown() const 266 { 267 return correspondingElement()->getAttributeEventListener(eventNames().keydownEvent); 268 } 269 setOnkeydown(PassRefPtr<EventListener> eventListener)270 void SVGElementInstance::setOnkeydown(PassRefPtr<EventListener> eventListener) 271 { 272 correspondingElement()->setAttributeEventListener(eventNames().keydownEvent, eventListener); 273 } 274 onkeypress() const275 EventListener* SVGElementInstance::onkeypress() const 276 { 277 return correspondingElement()->getAttributeEventListener(eventNames().keypressEvent); 278 } 279 setOnkeypress(PassRefPtr<EventListener> eventListener)280 void SVGElementInstance::setOnkeypress(PassRefPtr<EventListener> eventListener) 281 { 282 correspondingElement()->setAttributeEventListener(eventNames().keypressEvent, eventListener); 283 } 284 onkeyup() const285 EventListener* SVGElementInstance::onkeyup() const 286 { 287 return correspondingElement()->getAttributeEventListener(eventNames().keyupEvent); 288 } 289 setOnkeyup(PassRefPtr<EventListener> eventListener)290 void SVGElementInstance::setOnkeyup(PassRefPtr<EventListener> eventListener) 291 { 292 correspondingElement()->setAttributeEventListener(eventNames().keyupEvent, eventListener); 293 } 294 onload() const295 EventListener* SVGElementInstance::onload() const 296 { 297 return correspondingElement()->getAttributeEventListener(eventNames().loadEvent); 298 } 299 setOnload(PassRefPtr<EventListener> eventListener)300 void SVGElementInstance::setOnload(PassRefPtr<EventListener> eventListener) 301 { 302 correspondingElement()->setAttributeEventListener(eventNames().loadEvent, eventListener); 303 } 304 onmousedown() const305 EventListener* SVGElementInstance::onmousedown() const 306 { 307 return correspondingElement()->getAttributeEventListener(eventNames().mousedownEvent); 308 } 309 setOnmousedown(PassRefPtr<EventListener> eventListener)310 void SVGElementInstance::setOnmousedown(PassRefPtr<EventListener> eventListener) 311 { 312 correspondingElement()->setAttributeEventListener(eventNames().mousedownEvent, eventListener); 313 } 314 onmousemove() const315 EventListener* SVGElementInstance::onmousemove() const 316 { 317 return correspondingElement()->getAttributeEventListener(eventNames().mousemoveEvent); 318 } 319 setOnmousemove(PassRefPtr<EventListener> eventListener)320 void SVGElementInstance::setOnmousemove(PassRefPtr<EventListener> eventListener) 321 { 322 correspondingElement()->setAttributeEventListener(eventNames().mousemoveEvent, eventListener); 323 } 324 onmouseout() const325 EventListener* SVGElementInstance::onmouseout() const 326 { 327 return correspondingElement()->getAttributeEventListener(eventNames().mouseoutEvent); 328 } 329 setOnmouseout(PassRefPtr<EventListener> eventListener)330 void SVGElementInstance::setOnmouseout(PassRefPtr<EventListener> eventListener) 331 { 332 correspondingElement()->setAttributeEventListener(eventNames().mouseoutEvent, eventListener); 333 } 334 onmouseover() const335 EventListener* SVGElementInstance::onmouseover() const 336 { 337 return correspondingElement()->getAttributeEventListener(eventNames().mouseoverEvent); 338 } 339 setOnmouseover(PassRefPtr<EventListener> eventListener)340 void SVGElementInstance::setOnmouseover(PassRefPtr<EventListener> eventListener) 341 { 342 correspondingElement()->setAttributeEventListener(eventNames().mouseoverEvent, eventListener); 343 } 344 onmouseup() const345 EventListener* SVGElementInstance::onmouseup() const 346 { 347 return correspondingElement()->getAttributeEventListener(eventNames().mouseupEvent); 348 } 349 setOnmouseup(PassRefPtr<EventListener> eventListener)350 void SVGElementInstance::setOnmouseup(PassRefPtr<EventListener> eventListener) 351 { 352 correspondingElement()->setAttributeEventListener(eventNames().mouseupEvent, eventListener); 353 } 354 onmousewheel() const355 EventListener* SVGElementInstance::onmousewheel() const 356 { 357 return correspondingElement()->getAttributeEventListener(eventNames().mousewheelEvent); 358 } 359 setOnmousewheel(PassRefPtr<EventListener> eventListener)360 void SVGElementInstance::setOnmousewheel(PassRefPtr<EventListener> eventListener) 361 { 362 correspondingElement()->setAttributeEventListener(eventNames().mousewheelEvent, eventListener); 363 } 364 onbeforecut() const365 EventListener* SVGElementInstance::onbeforecut() const 366 { 367 return correspondingElement()->getAttributeEventListener(eventNames().beforecutEvent); 368 } 369 setOnbeforecut(PassRefPtr<EventListener> eventListener)370 void SVGElementInstance::setOnbeforecut(PassRefPtr<EventListener> eventListener) 371 { 372 correspondingElement()->setAttributeEventListener(eventNames().beforecutEvent, eventListener); 373 } 374 oncut() const375 EventListener* SVGElementInstance::oncut() const 376 { 377 return correspondingElement()->getAttributeEventListener(eventNames().cutEvent); 378 } 379 setOncut(PassRefPtr<EventListener> eventListener)380 void SVGElementInstance::setOncut(PassRefPtr<EventListener> eventListener) 381 { 382 correspondingElement()->setAttributeEventListener(eventNames().cutEvent, eventListener); 383 } 384 onbeforecopy() const385 EventListener* SVGElementInstance::onbeforecopy() const 386 { 387 return correspondingElement()->getAttributeEventListener(eventNames().beforecopyEvent); 388 } 389 setOnbeforecopy(PassRefPtr<EventListener> eventListener)390 void SVGElementInstance::setOnbeforecopy(PassRefPtr<EventListener> eventListener) 391 { 392 correspondingElement()->setAttributeEventListener(eventNames().beforecopyEvent, eventListener); 393 } 394 oncopy() const395 EventListener* SVGElementInstance::oncopy() const 396 { 397 return correspondingElement()->getAttributeEventListener(eventNames().copyEvent); 398 } 399 setOncopy(PassRefPtr<EventListener> eventListener)400 void SVGElementInstance::setOncopy(PassRefPtr<EventListener> eventListener) 401 { 402 correspondingElement()->setAttributeEventListener(eventNames().copyEvent, eventListener); 403 } 404 onbeforepaste() const405 EventListener* SVGElementInstance::onbeforepaste() const 406 { 407 return correspondingElement()->getAttributeEventListener(eventNames().beforepasteEvent); 408 } 409 setOnbeforepaste(PassRefPtr<EventListener> eventListener)410 void SVGElementInstance::setOnbeforepaste(PassRefPtr<EventListener> eventListener) 411 { 412 correspondingElement()->setAttributeEventListener(eventNames().beforepasteEvent, eventListener); 413 } 414 onpaste() const415 EventListener* SVGElementInstance::onpaste() const 416 { 417 return correspondingElement()->getAttributeEventListener(eventNames().pasteEvent); 418 } 419 setOnpaste(PassRefPtr<EventListener> eventListener)420 void SVGElementInstance::setOnpaste(PassRefPtr<EventListener> eventListener) 421 { 422 correspondingElement()->setAttributeEventListener(eventNames().pasteEvent, eventListener); 423 } 424 ondragenter() const425 EventListener* SVGElementInstance::ondragenter() const 426 { 427 return correspondingElement()->getAttributeEventListener(eventNames().dragenterEvent); 428 } 429 setOndragenter(PassRefPtr<EventListener> eventListener)430 void SVGElementInstance::setOndragenter(PassRefPtr<EventListener> eventListener) 431 { 432 correspondingElement()->setAttributeEventListener(eventNames().dragenterEvent, eventListener); 433 } 434 ondragover() const435 EventListener* SVGElementInstance::ondragover() const 436 { 437 return correspondingElement()->getAttributeEventListener(eventNames().dragoverEvent); 438 } 439 setOndragover(PassRefPtr<EventListener> eventListener)440 void SVGElementInstance::setOndragover(PassRefPtr<EventListener> eventListener) 441 { 442 correspondingElement()->setAttributeEventListener(eventNames().dragoverEvent, eventListener); 443 } 444 ondragleave() const445 EventListener* SVGElementInstance::ondragleave() const 446 { 447 return correspondingElement()->getAttributeEventListener(eventNames().dragleaveEvent); 448 } 449 setOndragleave(PassRefPtr<EventListener> eventListener)450 void SVGElementInstance::setOndragleave(PassRefPtr<EventListener> eventListener) 451 { 452 correspondingElement()->setAttributeEventListener(eventNames().dragleaveEvent, eventListener); 453 } 454 ondrop() const455 EventListener* SVGElementInstance::ondrop() const 456 { 457 return correspondingElement()->getAttributeEventListener(eventNames().dropEvent); 458 } 459 setOndrop(PassRefPtr<EventListener> eventListener)460 void SVGElementInstance::setOndrop(PassRefPtr<EventListener> eventListener) 461 { 462 correspondingElement()->setAttributeEventListener(eventNames().dropEvent, eventListener); 463 } 464 ondragstart() const465 EventListener* SVGElementInstance::ondragstart() const 466 { 467 return correspondingElement()->getAttributeEventListener(eventNames().dragstartEvent); 468 } 469 setOndragstart(PassRefPtr<EventListener> eventListener)470 void SVGElementInstance::setOndragstart(PassRefPtr<EventListener> eventListener) 471 { 472 correspondingElement()->setAttributeEventListener(eventNames().dragstartEvent, eventListener); 473 } 474 ondrag() const475 EventListener* SVGElementInstance::ondrag() const 476 { 477 return correspondingElement()->getAttributeEventListener(eventNames().dragEvent); 478 } 479 setOndrag(PassRefPtr<EventListener> eventListener)480 void SVGElementInstance::setOndrag(PassRefPtr<EventListener> eventListener) 481 { 482 correspondingElement()->setAttributeEventListener(eventNames().dragEvent, eventListener); 483 } 484 ondragend() const485 EventListener* SVGElementInstance::ondragend() const 486 { 487 return correspondingElement()->getAttributeEventListener(eventNames().dragendEvent); 488 } 489 setOndragend(PassRefPtr<EventListener> eventListener)490 void SVGElementInstance::setOndragend(PassRefPtr<EventListener> eventListener) 491 { 492 correspondingElement()->setAttributeEventListener(eventNames().dragendEvent, eventListener); 493 } 494 onreset() const495 EventListener* SVGElementInstance::onreset() const 496 { 497 return correspondingElement()->getAttributeEventListener(eventNames().resetEvent); 498 } 499 setOnreset(PassRefPtr<EventListener> eventListener)500 void SVGElementInstance::setOnreset(PassRefPtr<EventListener> eventListener) 501 { 502 correspondingElement()->setAttributeEventListener(eventNames().resetEvent, eventListener); 503 } 504 onresize() const505 EventListener* SVGElementInstance::onresize() const 506 { 507 return correspondingElement()->getAttributeEventListener(eventNames().resizeEvent); 508 } 509 setOnresize(PassRefPtr<EventListener> eventListener)510 void SVGElementInstance::setOnresize(PassRefPtr<EventListener> eventListener) 511 { 512 correspondingElement()->setAttributeEventListener(eventNames().resizeEvent, eventListener); 513 } 514 onscroll() const515 EventListener* SVGElementInstance::onscroll() const 516 { 517 return correspondingElement()->getAttributeEventListener(eventNames().scrollEvent); 518 } 519 setOnscroll(PassRefPtr<EventListener> eventListener)520 void SVGElementInstance::setOnscroll(PassRefPtr<EventListener> eventListener) 521 { 522 correspondingElement()->setAttributeEventListener(eventNames().scrollEvent, eventListener); 523 } 524 onsearch() const525 EventListener* SVGElementInstance::onsearch() const 526 { 527 return correspondingElement()->getAttributeEventListener(eventNames().searchEvent); 528 } 529 setOnsearch(PassRefPtr<EventListener> eventListener)530 void SVGElementInstance::setOnsearch(PassRefPtr<EventListener> eventListener) 531 { 532 correspondingElement()->setAttributeEventListener(eventNames().searchEvent, eventListener); 533 } 534 onselect() const535 EventListener* SVGElementInstance::onselect() const 536 { 537 return correspondingElement()->getAttributeEventListener(eventNames().selectEvent); 538 } 539 setOnselect(PassRefPtr<EventListener> eventListener)540 void SVGElementInstance::setOnselect(PassRefPtr<EventListener> eventListener) 541 { 542 correspondingElement()->setAttributeEventListener(eventNames().selectEvent, eventListener); 543 } 544 onselectstart() const545 EventListener* SVGElementInstance::onselectstart() const 546 { 547 return correspondingElement()->getAttributeEventListener(eventNames().selectstartEvent); 548 } 549 setOnselectstart(PassRefPtr<EventListener> eventListener)550 void SVGElementInstance::setOnselectstart(PassRefPtr<EventListener> eventListener) 551 { 552 correspondingElement()->setAttributeEventListener(eventNames().selectstartEvent, eventListener); 553 } 554 onsubmit() const555 EventListener* SVGElementInstance::onsubmit() const 556 { 557 return correspondingElement()->getAttributeEventListener(eventNames().submitEvent); 558 } 559 setOnsubmit(PassRefPtr<EventListener> eventListener)560 void SVGElementInstance::setOnsubmit(PassRefPtr<EventListener> eventListener) 561 { 562 correspondingElement()->setAttributeEventListener(eventNames().submitEvent, eventListener); 563 } 564 onunload() const565 EventListener* SVGElementInstance::onunload() const 566 { 567 return correspondingElement()->getAttributeEventListener(eventNames().unloadEvent); 568 } 569 setOnunload(PassRefPtr<EventListener> eventListener)570 void SVGElementInstance::setOnunload(PassRefPtr<EventListener> eventListener) 571 { 572 correspondingElement()->setAttributeEventListener(eventNames().unloadEvent, eventListener); 573 } 574 575 } 576 577 #endif // ENABLE(SVG) 578