1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "ui/events/event_utils.h"
6
7#include <Cocoa/Cocoa.h>
8
9#import "base/mac/mac_util.h"
10#import "base/mac/sdk_forward_declarations.h"
11#include "base/logging.h"
12#include "base/time/time.h"
13#include "build/build_config.h"
14#include "ui/events/cocoa/cocoa_event_utils.h"
15#include "ui/events/event_utils.h"
16#import "ui/events/keycodes/keyboard_code_conversion_mac.h"
17#include "ui/gfx/point.h"
18#include "ui/gfx/vector2d.h"
19
20namespace ui {
21
22void UpdateDeviceList() {
23  NOTIMPLEMENTED();
24}
25
26EventType EventTypeFromNative(const base::NativeEvent& native_event) {
27  NSEventType type = [native_event type];
28  switch (type) {
29    case NSKeyDown:
30      return ET_KEY_PRESSED;
31    case NSKeyUp:
32      return ET_KEY_RELEASED;
33    case NSLeftMouseDown:
34    case NSRightMouseDown:
35    case NSOtherMouseDown:
36      return ET_MOUSE_PRESSED;
37    case NSLeftMouseUp:
38    case NSRightMouseUp:
39    case NSOtherMouseUp:
40      return ET_MOUSE_RELEASED;
41    case NSLeftMouseDragged:
42    case NSRightMouseDragged:
43    case NSOtherMouseDragged:
44      return ET_MOUSE_DRAGGED;
45    case NSMouseMoved:
46      return ET_MOUSE_MOVED;
47    case NSScrollWheel:
48      return ET_MOUSEWHEEL;
49    case NSMouseEntered:
50      return ET_MOUSE_ENTERED;
51    case NSMouseExited:
52      return ET_MOUSE_EXITED;
53    case NSEventTypeSwipe:
54      return ET_SCROLL_FLING_START;
55    case NSFlagsChanged:
56    case NSAppKitDefined:
57    case NSSystemDefined:
58    case NSApplicationDefined:
59    case NSPeriodic:
60    case NSCursorUpdate:
61    case NSTabletPoint:
62    case NSTabletProximity:
63    case NSEventTypeGesture:
64    case NSEventTypeMagnify:
65    case NSEventTypeRotate:
66    case NSEventTypeBeginGesture:
67    case NSEventTypeEndGesture:
68      NOTIMPLEMENTED() << type;
69      break;
70    default:
71      NOTIMPLEMENTED() << type;
72      break;
73  }
74  return ET_UNKNOWN;
75}
76
77int EventFlagsFromNative(const base::NativeEvent& event) {
78  NSUInteger modifiers = [event modifierFlags];
79  return EventFlagsFromNSEventWithModifiers(event, modifiers);
80}
81
82base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
83  NSTimeInterval since_system_startup = [native_event timestamp];
84  // Truncate to extract seconds before doing floating point arithmetic.
85  int64_t seconds = since_system_startup;
86  since_system_startup -= seconds;
87  int64_t microseconds = since_system_startup * 1000000;
88  return base::TimeDelta::FromSeconds(seconds) +
89      base::TimeDelta::FromMicroseconds(microseconds);
90}
91
92gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
93  NSWindow* window = [native_event window];
94  if (!window) {
95    NOTIMPLEMENTED();  // Point will be in screen coordinates.
96    return gfx::Point();
97  }
98  NSPoint location = [native_event locationInWindow];
99  NSRect content_rect = [window contentRectForFrameRect:[window frame]];
100  return gfx::Point(location.x, NSHeight(content_rect) - location.y);
101}
102
103gfx::Point EventSystemLocationFromNative(
104    const base::NativeEvent& native_event) {
105  NOTIMPLEMENTED();
106  return gfx::Point();
107}
108
109int EventButtonFromNative(const base::NativeEvent& native_event) {
110  NOTIMPLEMENTED();
111  return 0;
112}
113
114int GetChangedMouseButtonFlagsFromNative(
115    const base::NativeEvent& native_event) {
116  NSEventType type = [native_event type];
117  switch (type) {
118    case NSLeftMouseDown:
119    case NSLeftMouseUp:
120    case NSLeftMouseDragged:
121      return EF_LEFT_MOUSE_BUTTON;
122    case NSRightMouseDown:
123    case NSRightMouseUp:
124    case NSRightMouseDragged:
125      return EF_RIGHT_MOUSE_BUTTON;
126    case NSOtherMouseDown:
127    case NSOtherMouseUp:
128    case NSOtherMouseDragged:
129      return EF_MIDDLE_MOUSE_BUTTON;
130  }
131  return 0;
132}
133
134gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& event) {
135  if ([event respondsToSelector:@selector(hasPreciseScrollingDeltas)] &&
136      [event hasPreciseScrollingDeltas]) {
137    // Handle continuous scrolling devices such as a Magic Mouse or a trackpad.
138    // -scrollingDelta{X|Y} have float return types but they return values that
139    // are already rounded to integers.
140    // The values are the same as the values returned from calling
141    // CGEventGetIntegerValueField(kCGScrollWheelEventPointDeltaAxis{1|2}).
142    return gfx::Vector2d([event scrollingDeltaX], [event scrollingDeltaY]);
143  } else {
144    // Empirically, a value of 0.1 is typical for one mousewheel click. Positive
145    // values when scrolling up or to the left. Scrolling quickly results in a
146    // higher delta per click, up to about 15.0. (Quartz documentation suggests
147    // +/-10).
148    // Multiply by 1000 to vaguely approximate WHEEL_DELTA on Windows (120).
149    const CGFloat kWheelDeltaMultiplier = 1000;
150    return gfx::Vector2d(kWheelDeltaMultiplier * [event deltaX],
151                         kWheelDeltaMultiplier * [event deltaY]);
152  }
153}
154
155base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
156  return [event copy];
157}
158
159void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
160  [event release];
161}
162
163void IncrementTouchIdRefCount(const base::NativeEvent& native_event) {
164  NOTIMPLEMENTED();
165}
166
167void ClearTouchIdIfReleased(const base::NativeEvent& native_event) {
168  NOTIMPLEMENTED();
169}
170
171int GetTouchId(const base::NativeEvent& native_event) {
172  NOTIMPLEMENTED();
173  return 0;
174}
175
176float GetTouchRadiusX(const base::NativeEvent& native_event) {
177  NOTIMPLEMENTED();
178  return 0.f;
179}
180
181float GetTouchRadiusY(const base::NativeEvent& native_event) {
182  NOTIMPLEMENTED();
183  return 0.f;
184}
185
186float GetTouchAngle(const base::NativeEvent& native_event) {
187  NOTIMPLEMENTED();
188  return 0.f;
189}
190
191float GetTouchForce(const base::NativeEvent& native_event) {
192  NOTIMPLEMENTED();
193  return 0.f;
194}
195
196bool GetScrollOffsets(const base::NativeEvent& native_event,
197                      float* x_offset,
198                      float* y_offset,
199                      float* x_offset_ordinal,
200                      float* y_offset_ordinal,
201                      int* finger_count) {
202  NOTIMPLEMENTED();
203  return false;
204}
205
206bool GetFlingData(const base::NativeEvent& native_event,
207                  float* vx,
208                  float* vy,
209                  float* vx_ordinal,
210                  float* vy_ordinal,
211                  bool* is_cancel) {
212  NOTIMPLEMENTED();
213  return false;
214}
215
216KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
217  return KeyboardCodeFromNSEvent(native_event);
218}
219
220const char* CodeFromNative(const base::NativeEvent& native_event) {
221  return CodeFromNSEvent(native_event);
222}
223
224uint32 PlatformKeycodeFromNative(const base::NativeEvent& native_event) {
225  return native_event.keyCode;
226}
227
228uint32 WindowsKeycodeFromNative(const base::NativeEvent& native_event) {
229  return static_cast<uint32>(KeyboardCodeFromNSEvent(native_event));
230}
231
232uint16 TextFromNative(const base::NativeEvent& native_event) {
233  NSString* text = @"";
234  if ([native_event type] != NSFlagsChanged)
235    text = [native_event characters];
236
237  // These exceptions are based on WebInputEventFactoryMac.mm:
238  uint32 windows_keycode = WindowsKeycodeFromNative(native_event);
239  if (windows_keycode == '\r')
240    text = @"\r";
241  if ([text isEqualToString:@"\x7F"])
242    text = @"\x8";
243  if (windows_keycode == 9)
244    text = @"\x9";
245
246  uint16 return_value;
247  [text getCharacters:&return_value];
248  return return_value;
249}
250
251uint16 UnmodifiedTextFromNative(const base::NativeEvent& native_event) {
252  NSString* text = @"";
253  if ([native_event type] != NSFlagsChanged)
254    text = [native_event charactersIgnoringModifiers];
255
256  // These exceptions are based on WebInputEventFactoryMac.mm:
257  uint32 windows_keycode = WindowsKeycodeFromNative(native_event);
258  if (windows_keycode == '\r')
259    text = @"\r";
260  if ([text isEqualToString:@"\x7F"])
261    text = @"\x8";
262  if (windows_keycode == 9)
263    text = @"\x9";
264
265  uint16 return_value;
266  [text getCharacters:&return_value];
267  return return_value;
268}
269
270bool IsCharFromNative(const base::NativeEvent& native_event) {
271  return false;
272}
273
274}  // namespace ui
275