WebEventFactory.mm 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /*
  2. * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions
  6. * are met:
  7. * 1. Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * 2. Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
  14. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  15. * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  16. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
  17. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  18. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  23. * THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #import "config.h"
  26. #import "WebEventFactory.h"
  27. #if USE(APPKIT)
  28. #import "WebKitSystemInterface.h"
  29. #import <wtf/ASCIICType.h>
  30. #import <WebCore/PlatformEventFactoryMac.h>
  31. #import <WebCore/Scrollbar.h>
  32. #import <WebCore/WindowsKeyboardCodes.h>
  33. using namespace WebCore;
  34. @interface NSEvent (WebNSEventDetails)
  35. - (NSInteger)_scrollCount;
  36. - (CGFloat)_unacceleratedScrollingDeltaX;
  37. - (CGFloat)_unacceleratedScrollingDeltaY;
  38. @end
  39. namespace WebKit {
  40. // FIXME: This is a huge copy/paste from WebCore/PlatformEventFactoryMac.mm. The code should be merged.
  41. static WebMouseEvent::Button currentMouseButton()
  42. {
  43. NSUInteger pressedMouseButtons = [NSEvent pressedMouseButtons];
  44. if (!pressedMouseButtons)
  45. return WebMouseEvent::NoButton;
  46. if (pressedMouseButtons == 1 << 0)
  47. return WebMouseEvent::LeftButton;
  48. if (pressedMouseButtons == 1 << 1)
  49. return WebMouseEvent::RightButton;
  50. return WebMouseEvent::MiddleButton;
  51. }
  52. static WebMouseEvent::Button mouseButtonForEvent(NSEvent *event)
  53. {
  54. switch ([event type]) {
  55. case NSLeftMouseDown:
  56. case NSLeftMouseUp:
  57. case NSLeftMouseDragged:
  58. return WebMouseEvent::LeftButton;
  59. case NSRightMouseDown:
  60. case NSRightMouseUp:
  61. case NSRightMouseDragged:
  62. return WebMouseEvent::RightButton;
  63. case NSOtherMouseDown:
  64. case NSOtherMouseUp:
  65. case NSOtherMouseDragged:
  66. return WebMouseEvent::MiddleButton;
  67. case NSMouseEntered:
  68. case NSMouseExited:
  69. return currentMouseButton();
  70. default:
  71. return WebMouseEvent::NoButton;
  72. }
  73. }
  74. static WebEvent::Type mouseEventTypeForEvent(NSEvent* event)
  75. {
  76. switch ([event type]) {
  77. case NSLeftMouseDragged:
  78. case NSMouseEntered:
  79. case NSMouseExited:
  80. case NSMouseMoved:
  81. case NSOtherMouseDragged:
  82. case NSRightMouseDragged:
  83. return WebEvent::MouseMove;
  84. case NSLeftMouseDown:
  85. case NSRightMouseDown:
  86. case NSOtherMouseDown:
  87. return WebEvent::MouseDown;
  88. case NSLeftMouseUp:
  89. case NSRightMouseUp:
  90. case NSOtherMouseUp:
  91. return WebEvent::MouseUp;
  92. default:
  93. return WebEvent::MouseMove;
  94. }
  95. }
  96. static int clickCountForEvent(NSEvent *event)
  97. {
  98. switch ([event type]) {
  99. case NSLeftMouseDown:
  100. case NSLeftMouseUp:
  101. case NSLeftMouseDragged:
  102. case NSRightMouseDown:
  103. case NSRightMouseUp:
  104. case NSRightMouseDragged:
  105. case NSOtherMouseDown:
  106. case NSOtherMouseUp:
  107. case NSOtherMouseDragged:
  108. return [event clickCount];
  109. default:
  110. return 0;
  111. }
  112. }
  113. static NSScreen *screenForWindow(NSWindow *window)
  114. {
  115. NSScreen *screen = [window screen]; // nil if the window is off-screen
  116. if (screen)
  117. return screen;
  118. NSArray *screens = [NSScreen screens];
  119. if ([screens count] > 0)
  120. return [screens objectAtIndex:0]; // screen containing the menubar
  121. return nil;
  122. }
  123. static NSPoint flipScreenPoint(const NSPoint& screenPoint, NSScreen *screen)
  124. {
  125. NSPoint flippedPoint = screenPoint;
  126. flippedPoint.y = NSMaxY([screen frame]) - flippedPoint.y;
  127. return flippedPoint;
  128. }
  129. static NSPoint globalPoint(const NSPoint& windowPoint, NSWindow *window)
  130. {
  131. return flipScreenPoint([window convertBaseToScreen:windowPoint], screenForWindow(window));
  132. }
  133. static NSPoint globalPointForEvent(NSEvent *event)
  134. {
  135. switch ([event type]) {
  136. case NSLeftMouseDown:
  137. case NSLeftMouseDragged:
  138. case NSLeftMouseUp:
  139. case NSMouseEntered:
  140. case NSMouseExited:
  141. case NSMouseMoved:
  142. case NSOtherMouseDown:
  143. case NSOtherMouseDragged:
  144. case NSOtherMouseUp:
  145. case NSRightMouseDown:
  146. case NSRightMouseDragged:
  147. case NSRightMouseUp:
  148. case NSScrollWheel:
  149. return globalPoint([event locationInWindow], [event window]);
  150. default:
  151. return NSZeroPoint;
  152. }
  153. }
  154. static NSPoint pointForEvent(NSEvent *event, NSView *windowView)
  155. {
  156. switch ([event type]) {
  157. case NSLeftMouseDown:
  158. case NSLeftMouseDragged:
  159. case NSLeftMouseUp:
  160. case NSMouseEntered:
  161. case NSMouseExited:
  162. case NSMouseMoved:
  163. case NSOtherMouseDown:
  164. case NSOtherMouseDragged:
  165. case NSOtherMouseUp:
  166. case NSRightMouseDown:
  167. case NSRightMouseDragged:
  168. case NSRightMouseUp:
  169. case NSScrollWheel: {
  170. // Note: This will have its origin at the bottom left of the window unless windowView is flipped.
  171. // In those cases, the Y coordinate gets flipped by Widget::convertFromContainingWindow.
  172. NSPoint location = [event locationInWindow];
  173. if (windowView)
  174. location = [windowView convertPoint:location fromView:nil];
  175. return location;
  176. }
  177. default:
  178. return NSZeroPoint;
  179. }
  180. }
  181. static WebWheelEvent::Phase phaseForEvent(NSEvent *event)
  182. {
  183. uint32_t phase = WebWheelEvent::PhaseNone;
  184. if ([event phase] & NSEventPhaseBegan)
  185. phase |= WebWheelEvent::PhaseBegan;
  186. if ([event phase] & NSEventPhaseStationary)
  187. phase |= WebWheelEvent::PhaseStationary;
  188. if ([event phase] & NSEventPhaseChanged)
  189. phase |= WebWheelEvent::PhaseChanged;
  190. if ([event phase] & NSEventPhaseEnded)
  191. phase |= WebWheelEvent::PhaseEnded;
  192. if ([event phase] & NSEventPhaseCancelled)
  193. phase |= WebWheelEvent::PhaseCancelled;
  194. #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 1080
  195. if ([event phase] & NSEventPhaseMayBegin)
  196. phase |= WebWheelEvent::PhaseMayBegin;
  197. #endif
  198. return static_cast<WebWheelEvent::Phase>(phase);
  199. }
  200. static WebWheelEvent::Phase momentumPhaseForEvent(NSEvent *event)
  201. {
  202. uint32_t phase = WebWheelEvent::PhaseNone;
  203. if ([event momentumPhase] & NSEventPhaseBegan)
  204. phase |= WebWheelEvent::PhaseBegan;
  205. if ([event momentumPhase] & NSEventPhaseStationary)
  206. phase |= WebWheelEvent::PhaseStationary;
  207. if ([event momentumPhase] & NSEventPhaseChanged)
  208. phase |= WebWheelEvent::PhaseChanged;
  209. if ([event momentumPhase] & NSEventPhaseEnded)
  210. phase |= WebWheelEvent::PhaseEnded;
  211. if ([event momentumPhase] & NSEventPhaseCancelled)
  212. phase |= WebWheelEvent::PhaseCancelled;
  213. return static_cast<WebWheelEvent::Phase>(phase);
  214. }
  215. #if ENABLE(GESTURE_EVENTS)
  216. static WebEvent::Type gestureEventTypeForEvent(NSEvent *event)
  217. {
  218. switch ([event type]) {
  219. case NSEventTypeBeginGesture:
  220. return WebEvent::GestureScrollBegin;
  221. case NSEventTypeEndGesture:
  222. return WebEvent::GestureScrollEnd;
  223. default:
  224. ASSERT_NOT_REACHED();
  225. return WebEvent::GestureScrollEnd;
  226. }
  227. }
  228. #endif
  229. static inline String textFromEvent(NSEvent* event)
  230. {
  231. if ([event type] == NSFlagsChanged)
  232. return String("");
  233. return String([event characters]);
  234. }
  235. static inline String unmodifiedTextFromEvent(NSEvent* event)
  236. {
  237. if ([event type] == NSFlagsChanged)
  238. return String("");
  239. return String([event charactersIgnoringModifiers]);
  240. }
  241. static bool isKeypadEvent(NSEvent* event)
  242. {
  243. // Check that this is the type of event that has a keyCode.
  244. switch ([event type]) {
  245. case NSKeyDown:
  246. case NSKeyUp:
  247. case NSFlagsChanged:
  248. break;
  249. default:
  250. return false;
  251. }
  252. switch ([event keyCode]) {
  253. case 71: // Clear
  254. case 81: // =
  255. case 75: // /
  256. case 67: // *
  257. case 78: // -
  258. case 69: // +
  259. case 76: // Enter
  260. case 65: // .
  261. case 82: // 0
  262. case 83: // 1
  263. case 84: // 2
  264. case 85: // 3
  265. case 86: // 4
  266. case 87: // 5
  267. case 88: // 6
  268. case 89: // 7
  269. case 91: // 8
  270. case 92: // 9
  271. return true;
  272. }
  273. return false;
  274. }
  275. static inline bool isKeyUpEvent(NSEvent *event)
  276. {
  277. if ([event type] != NSFlagsChanged)
  278. return [event type] == NSKeyUp;
  279. // FIXME: This logic fails if the user presses both Shift keys at once, for example:
  280. // we treat releasing one of them as keyDown.
  281. switch ([event keyCode]) {
  282. case 54: // Right Command
  283. case 55: // Left Command
  284. return ([event modifierFlags] & NSCommandKeyMask) == 0;
  285. case 57: // Capslock
  286. return ([event modifierFlags] & NSAlphaShiftKeyMask) == 0;
  287. case 56: // Left Shift
  288. case 60: // Right Shift
  289. return ([event modifierFlags] & NSShiftKeyMask) == 0;
  290. case 58: // Left Alt
  291. case 61: // Right Alt
  292. return ([event modifierFlags] & NSAlternateKeyMask) == 0;
  293. case 59: // Left Ctrl
  294. case 62: // Right Ctrl
  295. return ([event modifierFlags] & NSControlKeyMask) == 0;
  296. case 63: // Function
  297. return ([event modifierFlags] & NSFunctionKeyMask) == 0;
  298. }
  299. return false;
  300. }
  301. static inline WebEvent::Modifiers modifiersForEvent(NSEvent *event)
  302. {
  303. unsigned modifiers = 0;
  304. if ([event modifierFlags] & NSAlphaShiftKeyMask)
  305. modifiers |= WebEvent::CapsLockKey;
  306. if ([event modifierFlags] & NSShiftKeyMask)
  307. modifiers |= WebEvent::ShiftKey;
  308. if ([event modifierFlags] & NSControlKeyMask)
  309. modifiers |= WebEvent::ControlKey;
  310. if ([event modifierFlags] & NSAlternateKeyMask)
  311. modifiers |= WebEvent::AltKey;
  312. if ([event modifierFlags] & NSCommandKeyMask)
  313. modifiers |= WebEvent::MetaKey;
  314. return (WebEvent::Modifiers)modifiers;
  315. }
  316. WebMouseEvent WebEventFactory::createWebMouseEvent(NSEvent *event, NSView *windowView)
  317. {
  318. NSPoint position = pointForEvent(event, windowView);
  319. NSPoint globalPosition = globalPointForEvent(event);
  320. WebEvent::Type type = mouseEventTypeForEvent(event);
  321. WebMouseEvent::Button button = mouseButtonForEvent(event);
  322. float deltaX = [event deltaX];
  323. float deltaY = [event deltaY];
  324. float deltaZ = [event deltaZ];
  325. int clickCount = clickCountForEvent(event);
  326. WebEvent::Modifiers modifiers = modifiersForEvent(event);
  327. double timestamp = [event timestamp];
  328. return WebMouseEvent(type, button, IntPoint(position), IntPoint(globalPosition), deltaX, deltaY, deltaZ, clickCount, modifiers, timestamp);
  329. }
  330. WebWheelEvent WebEventFactory::createWebWheelEvent(NSEvent *event, NSView *windowView)
  331. {
  332. NSPoint position = pointForEvent(event, windowView);
  333. NSPoint globalPosition = globalPointForEvent(event);
  334. BOOL continuous;
  335. float deltaX = 0;
  336. float deltaY = 0;
  337. float wheelTicksX = 0;
  338. float wheelTicksY = 0;
  339. WKGetWheelEventDeltas(event, &deltaX, &deltaY, &continuous);
  340. if (continuous) {
  341. // smooth scroll events
  342. wheelTicksX = deltaX / static_cast<float>(Scrollbar::pixelsPerLineStep());
  343. wheelTicksY = deltaY / static_cast<float>(Scrollbar::pixelsPerLineStep());
  344. } else {
  345. // plain old wheel events
  346. wheelTicksX = deltaX;
  347. wheelTicksY = deltaY;
  348. deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep());
  349. deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep());
  350. }
  351. WebWheelEvent::Granularity granularity = WebWheelEvent::ScrollByPixelWheelEvent;
  352. #if HAVE(INVERTED_WHEEL_EVENTS)
  353. bool directionInvertedFromDevice = [event isDirectionInvertedFromDevice];
  354. #else
  355. bool directionInvertedFromDevice = false;
  356. #endif
  357. WebWheelEvent::Phase phase = phaseForEvent(event);
  358. WebWheelEvent::Phase momentumPhase = momentumPhaseForEvent(event);
  359. bool hasPreciseScrollingDeltas = continuous;
  360. uint32_t scrollCount;
  361. FloatSize unacceleratedScrollingDelta;
  362. static bool nsEventSupportsScrollCount = [NSEvent instancesRespondToSelector:@selector(_scrollCount)];
  363. if (nsEventSupportsScrollCount) {
  364. scrollCount = [event _scrollCount];
  365. unacceleratedScrollingDelta = FloatSize([event _unacceleratedScrollingDeltaX], [event _unacceleratedScrollingDeltaY]);
  366. } else {
  367. scrollCount = 0;
  368. unacceleratedScrollingDelta = FloatSize(deltaX, deltaY);
  369. }
  370. WebEvent::Modifiers modifiers = modifiersForEvent(event);
  371. double timestamp = [event timestamp];
  372. return WebWheelEvent(WebEvent::Wheel, IntPoint(position), IntPoint(globalPosition), FloatSize(deltaX, deltaY), FloatSize(wheelTicksX, wheelTicksY), granularity, directionInvertedFromDevice, phase, momentumPhase, hasPreciseScrollingDeltas, scrollCount, unacceleratedScrollingDelta, modifiers, timestamp);
  373. }
  374. WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(NSEvent *event, NSView *)
  375. {
  376. WebEvent::Type type = isKeyUpEvent(event) ? WebEvent::KeyUp : WebEvent::KeyDown;
  377. String text = textFromEvent(event);
  378. String unmodifiedText = unmodifiedTextFromEvent(event);
  379. String keyIdentifier = keyIdentifierForKeyEvent(event);
  380. int windowsVirtualKeyCode = windowsKeyCodeForKeyEvent(event);
  381. int nativeVirtualKeyCode = [event keyCode];
  382. int macCharCode = WKGetNSEventKeyChar(event);
  383. bool autoRepeat = ([event type] != NSFlagsChanged) && [event isARepeat];
  384. bool isKeypad = isKeypadEvent(event);
  385. bool isSystemKey = false; // SystemKey is always false on the Mac.
  386. WebEvent::Modifiers modifiers = modifiersForEvent(event);
  387. double timestamp = [event timestamp];
  388. // Always use 13 for Enter/Return -- we don't want to use AppKit's different character for Enter.
  389. if (windowsVirtualKeyCode == VK_RETURN) {
  390. text = "\r";
  391. unmodifiedText = "\r";
  392. }
  393. // AppKit sets text to "\x7F" for backspace, but the correct KeyboardEvent character code is 8.
  394. if (windowsVirtualKeyCode == VK_BACK) {
  395. text = "\x8";
  396. unmodifiedText = "\x8";
  397. }
  398. // Always use 9 for Tab -- we don't want to use AppKit's different character for shift-tab.
  399. if (windowsVirtualKeyCode == VK_TAB) {
  400. text = "\x9";
  401. unmodifiedText = "\x9";
  402. }
  403. return WebKeyboardEvent(type, text, unmodifiedText, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, macCharCode, autoRepeat, isKeypad, isSystemKey, modifiers, timestamp);
  404. }
  405. #if ENABLE(GESTURE_EVENTS)
  406. WebGestureEvent WebEventFactory::createWebGestureEvent(NSEvent *event, NSView *windowView)
  407. {
  408. WebEvent::Type type = gestureEventTypeForEvent(event);
  409. NSPoint position = pointForEvent(event, windowView);
  410. NSPoint globalPosition = globalPointForEvent(event);
  411. WebEvent::Modifiers modifiers = modifiersForEvent(event);
  412. double timestamp = [event timestamp];
  413. return WebGestureEvent(type, IntPoint(position), IntPoint(globalPosition), modifiers, timestamp);
  414. }
  415. #endif
  416. } // namespace WebKit
  417. #endif // USE(APPKIT)