WebEventFactoryQt.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Copyright (C) 2010 Apple Inc. All rights reserved.
  3. * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
  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. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
  15. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  16. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
  18. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  24. * THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "config.h"
  27. #include "WebEventFactoryQt.h"
  28. #include <QKeyEvent>
  29. #include <QLineF>
  30. #include <QTransform>
  31. #include <WebCore/FloatPoint.h>
  32. #include <WebCore/FloatSize.h>
  33. #include <WebCore/IntPoint.h>
  34. #include <WebCore/PlatformKeyboardEvent.h>
  35. #include <wtf/ASCIICType.h>
  36. #include <wtf/CurrentTime.h>
  37. using namespace WebCore;
  38. namespace WebKit {
  39. static inline double currentTimeForEvent(const QInputEvent* event)
  40. {
  41. ASSERT(event);
  42. // Use the input event timestamps if they are available.
  43. // These timestamps are in milliseconds, thus convert them to seconds.
  44. if (event->timestamp())
  45. return static_cast<double>(event->timestamp()) / 1000;
  46. return WTF::currentTime();
  47. }
  48. static WebMouseEvent::Button mouseButtonForEvent(QMouseEvent *event)
  49. {
  50. if (event->button() == Qt::LeftButton || (event->buttons() & Qt::LeftButton))
  51. return WebMouseEvent::LeftButton;
  52. else if (event->button() == Qt::RightButton || (event->buttons() & Qt::RightButton))
  53. return WebMouseEvent::RightButton;
  54. else if (event->button() == Qt::MidButton || (event->buttons() & Qt::MidButton))
  55. return WebMouseEvent::MiddleButton;
  56. return WebMouseEvent::NoButton;
  57. }
  58. static WebEvent::Type webEventTypeForEvent(const QEvent* event)
  59. {
  60. switch (event->type()) {
  61. case QEvent::MouseButtonPress:
  62. return WebEvent::MouseDown;
  63. case QEvent::MouseButtonRelease:
  64. return WebEvent::MouseUp;
  65. case QEvent::MouseMove:
  66. return WebEvent::MouseMove;
  67. case QEvent::Wheel:
  68. return WebEvent::Wheel;
  69. case QEvent::KeyPress:
  70. return WebEvent::KeyDown;
  71. case QEvent::KeyRelease:
  72. return WebEvent::KeyUp;
  73. #if ENABLE(TOUCH_EVENTS)
  74. case QEvent::TouchBegin:
  75. return WebEvent::TouchStart;
  76. case QEvent::TouchUpdate:
  77. return WebEvent::TouchMove;
  78. case QEvent::TouchEnd:
  79. return WebEvent::TouchEnd;
  80. case QEvent::TouchCancel:
  81. return WebEvent::TouchCancel;
  82. #endif
  83. case QEvent::MouseButtonDblClick:
  84. ASSERT_NOT_REACHED();
  85. return WebEvent::NoType;
  86. default:
  87. // assert
  88. return WebEvent::MouseMove;
  89. }
  90. }
  91. static inline WebEvent::Modifiers modifiersForEvent(Qt::KeyboardModifiers modifiers)
  92. {
  93. unsigned result = 0;
  94. if (modifiers & Qt::ShiftModifier)
  95. result |= WebEvent::ShiftKey;
  96. if (modifiers & Qt::ControlModifier)
  97. result |= WebEvent::ControlKey;
  98. if (modifiers & Qt::AltModifier)
  99. result |= WebEvent::AltKey;
  100. if (modifiers & Qt::MetaModifier)
  101. result |= WebEvent::MetaKey;
  102. return (WebEvent::Modifiers)result;
  103. }
  104. WebMouseEvent WebEventFactory::createWebMouseEvent(QMouseEvent* event, const QTransform& fromItemTransform, int eventClickCount)
  105. {
  106. static FloatPoint lastPos = FloatPoint(0, 0);
  107. WebEvent::Type type = webEventTypeForEvent(event);
  108. WebMouseEvent::Button button = mouseButtonForEvent(event);
  109. float deltaX = event->pos().x() - lastPos.x();
  110. float deltaY = event->pos().y() - lastPos.y();
  111. int clickCount = eventClickCount;
  112. WebEvent::Modifiers modifiers = modifiersForEvent(event->modifiers());
  113. double timestamp = currentTimeForEvent(event);
  114. lastPos.set(event->localPos().x(), event->localPos().y());
  115. return WebMouseEvent(type, button, fromItemTransform.map(event->localPos()).toPoint(), event->screenPos().toPoint(), deltaX, deltaY, 0.0f, clickCount, modifiers, timestamp);
  116. }
  117. WebWheelEvent WebEventFactory::createWebWheelEvent(QWheelEvent* e, const QTransform& fromItemTransform)
  118. {
  119. float deltaX = 0;
  120. float deltaY = 0;
  121. float wheelTicksX = 0;
  122. float wheelTicksY = 0;
  123. WebWheelEvent::Granularity granularity = WebWheelEvent::ScrollByPixelWheelEvent;
  124. WebEvent::Modifiers modifiers = modifiersForEvent(e->modifiers());
  125. double timestamp = currentTimeForEvent(e);
  126. if (e->orientation() == Qt::Horizontal) {
  127. deltaX = e->delta();
  128. wheelTicksX = deltaX / 120.0f;
  129. } else {
  130. deltaY = e->delta();
  131. wheelTicksY = deltaY / 120.0f;
  132. }
  133. // Since we report the scroll by the pixel, convert the delta to pixel distance using standard scroll step.
  134. // Use the same single scroll step as QTextEdit (in QTextEditPrivate::init [h,v]bar->setSingleStep)
  135. static const float cDefaultQtScrollStep = 20.f;
  136. // ### FIXME: Default from QtGui. Should use Qt platform theme API once configurable.
  137. const int wheelScrollLines = 3;
  138. deltaX = wheelTicksX * wheelScrollLines * cDefaultQtScrollStep;
  139. deltaY = wheelTicksY * wheelScrollLines * cDefaultQtScrollStep;
  140. // Transform the position and the pixel scrolling distance.
  141. QLineF transformedScroll = fromItemTransform.map(QLineF(e->posF(), e->posF() + QPointF(deltaX, deltaY)));
  142. IntPoint transformedPoint = transformedScroll.p1().toPoint();
  143. IntPoint globalPoint = e->globalPosF().toPoint();
  144. FloatSize transformedDelta(transformedScroll.dx(), transformedScroll.dy());
  145. FloatSize wheelTicks(wheelTicksX, wheelTicksY);
  146. return WebWheelEvent(WebEvent::Wheel, transformedPoint, globalPoint, transformedDelta, wheelTicks, granularity, modifiers, timestamp);
  147. }
  148. WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(QKeyEvent* event)
  149. {
  150. const int state = event->modifiers();
  151. WebEvent::Type type = webEventTypeForEvent(event);
  152. const String text = event->text();
  153. const String unmodifiedText = event->text();
  154. bool isAutoRepeat = event->isAutoRepeat();
  155. bool isSystemKey = false; // FIXME: No idea what that is.
  156. bool isKeypad = (state & Qt::KeypadModifier);
  157. const String keyIdentifier = keyIdentifierForQtKeyCode(event->key());
  158. int windowsVirtualKeyCode = windowsKeyCodeForKeyEvent(event->key(), isKeypad);
  159. int nativeVirtualKeyCode = event->nativeVirtualKey();
  160. int macCharCode = 0;
  161. WebEvent::Modifiers modifiers = modifiersForEvent(event->modifiers());
  162. double timestamp = currentTimeForEvent(event);
  163. return WebKeyboardEvent(type, text, unmodifiedText, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, macCharCode, isAutoRepeat, isKeypad, isSystemKey, modifiers, timestamp);
  164. }
  165. #if ENABLE(TOUCH_EVENTS)
  166. WebTouchEvent WebEventFactory::createWebTouchEvent(const QTouchEvent* event, const QTransform& fromItemTransform)
  167. {
  168. WebEvent::Type type = webEventTypeForEvent(event);
  169. WebPlatformTouchPoint::TouchPointState state = static_cast<WebPlatformTouchPoint::TouchPointState>(0);
  170. unsigned int id;
  171. WebEvent::Modifiers modifiers = modifiersForEvent(event->modifiers());
  172. double timestamp = currentTimeForEvent(event);
  173. const QList<QTouchEvent::TouchPoint>& points = event->touchPoints();
  174. Vector<WebPlatformTouchPoint, 6> m_touchPoints;
  175. for (int i = 0; i < points.count(); ++i) {
  176. const QTouchEvent::TouchPoint& touchPoint = points.at(i);
  177. id = static_cast<unsigned>(touchPoint.id());
  178. switch (touchPoint.state()) {
  179. case Qt::TouchPointReleased:
  180. state = WebPlatformTouchPoint::TouchReleased;
  181. break;
  182. case Qt::TouchPointMoved:
  183. state = WebPlatformTouchPoint::TouchMoved;
  184. break;
  185. case Qt::TouchPointPressed:
  186. state = WebPlatformTouchPoint::TouchPressed;
  187. break;
  188. case Qt::TouchPointStationary:
  189. state = WebPlatformTouchPoint::TouchStationary;
  190. break;
  191. default:
  192. ASSERT_NOT_REACHED();
  193. break;
  194. }
  195. // Qt does not have a Qt::TouchPointCancelled point state, so if we receive a touch cancel event,
  196. // simply cancel all touch points here.
  197. if (type == WebEvent::TouchCancel)
  198. state = WebPlatformTouchPoint::TouchCancelled;
  199. IntSize radius(touchPoint.rect().width()/ 2, touchPoint.rect().height() / 2);
  200. m_touchPoints.append(WebPlatformTouchPoint(id, state, touchPoint.screenPos().toPoint(), fromItemTransform.map(touchPoint.pos()).toPoint(), radius, 0.0, touchPoint.pressure()));
  201. }
  202. return WebTouchEvent(type, m_touchPoints, modifiers, timestamp);
  203. }
  204. #endif
  205. } // namespace WebKit