1/* 2 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29#include "config.h" 30#include "EventSenderQt.h" 31 32#include <QGraphicsSceneMouseEvent> 33#include <QtTest/QtTest> 34 35#define KEYCODE_DEL 127 36#define KEYCODE_BACKSPACE 8 37#define KEYCODE_LEFTARROW 0xf702 38#define KEYCODE_RIGHTARROW 0xf703 39#define KEYCODE_UPARROW 0xf700 40#define KEYCODE_DOWNARROW 0xf701 41 42// Ports like Gtk and Windows expose a different approach for their zooming 43// API if compared to Qt: they have specific methods for zooming in and out, 44// as well as a settable zoom factor, while Qt has only a 'setZoomValue' method. 45// Hence Qt DRT adopts a fixed zoom-factor (1.2) for compatibility. 46#define ZOOM_STEP 1.2 47 48#define DRT_MESSAGE_DONE (QEvent::User + 1) 49 50struct DRTEventQueue { 51 QEvent* m_event; 52 int m_delay; 53}; 54 55static DRTEventQueue eventQueue[1024]; 56static unsigned endOfQueue; 57static unsigned startOfQueue; 58 59EventSender::EventSender(QWebPage* parent) 60 : QObject(parent) 61{ 62 m_page = parent; 63 m_mouseButtonPressed = false; 64 m_drag = false; 65 memset(eventQueue, 0, sizeof(eventQueue)); 66 endOfQueue = 0; 67 startOfQueue = 0; 68 m_eventLoop = 0; 69 m_currentButton = 0; 70 resetClickCount(); 71 m_page->view()->installEventFilter(this); 72 // So that we can match Scrollbar::pixelsPerLineStep() in WheelEventQt.cpp and 73 // pass fast/events/platform-wheelevent-in-scrolling-div.html 74 QApplication::setWheelScrollLines(2); 75} 76 77void EventSender::mouseDown(int button) 78{ 79 Qt::MouseButton mouseButton; 80 switch (button) { 81 case 0: 82 mouseButton = Qt::LeftButton; 83 break; 84 case 1: 85 mouseButton = Qt::MidButton; 86 break; 87 case 2: 88 mouseButton = Qt::RightButton; 89 break; 90 case 3: 91 // fast/events/mouse-click-events expects the 4th button to be treated as the middle button 92 mouseButton = Qt::MidButton; 93 break; 94 default: 95 mouseButton = Qt::LeftButton; 96 break; 97 } 98 99 // only consider a click to count, an event originated by the 100 // same previous button and at the same position. 101 if (m_currentButton == button 102 && m_mousePos == m_clickPos 103 && m_clickTimer.isActive()) 104 m_clickCount++; 105 else 106 m_clickCount = 1; 107 108 m_currentButton = button; 109 m_clickPos = m_mousePos; 110 m_mouseButtons |= mouseButton; 111 112// qDebug() << "EventSender::mouseDown" << frame; 113 QEvent* event; 114 if (isGraphicsBased()) { 115 event = createGraphicsSceneMouseEvent((m_clickCount == 2) ? 116 QEvent::GraphicsSceneMouseDoubleClick : QEvent::GraphicsSceneMousePress, 117 m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier); 118 } else { 119 event = new QMouseEvent((m_clickCount == 2) ? QEvent::MouseButtonDblClick : 120 QEvent::MouseButtonPress, m_mousePos, m_mousePos, 121 mouseButton, m_mouseButtons, Qt::NoModifier); 122 } 123 124 sendOrQueueEvent(event); 125 126 m_clickTimer.start(QApplication::doubleClickInterval(), this); 127} 128 129void EventSender::mouseUp(int button) 130{ 131 Qt::MouseButton mouseButton; 132 switch (button) { 133 case 0: 134 mouseButton = Qt::LeftButton; 135 break; 136 case 1: 137 mouseButton = Qt::MidButton; 138 break; 139 case 2: 140 mouseButton = Qt::RightButton; 141 break; 142 case 3: 143 // fast/events/mouse-click-events expects the 4th button to be treated as the middle button 144 mouseButton = Qt::MidButton; 145 break; 146 default: 147 mouseButton = Qt::LeftButton; 148 break; 149 } 150 151 m_mouseButtons &= ~mouseButton; 152 153// qDebug() << "EventSender::mouseUp" << frame; 154 QEvent* event; 155 if (isGraphicsBased()) { 156 event = createGraphicsSceneMouseEvent(QEvent::GraphicsSceneMouseRelease, 157 m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier); 158 } else { 159 event = new QMouseEvent(QEvent::MouseButtonRelease, 160 m_mousePos, m_mousePos, mouseButton, m_mouseButtons, Qt::NoModifier); 161 } 162 163 sendOrQueueEvent(event); 164} 165 166void EventSender::mouseMoveTo(int x, int y) 167{ 168// qDebug() << "EventSender::mouseMoveTo" << x << y; 169 m_mousePos = QPoint(x, y); 170 171 QEvent* event; 172 if (isGraphicsBased()) { 173 event = createGraphicsSceneMouseEvent(QEvent::GraphicsSceneMouseMove, 174 m_mousePos, m_mousePos, Qt::NoButton, m_mouseButtons, Qt::NoModifier); 175 } else { 176 event = new QMouseEvent(QEvent::MouseMove, 177 m_mousePos, m_mousePos, Qt::NoButton, m_mouseButtons, Qt::NoModifier); 178 } 179 180 sendOrQueueEvent(event); 181} 182 183#ifndef QT_NO_WHEELEVENT 184void EventSender::mouseScrollBy(int x, int y) 185{ 186 continuousMouseScrollBy((x*120), (y*120)); 187} 188 189void EventSender::continuousMouseScrollBy(int x, int y) 190{ 191 // continuousMouseScrollBy() mimics devices that send fine-grained scroll events where the 'delta' specified is not the usual 192 // multiple of 120. See http://doc.qt.nokia.com/4.6/qwheelevent.html#delta for a good explanation of this. 193 if (x) { 194 QEvent* event; 195 if (isGraphicsBased()) { 196 event = createGraphicsSceneWheelEvent(QEvent::GraphicsSceneWheel, 197 m_mousePos, m_mousePos, x, Qt::NoModifier, Qt::Horizontal); 198 } else 199 event = new QWheelEvent(m_mousePos, m_mousePos, x, m_mouseButtons, Qt::NoModifier, Qt::Horizontal); 200 201 sendOrQueueEvent(event); 202 } 203 if (y) { 204 QEvent* event; 205 if (isGraphicsBased()) { 206 event = createGraphicsSceneWheelEvent(QEvent::GraphicsSceneWheel, 207 m_mousePos, m_mousePos, y, Qt::NoModifier, Qt::Vertical); 208 } else 209 event = new QWheelEvent(m_mousePos, m_mousePos, y, m_mouseButtons, Qt::NoModifier, Qt::Vertical); 210 211 sendOrQueueEvent(event); 212 } 213} 214#endif 215 216void EventSender::leapForward(int ms) 217{ 218 eventQueue[endOfQueue].m_delay = ms; 219 //qDebug() << "EventSender::leapForward" << ms; 220} 221 222void EventSender::keyDown(const QString& string, const QStringList& modifiers, unsigned int location) 223{ 224 QString s = string; 225 Qt::KeyboardModifiers modifs = 0; 226 for (int i = 0; i < modifiers.size(); ++i) { 227 const QString& m = modifiers.at(i); 228 if (m == "ctrlKey") 229 modifs |= Qt::ControlModifier; 230 else if (m == "shiftKey") 231 modifs |= Qt::ShiftModifier; 232 else if (m == "altKey") 233 modifs |= Qt::AltModifier; 234 else if (m == "metaKey") 235 modifs |= Qt::MetaModifier; 236 } 237 if (location == 3) 238 modifs |= Qt::KeypadModifier; 239 int code = 0; 240 if (string.length() == 1) { 241 code = string.unicode()->unicode(); 242 //qDebug() << ">>>>>>>>> keyDown" << code << (char)code; 243 // map special keycodes used by the tests to something that works for Qt/X11 244 if (code == '\r') { 245 code = Qt::Key_Return; 246 } else if (code == '\t') { 247 code = Qt::Key_Tab; 248 if (modifs == Qt::ShiftModifier) 249 code = Qt::Key_Backtab; 250 s = QString(); 251 } else if (code == KEYCODE_DEL || code == KEYCODE_BACKSPACE) { 252 code = Qt::Key_Backspace; 253 if (modifs == Qt::AltModifier) 254 modifs = Qt::ControlModifier; 255 s = QString(); 256 } else if (code == 'o' && modifs == Qt::ControlModifier) { 257 // Mimic the emacs ctrl-o binding on Mac by inserting a paragraph 258 // separator and then putting the cursor back to its original 259 // position. Allows us to pass emacs-ctrl-o.html 260 s = QLatin1String("\n"); 261 code = '\n'; 262 modifs = 0; 263 QKeyEvent event(QEvent::KeyPress, code, modifs, s); 264 sendEvent(m_page, &event); 265 QKeyEvent event2(QEvent::KeyRelease, code, modifs, s); 266 sendEvent(m_page, &event2); 267 s = QString(); 268 code = Qt::Key_Left; 269 } else if (code == 'y' && modifs == Qt::ControlModifier) { 270 s = QLatin1String("c"); 271 code = 'c'; 272 } else if (code == 'k' && modifs == Qt::ControlModifier) { 273 s = QLatin1String("x"); 274 code = 'x'; 275 } else if (code == 'a' && modifs == Qt::ControlModifier) { 276 s = QString(); 277 code = Qt::Key_Home; 278 modifs = 0; 279 } else if (code == KEYCODE_LEFTARROW) { 280 s = QString(); 281 code = Qt::Key_Left; 282 if (modifs & Qt::MetaModifier) { 283 code = Qt::Key_Home; 284 modifs &= ~Qt::MetaModifier; 285 } 286 } else if (code == KEYCODE_RIGHTARROW) { 287 s = QString(); 288 code = Qt::Key_Right; 289 if (modifs & Qt::MetaModifier) { 290 code = Qt::Key_End; 291 modifs &= ~Qt::MetaModifier; 292 } 293 } else if (code == KEYCODE_UPARROW) { 294 s = QString(); 295 code = Qt::Key_Up; 296 if (modifs & Qt::MetaModifier) { 297 code = Qt::Key_PageUp; 298 modifs &= ~Qt::MetaModifier; 299 } 300 } else if (code == KEYCODE_DOWNARROW) { 301 s = QString(); 302 code = Qt::Key_Down; 303 if (modifs & Qt::MetaModifier) { 304 code = Qt::Key_PageDown; 305 modifs &= ~Qt::MetaModifier; 306 } 307 } else if (code == 'a' && modifs == Qt::ControlModifier) { 308 s = QString(); 309 code = Qt::Key_Home; 310 modifs = 0; 311 } else 312 code = string.unicode()->toUpper().unicode(); 313 } else { 314 //qDebug() << ">>>>>>>>> keyDown" << string; 315 316 if (string.startsWith(QLatin1Char('F')) && string.count() <= 3) { 317 s = s.mid(1); 318 int functionKey = s.toInt(); 319 Q_ASSERT(functionKey >= 1 && functionKey <= 35); 320 code = Qt::Key_F1 + (functionKey - 1); 321 // map special keycode strings used by the tests to something that works for Qt/X11 322 } else if (string == QLatin1String("leftArrow")) { 323 s = QString(); 324 code = Qt::Key_Left; 325 } else if (string == QLatin1String("rightArrow")) { 326 s = QString(); 327 code = Qt::Key_Right; 328 } else if (string == QLatin1String("upArrow")) { 329 s = QString(); 330 code = Qt::Key_Up; 331 } else if (string == QLatin1String("downArrow")) { 332 s = QString(); 333 code = Qt::Key_Down; 334 } else if (string == QLatin1String("pageUp")) { 335 s = QString(); 336 code = Qt::Key_PageUp; 337 } else if (string == QLatin1String("pageDown")) { 338 s = QString(); 339 code = Qt::Key_PageDown; 340 } else if (string == QLatin1String("home")) { 341 s = QString(); 342 code = Qt::Key_Home; 343 } else if (string == QLatin1String("end")) { 344 s = QString(); 345 code = Qt::Key_End; 346 } else if (string == QLatin1String("insert")) { 347 s = QString(); 348 code = Qt::Key_Insert; 349 } else if (string == QLatin1String("delete")) { 350 s = QString(); 351 code = Qt::Key_Delete; 352 } else if (string == QLatin1String("printScreen")) { 353 s = QString(); 354 code = Qt::Key_Print; 355 } else if (string == QLatin1String("menu")) { 356 s = QString(); 357 code = Qt::Key_Menu; 358 } 359 } 360 QKeyEvent event(QEvent::KeyPress, code, modifs, s); 361 sendEvent(m_page, &event); 362 QKeyEvent event2(QEvent::KeyRelease, code, modifs, s); 363 sendEvent(m_page, &event2); 364} 365 366QStringList EventSender::contextClick() 367{ 368 QMouseEvent event(QEvent::MouseButtonPress, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier); 369 sendEvent(m_page, &event); 370 QMouseEvent event2(QEvent::MouseButtonRelease, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier); 371 sendEvent(m_page, &event2); 372 373 if (isGraphicsBased()) { 374 QGraphicsSceneContextMenuEvent ctxEvent(QEvent::GraphicsSceneContextMenu); 375 ctxEvent.setReason(QGraphicsSceneContextMenuEvent::Mouse); 376 ctxEvent.setPos(m_mousePos); 377 WebCore::WebViewGraphicsBased* view = qobject_cast<WebCore::WebViewGraphicsBased*>(m_page->view()); 378 if (view) 379 sendEvent(view->graphicsView(), &ctxEvent); 380 } else { 381 QContextMenuEvent ctxEvent(QContextMenuEvent::Mouse, m_mousePos); 382 sendEvent(m_page->view(), &ctxEvent); 383 } 384 return DumpRenderTreeSupportQt::contextMenu(m_page); 385} 386 387void EventSender::scheduleAsynchronousClick() 388{ 389 QMouseEvent* event = new QMouseEvent(QEvent::MouseButtonPress, m_mousePos, Qt::LeftButton, Qt::RightButton, Qt::NoModifier); 390 postEvent(m_page, event); 391 QMouseEvent* event2 = new QMouseEvent(QEvent::MouseButtonRelease, m_mousePos, Qt::LeftButton, Qt::RightButton, Qt::NoModifier); 392 postEvent(m_page, event2); 393} 394 395void EventSender::addTouchPoint(int x, int y) 396{ 397 // Use index to refer to the position in the vector that this touch 398 // is stored. We then create a unique id for the touch that will be 399 // passed into WebCore. 400 int index = m_touchPoints.count(); 401 int id = m_touchPoints.isEmpty() ? 0 : m_touchPoints.last().id() + 1; 402 QTouchEvent::TouchPoint point(id); 403 m_touchPoints.append(point); 404 updateTouchPoint(index, x, y); 405 m_touchPoints[index].setState(Qt::TouchPointPressed); 406} 407 408void EventSender::updateTouchPoint(int index, int x, int y) 409{ 410 if (index < 0 || index >= m_touchPoints.count()) 411 return; 412 413 QTouchEvent::TouchPoint &p = m_touchPoints[index]; 414 p.setPos(QPointF(x, y)); 415 p.setState(Qt::TouchPointMoved); 416} 417 418void EventSender::setTouchModifier(const QString &modifier, bool enable) 419{ 420 Qt::KeyboardModifier mod = Qt::NoModifier; 421 if (!modifier.compare(QLatin1String("shift"), Qt::CaseInsensitive)) 422 mod = Qt::ShiftModifier; 423 else if (!modifier.compare(QLatin1String("alt"), Qt::CaseInsensitive)) 424 mod = Qt::AltModifier; 425 else if (!modifier.compare(QLatin1String("meta"), Qt::CaseInsensitive)) 426 mod = Qt::MetaModifier; 427 else if (!modifier.compare(QLatin1String("ctrl"), Qt::CaseInsensitive)) 428 mod = Qt::ControlModifier; 429 430 if (enable) 431 m_touchModifiers |= mod; 432 else 433 m_touchModifiers &= ~mod; 434} 435 436void EventSender::touchStart() 437{ 438 if (!m_touchActive) { 439 sendTouchEvent(QEvent::TouchBegin); 440 m_touchActive = true; 441 } else 442 sendTouchEvent(QEvent::TouchUpdate); 443} 444 445void EventSender::touchMove() 446{ 447 sendTouchEvent(QEvent::TouchUpdate); 448} 449 450void EventSender::touchEnd() 451{ 452 for (int i = 0; i < m_touchPoints.count(); ++i) 453 if (m_touchPoints[i].state() != Qt::TouchPointReleased) { 454 sendTouchEvent(QEvent::TouchUpdate); 455 return; 456 } 457 sendTouchEvent(QEvent::TouchEnd); 458 m_touchActive = false; 459} 460 461void EventSender::clearTouchPoints() 462{ 463 m_touchPoints.clear(); 464 m_touchModifiers = Qt::KeyboardModifiers(); 465 m_touchActive = false; 466} 467 468void EventSender::releaseTouchPoint(int index) 469{ 470 if (index < 0 || index >= m_touchPoints.count()) 471 return; 472 473 m_touchPoints[index].setState(Qt::TouchPointReleased); 474} 475 476void EventSender::sendTouchEvent(QEvent::Type type) 477{ 478 QTouchEvent event(type, QTouchEvent::TouchScreen, m_touchModifiers); 479 event.setTouchPoints(m_touchPoints); 480 sendEvent(m_page, &event); 481 QList<QTouchEvent::TouchPoint>::Iterator it = m_touchPoints.begin(); 482 while (it != m_touchPoints.end()) { 483 if (it->state() == Qt::TouchPointReleased) 484 it = m_touchPoints.erase(it); 485 else { 486 it->setState(Qt::TouchPointStationary); 487 ++it; 488 } 489 } 490} 491 492void EventSender::zoomPageIn() 493{ 494 if (QWebFrame* frame = m_page->mainFrame()) 495 frame->setZoomFactor(frame->zoomFactor() * ZOOM_STEP); 496} 497 498void EventSender::zoomPageOut() 499{ 500 if (QWebFrame* frame = m_page->mainFrame()) 501 frame->setZoomFactor(frame->zoomFactor() / ZOOM_STEP); 502} 503 504void EventSender::textZoomIn() 505{ 506 if (QWebFrame* frame = m_page->mainFrame()) 507 frame->setTextSizeMultiplier(frame->textSizeMultiplier() * ZOOM_STEP); 508} 509 510void EventSender::textZoomOut() 511{ 512 if (QWebFrame* frame = m_page->mainFrame()) 513 frame->setTextSizeMultiplier(frame->textSizeMultiplier() / ZOOM_STEP); 514} 515 516QWebFrame* EventSender::frameUnderMouse() const 517{ 518 QWebFrame* frame = m_page->mainFrame(); 519 520redo: 521 QList<QWebFrame*> children = frame->childFrames(); 522 for (int i = 0; i < children.size(); ++i) { 523 if (children.at(i)->geometry().contains(m_mousePos)) { 524 frame = children.at(i); 525 goto redo; 526 } 527 } 528 if (frame->geometry().contains(m_mousePos)) 529 return frame; 530 return 0; 531} 532 533void EventSender::sendOrQueueEvent(QEvent* event) 534{ 535 // Mouse move events are queued if 536 // 1. A previous event was queued. 537 // 2. A delay was set-up by leapForward(). 538 // 3. A call to mouseMoveTo while the mouse button is pressed could initiate a drag operation, and that does not return until mouseUp is processed. 539 // To be safe and avoid a deadlock, this event is queued. 540 if (endOfQueue == startOfQueue && !eventQueue[endOfQueue].m_delay && (!(m_mouseButtonPressed && (m_eventLoop && event->type() == QEvent::MouseButtonRelease)))) { 541 sendEvent(m_page->view(), event); 542 delete event; 543 return; 544 } 545 eventQueue[endOfQueue++].m_event = event; 546 eventQueue[endOfQueue].m_delay = 0; 547 replaySavedEvents(event->type() != QEvent::MouseMove); 548} 549 550void EventSender::replaySavedEvents(bool flush) 551{ 552 if (startOfQueue < endOfQueue) { 553 // First send all the events that are ready to be sent 554 while (!eventQueue[startOfQueue].m_delay && startOfQueue < endOfQueue) { 555 QEvent* ev = eventQueue[startOfQueue++].m_event; 556 postEvent(m_page->view(), ev); 557 } 558 if (startOfQueue == endOfQueue) { 559 // Reset the queue 560 startOfQueue = 0; 561 endOfQueue = 0; 562 } else { 563 QTest::qWait(eventQueue[startOfQueue].m_delay); 564 eventQueue[startOfQueue].m_delay = 0; 565 } 566 } 567 if (!flush) 568 return; 569 570 // Send a marker event, it will tell us when it is safe to exit the new event loop 571 QEvent* drtEvent = new QEvent((QEvent::Type)DRT_MESSAGE_DONE); 572 QApplication::postEvent(m_page->view(), drtEvent); 573 574 // Start an event loop for async handling of Drag & Drop 575 m_eventLoop = new QEventLoop; 576 m_eventLoop->exec(); 577 delete m_eventLoop; 578 m_eventLoop = 0; 579} 580 581bool EventSender::eventFilter(QObject* watched, QEvent* event) 582{ 583 if (watched != m_page->view()) 584 return false; 585 switch (event->type()) { 586 case QEvent::Leave: 587 return true; 588 case QEvent::MouseButtonPress: 589 case QEvent::GraphicsSceneMousePress: 590 m_mouseButtonPressed = true; 591 break; 592 case QEvent::MouseMove: 593 case QEvent::GraphicsSceneMouseMove: 594 if (m_mouseButtonPressed) 595 m_drag = true; 596 break; 597 case QEvent::MouseButtonRelease: 598 case QEvent::GraphicsSceneMouseRelease: 599 m_mouseButtonPressed = false; 600 m_drag = false; 601 break; 602 case DRT_MESSAGE_DONE: 603 m_eventLoop->exit(); 604 return true; 605 } 606 return false; 607} 608 609void EventSender::timerEvent(QTimerEvent* ev) 610{ 611 m_clickTimer.stop(); 612} 613 614QGraphicsSceneMouseEvent* EventSender::createGraphicsSceneMouseEvent(QEvent::Type type, const QPoint& pos, const QPoint& screenPos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) 615{ 616 QGraphicsSceneMouseEvent* event; 617 event = new QGraphicsSceneMouseEvent(type); 618 event->setPos(pos); 619 event->setScreenPos(screenPos); 620 event->setButton(button); 621 event->setButtons(buttons); 622 event->setModifiers(modifiers); 623 624 return event; 625} 626 627QGraphicsSceneWheelEvent* EventSender::createGraphicsSceneWheelEvent(QEvent::Type type, const QPoint& pos, const QPoint& screenPos, int delta, Qt::KeyboardModifiers modifiers, Qt::Orientation orientation) 628{ 629 QGraphicsSceneWheelEvent* event; 630 event = new QGraphicsSceneWheelEvent(type); 631 event->setPos(pos); 632 event->setScreenPos(screenPos); 633 event->setDelta(delta); 634 event->setModifiers(modifiers); 635 event->setOrientation(orientation); 636 637 return event; 638} 639 640void EventSender::sendEvent(QObject* receiver, QEvent* event) 641{ 642 if (WebCore::WebViewGraphicsBased* view = qobject_cast<WebCore::WebViewGraphicsBased*>(receiver)) 643 view->scene()->sendEvent(view->graphicsView(), event); 644 else 645 QApplication::sendEvent(receiver, event); 646} 647 648void EventSender::postEvent(QObject* receiver, QEvent* event) 649{ 650 // QGraphicsScene does not have a postEvent method, so send the event in this case 651 // and delete it after that. 652 if (WebCore::WebViewGraphicsBased* view = qobject_cast<WebCore::WebViewGraphicsBased*>(receiver)) { 653 view->scene()->sendEvent(view->graphicsView(), event); 654 delete event; 655 } else 656 QApplication::postEvent(receiver, event); // event deleted by the system 657} 658