WebKitTools/DumpRenderTree/qt/EventSenderQt.cpp
changeset 2 303757a437d3
parent 0 4f2f89ce4247
equal deleted inserted replaced
0:4f2f89ce4247 2:303757a437d3
     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 
       
    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 
       
    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 
       
   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 
       
   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
       
   184 void EventSender::mouseScrollBy(int x, int y)
       
   185 {
       
   186     continuousMouseScrollBy((x*120), (y*120));
       
   187 }
       
   188 
       
   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 
       
   216 void EventSender::leapForward(int ms)
       
   217 {
       
   218     eventQueue[endOfQueue].m_delay = ms;
       
   219     //qDebug() << "EventSender::leapForward" << ms;
       
   220 }
       
   221 
       
   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             s = QLatin1String("\n");
       
   258             code = '\n';
       
   259             modifs = 0;
       
   260         } else if (code == 'y' && modifs == Qt::ControlModifier) {
       
   261             s = QLatin1String("c");
       
   262             code = 'c';
       
   263         } else if (code == 'k' && modifs == Qt::ControlModifier) {
       
   264             s = QLatin1String("x");
       
   265             code = 'x';
       
   266         } else if (code == 'a' && modifs == Qt::ControlModifier) {
       
   267             s = QString();
       
   268             code = Qt::Key_Home;
       
   269             modifs = 0;
       
   270         } else if (code == KEYCODE_LEFTARROW) {
       
   271             s = QString();
       
   272             code = Qt::Key_Left;
       
   273             if (modifs & Qt::MetaModifier) {
       
   274                 code = Qt::Key_Home;
       
   275                 modifs &= ~Qt::MetaModifier;
       
   276             }
       
   277         } else if (code == KEYCODE_RIGHTARROW) {
       
   278             s = QString();
       
   279             code = Qt::Key_Right;
       
   280             if (modifs & Qt::MetaModifier) {
       
   281                 code = Qt::Key_End;
       
   282                 modifs &= ~Qt::MetaModifier;
       
   283             }
       
   284         } else if (code == KEYCODE_UPARROW) {
       
   285             s = QString();
       
   286             code = Qt::Key_Up;
       
   287             if (modifs & Qt::MetaModifier) {
       
   288                 code = Qt::Key_PageUp;
       
   289                 modifs &= ~Qt::MetaModifier;
       
   290             }
       
   291         } else if (code == KEYCODE_DOWNARROW) {
       
   292             s = QString();
       
   293             code = Qt::Key_Down;
       
   294             if (modifs & Qt::MetaModifier) {
       
   295                 code = Qt::Key_PageDown;
       
   296                 modifs &= ~Qt::MetaModifier;
       
   297             }
       
   298         } else if (code == 'a' && modifs == Qt::ControlModifier) {
       
   299             s = QString();
       
   300             code = Qt::Key_Home;
       
   301             modifs = 0;
       
   302         } else
       
   303             code = string.unicode()->toUpper().unicode();
       
   304     } else {
       
   305         //qDebug() << ">>>>>>>>> keyDown" << string;
       
   306 
       
   307         if (string.startsWith(QLatin1Char('F')) && string.count() <= 3) {
       
   308             s = s.mid(1);
       
   309             int functionKey = s.toInt();
       
   310             Q_ASSERT(functionKey >= 1 && functionKey <= 35);
       
   311             code = Qt::Key_F1 + (functionKey - 1);
       
   312         // map special keycode strings used by the tests to something that works for Qt/X11
       
   313         } else if (string == QLatin1String("leftArrow")) {
       
   314             s = QString();
       
   315             code = Qt::Key_Left;
       
   316         } else if (string == QLatin1String("rightArrow")) {
       
   317             s = QString();
       
   318             code = Qt::Key_Right;
       
   319         } else if (string == QLatin1String("upArrow")) {
       
   320             s = QString();
       
   321             code = Qt::Key_Up;
       
   322         } else if (string == QLatin1String("downArrow")) {
       
   323             s = QString();
       
   324             code = Qt::Key_Down;
       
   325         } else if (string == QLatin1String("pageUp")) {
       
   326             s = QString();
       
   327             code = Qt::Key_PageUp;
       
   328         } else if (string == QLatin1String("pageDown")) {
       
   329             s = QString();
       
   330             code = Qt::Key_PageDown;
       
   331         } else if (string == QLatin1String("home")) {
       
   332             s = QString();
       
   333             code = Qt::Key_Home;
       
   334         } else if (string == QLatin1String("end")) {
       
   335             s = QString();
       
   336             code = Qt::Key_End;
       
   337         } else if (string == QLatin1String("delete")) {
       
   338             s = QString();
       
   339             code = Qt::Key_Delete;
       
   340         }
       
   341     }
       
   342     QKeyEvent event(QEvent::KeyPress, code, modifs, s);
       
   343     sendEvent(m_page, &event);
       
   344     QKeyEvent event2(QEvent::KeyRelease, code, modifs, s);
       
   345     sendEvent(m_page, &event2);
       
   346 }
       
   347 
       
   348 void EventSender::contextClick()
       
   349 {
       
   350     QMouseEvent event(QEvent::MouseButtonPress, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
       
   351     sendEvent(m_page, &event);
       
   352     QMouseEvent event2(QEvent::MouseButtonRelease, m_mousePos, Qt::RightButton, Qt::RightButton, Qt::NoModifier);
       
   353     sendEvent(m_page, &event2);
       
   354 
       
   355     if (isGraphicsBased()) {
       
   356         QGraphicsSceneContextMenuEvent ctxEvent(QEvent::GraphicsSceneContextMenu);
       
   357         ctxEvent.setReason(QGraphicsSceneContextMenuEvent::Mouse);
       
   358         ctxEvent.setPos(m_mousePos);
       
   359         WebCore::WebViewGraphicsBased* view = qobject_cast<WebCore::WebViewGraphicsBased*>(m_page->view());
       
   360         if (view)
       
   361             sendEvent(view->graphicsView(), &ctxEvent);
       
   362     } else {
       
   363         QContextMenuEvent ctxEvent(QContextMenuEvent::Mouse, m_mousePos);
       
   364         sendEvent(m_page->view(), &ctxEvent);
       
   365     }
       
   366 }
       
   367 
       
   368 void EventSender::scheduleAsynchronousClick()
       
   369 {
       
   370     QMouseEvent* event = new QMouseEvent(QEvent::MouseButtonPress, m_mousePos, Qt::LeftButton, Qt::RightButton, Qt::NoModifier);
       
   371     postEvent(m_page, event);
       
   372     QMouseEvent* event2 = new QMouseEvent(QEvent::MouseButtonRelease, m_mousePos, Qt::LeftButton, Qt::RightButton, Qt::NoModifier);
       
   373     postEvent(m_page, event2);
       
   374 }
       
   375 
       
   376 void EventSender::addTouchPoint(int x, int y)
       
   377 {
       
   378 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
       
   379     // Use index to refer to the position in the vector that this touch
       
   380     // is stored. We then create a unique id for the touch that will be
       
   381     // passed into WebCore.
       
   382     int index = m_touchPoints.count();
       
   383     int id = m_touchPoints.isEmpty() ? 0 : m_touchPoints.last().id() + 1;
       
   384     QTouchEvent::TouchPoint point(id);
       
   385     m_touchPoints.append(point);
       
   386     updateTouchPoint(index, x, y);
       
   387     m_touchPoints[index].setState(Qt::TouchPointPressed);
       
   388 #endif
       
   389 }
       
   390 
       
   391 void EventSender::updateTouchPoint(int index, int x, int y)
       
   392 {
       
   393 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
       
   394     if (index < 0 || index >= m_touchPoints.count())
       
   395         return;
       
   396 
       
   397     QTouchEvent::TouchPoint &p = m_touchPoints[index];
       
   398     p.setPos(QPointF(x, y));
       
   399     p.setState(Qt::TouchPointMoved);
       
   400 #endif
       
   401 }
       
   402 
       
   403 void EventSender::setTouchModifier(const QString &modifier, bool enable)
       
   404 {
       
   405 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
       
   406     Qt::KeyboardModifier mod = Qt::NoModifier;
       
   407     if (!modifier.compare(QLatin1String("shift"), Qt::CaseInsensitive))
       
   408         mod = Qt::ShiftModifier;
       
   409     else if (!modifier.compare(QLatin1String("alt"), Qt::CaseInsensitive))
       
   410         mod = Qt::AltModifier;
       
   411     else if (!modifier.compare(QLatin1String("meta"), Qt::CaseInsensitive))
       
   412         mod = Qt::MetaModifier;
       
   413     else if (!modifier.compare(QLatin1String("ctrl"), Qt::CaseInsensitive))
       
   414         mod = Qt::ControlModifier;
       
   415 
       
   416     if (enable)
       
   417         m_touchModifiers |= mod;
       
   418     else
       
   419         m_touchModifiers &= ~mod;
       
   420 #endif
       
   421 }
       
   422 
       
   423 void EventSender::touchStart()
       
   424 {
       
   425 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
       
   426     if (!m_touchActive) {
       
   427         sendTouchEvent(QEvent::TouchBegin);
       
   428         m_touchActive = true;
       
   429     } else
       
   430         sendTouchEvent(QEvent::TouchUpdate);
       
   431 #endif
       
   432 }
       
   433 
       
   434 void EventSender::touchMove()
       
   435 {
       
   436 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
       
   437     sendTouchEvent(QEvent::TouchUpdate);
       
   438 #endif
       
   439 }
       
   440 
       
   441 void EventSender::touchEnd()
       
   442 {
       
   443 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
       
   444     for (int i = 0; i < m_touchPoints.count(); ++i)
       
   445         if (m_touchPoints[i].state() != Qt::TouchPointReleased) {
       
   446             sendTouchEvent(QEvent::TouchUpdate);
       
   447             return;
       
   448         }
       
   449     sendTouchEvent(QEvent::TouchEnd);
       
   450     m_touchActive = false;
       
   451 #endif
       
   452 }
       
   453 
       
   454 void EventSender::clearTouchPoints()
       
   455 {
       
   456 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
       
   457     m_touchPoints.clear();
       
   458     m_touchModifiers = Qt::KeyboardModifiers();
       
   459     m_touchActive = false;
       
   460 #endif
       
   461 }
       
   462 
       
   463 void EventSender::releaseTouchPoint(int index)
       
   464 {
       
   465 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
       
   466     if (index < 0 || index >= m_touchPoints.count())
       
   467         return;
       
   468 
       
   469     m_touchPoints[index].setState(Qt::TouchPointReleased);
       
   470 #endif
       
   471 }
       
   472 
       
   473 void EventSender::sendTouchEvent(QEvent::Type type)
       
   474 {
       
   475 #if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
       
   476     QTouchEvent event(type, QTouchEvent::TouchScreen, m_touchModifiers);
       
   477     event.setTouchPoints(m_touchPoints);
       
   478     sendEvent(m_page, &event);
       
   479     QList<QTouchEvent::TouchPoint>::Iterator it = m_touchPoints.begin();
       
   480     while (it != m_touchPoints.end()) {
       
   481         if (it->state() == Qt::TouchPointReleased)
       
   482             it = m_touchPoints.erase(it);
       
   483         else {
       
   484             it->setState(Qt::TouchPointStationary);
       
   485             ++it;
       
   486         }
       
   487     }
       
   488 #endif
       
   489 }
       
   490 
       
   491 void EventSender::zoomPageIn()
       
   492 {
       
   493     if (QWebFrame* frame = m_page->mainFrame())
       
   494         frame->setZoomFactor(frame->zoomFactor() * ZOOM_STEP);
       
   495 }
       
   496 
       
   497 void EventSender::zoomPageOut()
       
   498 {
       
   499     if (QWebFrame* frame = m_page->mainFrame())
       
   500         frame->setZoomFactor(frame->zoomFactor() / ZOOM_STEP);
       
   501 }
       
   502 
       
   503 void EventSender::textZoomIn()
       
   504 {
       
   505     if (QWebFrame* frame = m_page->mainFrame())
       
   506         frame->setTextSizeMultiplier(frame->textSizeMultiplier() * ZOOM_STEP);
       
   507 }
       
   508 
       
   509 void EventSender::textZoomOut()
       
   510 {
       
   511     if (QWebFrame* frame = m_page->mainFrame())
       
   512         frame->setTextSizeMultiplier(frame->textSizeMultiplier() / ZOOM_STEP);
       
   513 }
       
   514 
       
   515 QWebFrame* EventSender::frameUnderMouse() const
       
   516 {
       
   517     QWebFrame* frame = m_page->mainFrame();
       
   518 
       
   519 redo:
       
   520     QList<QWebFrame*> children = frame->childFrames();
       
   521     for (int i = 0; i < children.size(); ++i) {
       
   522         if (children.at(i)->geometry().contains(m_mousePos)) {
       
   523             frame = children.at(i);
       
   524             goto redo;
       
   525         }
       
   526     }
       
   527     if (frame->geometry().contains(m_mousePos))
       
   528         return frame;
       
   529     return 0;
       
   530 }
       
   531 
       
   532 void EventSender::sendOrQueueEvent(QEvent* event)
       
   533 {
       
   534     // Mouse move events are queued if 
       
   535     // 1. A previous event was queued.
       
   536     // 2. A delay was set-up by leapForward().
       
   537     // 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. 
       
   538     // To be safe and avoid a deadlock, this event is queued.
       
   539     if (endOfQueue == startOfQueue && !eventQueue[endOfQueue].m_delay && (!(m_mouseButtonPressed && (m_eventLoop && event->type() == QEvent::MouseButtonRelease)))) {
       
   540         sendEvent(m_page->view(), event);
       
   541         delete event;
       
   542         return;
       
   543     }
       
   544     eventQueue[endOfQueue++].m_event = event;
       
   545     eventQueue[endOfQueue].m_delay = 0;
       
   546     replaySavedEvents(event->type() != QEvent::MouseMove);
       
   547 }
       
   548 
       
   549 void EventSender::replaySavedEvents(bool flush)
       
   550 {
       
   551     if (startOfQueue < endOfQueue) {
       
   552         // First send all the events that are ready to be sent
       
   553         while (!eventQueue[startOfQueue].m_delay && startOfQueue < endOfQueue) {
       
   554             QEvent* ev = eventQueue[startOfQueue++].m_event;
       
   555             postEvent(m_page->view(), ev);
       
   556         }
       
   557         if (startOfQueue == endOfQueue) {
       
   558             // Reset the queue
       
   559             startOfQueue = 0;
       
   560             endOfQueue = 0;
       
   561         } else {
       
   562             QTest::qWait(eventQueue[startOfQueue].m_delay);
       
   563             eventQueue[startOfQueue].m_delay = 0;
       
   564         }
       
   565     }
       
   566     if (!flush)
       
   567         return;
       
   568 
       
   569     // Send a marker event, it will tell us when it is safe to exit the new event loop
       
   570     QEvent* drtEvent = new QEvent((QEvent::Type)DRT_MESSAGE_DONE);
       
   571     QApplication::postEvent(m_page->view(), drtEvent);
       
   572 
       
   573     // Start an event loop for async handling of Drag & Drop
       
   574     m_eventLoop = new QEventLoop;
       
   575     m_eventLoop->exec();
       
   576     delete m_eventLoop;
       
   577     m_eventLoop = 0;
       
   578 }
       
   579 
       
   580 bool EventSender::eventFilter(QObject* watched, QEvent* event)
       
   581 {
       
   582     if (watched != m_page->view())
       
   583         return false;
       
   584     switch (event->type()) {
       
   585     case QEvent::Leave:
       
   586         return true;
       
   587     case QEvent::MouseButtonPress:
       
   588     case QEvent::GraphicsSceneMousePress:
       
   589         m_mouseButtonPressed = true;
       
   590         break;
       
   591     case QEvent::MouseMove:
       
   592     case QEvent::GraphicsSceneMouseMove:
       
   593         if (m_mouseButtonPressed)
       
   594             m_drag = true;
       
   595         break;
       
   596     case QEvent::MouseButtonRelease:
       
   597     case QEvent::GraphicsSceneMouseRelease:
       
   598         m_mouseButtonPressed = false;
       
   599         m_drag = false;
       
   600         break;
       
   601     case DRT_MESSAGE_DONE:
       
   602         m_eventLoop->exit();
       
   603         return true;
       
   604     }
       
   605     return false;
       
   606 }
       
   607 
       
   608 void EventSender::timerEvent(QTimerEvent* ev)
       
   609 {
       
   610     m_clickTimer.stop();
       
   611 }
       
   612 
       
   613 QGraphicsSceneMouseEvent* EventSender::createGraphicsSceneMouseEvent(QEvent::Type type, const QPoint& pos, const QPoint& screenPos, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
       
   614 {
       
   615     QGraphicsSceneMouseEvent* event;
       
   616     event = new QGraphicsSceneMouseEvent(type);
       
   617     event->setPos(pos);
       
   618     event->setScreenPos(screenPos);
       
   619     event->setButton(button);
       
   620     event->setButtons(buttons);
       
   621     event->setModifiers(modifiers);
       
   622 
       
   623     return event;
       
   624 }
       
   625 
       
   626 QGraphicsSceneWheelEvent* EventSender::createGraphicsSceneWheelEvent(QEvent::Type type, const QPoint& pos, const QPoint& screenPos, int delta, Qt::KeyboardModifiers modifiers, Qt::Orientation orientation)
       
   627 {
       
   628     QGraphicsSceneWheelEvent* event;
       
   629     event = new QGraphicsSceneWheelEvent(type);
       
   630     event->setPos(pos);
       
   631     event->setScreenPos(screenPos);
       
   632     event->setDelta(delta);
       
   633     event->setModifiers(modifiers);
       
   634     event->setOrientation(orientation);
       
   635 
       
   636     return event;
       
   637 }
       
   638 
       
   639 void EventSender::sendEvent(QObject* receiver, QEvent* event)
       
   640 {
       
   641     if (WebCore::WebViewGraphicsBased* view = qobject_cast<WebCore::WebViewGraphicsBased*>(receiver))
       
   642         view->scene()->sendEvent(view->graphicsView(), event);
       
   643     else
       
   644         QApplication::sendEvent(receiver, event);
       
   645 }
       
   646 
       
   647 void EventSender::postEvent(QObject* receiver, QEvent* event)
       
   648 {
       
   649     // QGraphicsScene does not have a postEvent method, so send the event in this case
       
   650     // and delete it after that.
       
   651     if (WebCore::WebViewGraphicsBased* view = qobject_cast<WebCore::WebViewGraphicsBased*>(receiver)) {
       
   652         view->scene()->sendEvent(view->graphicsView(), event);
       
   653         delete event;
       
   654     } else
       
   655         QApplication::postEvent(receiver, event); // event deleted by the system
       
   656 }