• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
50 struct DRTEventQueue {
51     QEvent* m_event;
52     int m_delay;
53 };
54 
55 static DRTEventQueue eventQueue[1024];
56 static unsigned endOfQueue;
57 static unsigned startOfQueue;
58 
EventSender(QWebPage * parent)59 EventSender::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 
mouseDown(int button)77 void 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 
mouseUp(int button)129 void 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 
mouseMoveTo(int x,int y)166 void 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
mouseScrollBy(int x,int y)184 void EventSender::mouseScrollBy(int x, int y)
185 {
186     continuousMouseScrollBy((x*120), (y*120));
187 }
188 
continuousMouseScrollBy(int x,int y)189 void 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 
leapForward(int ms)216 void EventSender::leapForward(int ms)
217 {
218     eventQueue[endOfQueue].m_delay = ms;
219     //qDebug() << "EventSender::leapForward" << ms;
220 }
221 
keyDown(const QString & string,const QStringList & modifiers,unsigned int location)222 void 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 
contextClick()366 QStringList 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 
scheduleAsynchronousClick()387 void 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 
addTouchPoint(int x,int y)395 void 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 
updateTouchPoint(int index,int x,int y)408 void 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 
setTouchModifier(const QString & modifier,bool enable)418 void 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 
touchStart()436 void EventSender::touchStart()
437 {
438     if (!m_touchActive) {
439         sendTouchEvent(QEvent::TouchBegin);
440         m_touchActive = true;
441     } else
442         sendTouchEvent(QEvent::TouchUpdate);
443 }
444 
touchMove()445 void EventSender::touchMove()
446 {
447     sendTouchEvent(QEvent::TouchUpdate);
448 }
449 
touchEnd()450 void 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 
clearTouchPoints()461 void EventSender::clearTouchPoints()
462 {
463     m_touchPoints.clear();
464     m_touchModifiers = Qt::KeyboardModifiers();
465     m_touchActive = false;
466 }
467 
releaseTouchPoint(int index)468 void 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 
sendTouchEvent(QEvent::Type type)476 void 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 
zoomPageIn()492 void EventSender::zoomPageIn()
493 {
494     if (QWebFrame* frame = m_page->mainFrame())
495         frame->setZoomFactor(frame->zoomFactor() * ZOOM_STEP);
496 }
497 
zoomPageOut()498 void EventSender::zoomPageOut()
499 {
500     if (QWebFrame* frame = m_page->mainFrame())
501         frame->setZoomFactor(frame->zoomFactor() / ZOOM_STEP);
502 }
503 
textZoomIn()504 void EventSender::textZoomIn()
505 {
506     if (QWebFrame* frame = m_page->mainFrame())
507         frame->setTextSizeMultiplier(frame->textSizeMultiplier() * ZOOM_STEP);
508 }
509 
textZoomOut()510 void EventSender::textZoomOut()
511 {
512     if (QWebFrame* frame = m_page->mainFrame())
513         frame->setTextSizeMultiplier(frame->textSizeMultiplier() / ZOOM_STEP);
514 }
515 
frameUnderMouse() const516 QWebFrame* EventSender::frameUnderMouse() const
517 {
518     QWebFrame* frame = m_page->mainFrame();
519 
520 redo:
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 
sendOrQueueEvent(QEvent * event)533 void 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 
replaySavedEvents(bool flush)550 void 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 
eventFilter(QObject * watched,QEvent * event)581 bool 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 
timerEvent(QTimerEvent * ev)609 void EventSender::timerEvent(QTimerEvent* ev)
610 {
611     m_clickTimer.stop();
612 }
613 
createGraphicsSceneMouseEvent(QEvent::Type type,const QPoint & pos,const QPoint & screenPos,Qt::MouseButton button,Qt::MouseButtons buttons,Qt::KeyboardModifiers modifiers)614 QGraphicsSceneMouseEvent* 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 
createGraphicsSceneWheelEvent(QEvent::Type type,const QPoint & pos,const QPoint & screenPos,int delta,Qt::KeyboardModifiers modifiers,Qt::Orientation orientation)627 QGraphicsSceneWheelEvent* 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 
sendEvent(QObject * receiver,QEvent * event)640 void 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 
postEvent(QObject * receiver,QEvent * event)648 void 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