• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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.h"
6 
7 #if defined(USE_X11)
8 #include <X11/extensions/XInput2.h>
9 #include <X11/Xlib.h>
10 #include <X11/keysym.h>
11 #endif
12 
13 #include <cmath>
14 #include <cstring>
15 
16 #include "base/metrics/histogram.h"
17 #include "base/strings/stringprintf.h"
18 #include "ui/events/event_utils.h"
19 #include "ui/events/keycodes/keyboard_code_conversion.h"
20 #include "ui/gfx/point3_f.h"
21 #include "ui/gfx/point_conversions.h"
22 #include "ui/gfx/transform.h"
23 #include "ui/gfx/transform_util.h"
24 
25 #if defined(USE_X11)
26 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
27 #elif defined(USE_OZONE)
28 #include "ui/events/keycodes/keyboard_code_conversion.h"
29 #endif
30 
31 namespace {
32 
EventTypeName(ui::EventType type)33 std::string EventTypeName(ui::EventType type) {
34 #define RETURN_IF_TYPE(t) if (type == ui::t)  return #t
35 #define CASE_TYPE(t) case ui::t:  return #t
36   switch (type) {
37     CASE_TYPE(ET_UNKNOWN);
38     CASE_TYPE(ET_MOUSE_PRESSED);
39     CASE_TYPE(ET_MOUSE_DRAGGED);
40     CASE_TYPE(ET_MOUSE_RELEASED);
41     CASE_TYPE(ET_MOUSE_MOVED);
42     CASE_TYPE(ET_MOUSE_ENTERED);
43     CASE_TYPE(ET_MOUSE_EXITED);
44     CASE_TYPE(ET_KEY_PRESSED);
45     CASE_TYPE(ET_KEY_RELEASED);
46     CASE_TYPE(ET_MOUSEWHEEL);
47     CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED);
48     CASE_TYPE(ET_TOUCH_RELEASED);
49     CASE_TYPE(ET_TOUCH_PRESSED);
50     CASE_TYPE(ET_TOUCH_MOVED);
51     CASE_TYPE(ET_TOUCH_CANCELLED);
52     CASE_TYPE(ET_DROP_TARGET_EVENT);
53     CASE_TYPE(ET_TRANSLATED_KEY_PRESS);
54     CASE_TYPE(ET_TRANSLATED_KEY_RELEASE);
55     CASE_TYPE(ET_GESTURE_SCROLL_BEGIN);
56     CASE_TYPE(ET_GESTURE_SCROLL_END);
57     CASE_TYPE(ET_GESTURE_SCROLL_UPDATE);
58     CASE_TYPE(ET_GESTURE_SHOW_PRESS);
59     CASE_TYPE(ET_GESTURE_WIN8_EDGE_SWIPE);
60     CASE_TYPE(ET_GESTURE_TAP);
61     CASE_TYPE(ET_GESTURE_TAP_DOWN);
62     CASE_TYPE(ET_GESTURE_TAP_CANCEL);
63     CASE_TYPE(ET_GESTURE_BEGIN);
64     CASE_TYPE(ET_GESTURE_END);
65     CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP);
66     CASE_TYPE(ET_GESTURE_PINCH_BEGIN);
67     CASE_TYPE(ET_GESTURE_PINCH_END);
68     CASE_TYPE(ET_GESTURE_PINCH_UPDATE);
69     CASE_TYPE(ET_GESTURE_LONG_PRESS);
70     CASE_TYPE(ET_GESTURE_LONG_TAP);
71     CASE_TYPE(ET_GESTURE_SWIPE);
72     CASE_TYPE(ET_GESTURE_TAP_UNCONFIRMED);
73     CASE_TYPE(ET_GESTURE_DOUBLE_TAP);
74     CASE_TYPE(ET_SCROLL);
75     CASE_TYPE(ET_SCROLL_FLING_START);
76     CASE_TYPE(ET_SCROLL_FLING_CANCEL);
77     CASE_TYPE(ET_CANCEL_MODE);
78     CASE_TYPE(ET_UMA_DATA);
79     case ui::ET_LAST: NOTREACHED(); return std::string();
80     // Don't include default, so that we get an error when new type is added.
81   }
82 #undef CASE_TYPE
83 
84   NOTREACHED();
85   return std::string();
86 }
87 
IsX11SendEventTrue(const base::NativeEvent & event)88 bool IsX11SendEventTrue(const base::NativeEvent& event) {
89 #if defined(USE_X11)
90   return event && event->xany.send_event;
91 #else
92   return false;
93 #endif
94 }
95 
X11EventHasNonStandardState(const base::NativeEvent & event)96 bool X11EventHasNonStandardState(const base::NativeEvent& event) {
97 #if defined(USE_X11)
98   const unsigned int kAllStateMask =
99       Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask |
100       Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask | ShiftMask |
101       LockMask | ControlMask | AnyModifier;
102   return event && (event->xkey.state & ~kAllStateMask) != 0;
103 #else
104   return false;
105 #endif
106 }
107 
108 }  // namespace
109 
110 namespace ui {
111 
112 ////////////////////////////////////////////////////////////////////////////////
113 // Event
114 
115 // static
Clone(const Event & event)116 scoped_ptr<Event> Event::Clone(const Event& event) {
117   if (event.IsKeyEvent()) {
118     return scoped_ptr<Event>(new KeyEvent(static_cast<const KeyEvent&>(event)));
119   }
120 
121   if (event.IsMouseEvent()) {
122     if (event.IsMouseWheelEvent()) {
123       return scoped_ptr<Event>(
124           new MouseWheelEvent(static_cast<const MouseWheelEvent&>(event)));
125     }
126 
127     return scoped_ptr<Event>(
128         new MouseEvent(static_cast<const MouseEvent&>(event)));
129   }
130 
131   if (event.IsTouchEvent()) {
132     return scoped_ptr<Event>(
133         new TouchEvent(static_cast<const TouchEvent&>(event)));
134   }
135 
136   if (event.IsGestureEvent()) {
137     return scoped_ptr<Event>(
138         new GestureEvent(static_cast<const GestureEvent&>(event)));
139   }
140 
141   if (event.IsScrollEvent()) {
142     return scoped_ptr<Event>(
143         new ScrollEvent(static_cast<const ScrollEvent&>(event)));
144   }
145 
146   return scoped_ptr<Event>(new Event(event));
147 }
148 
~Event()149 Event::~Event() {
150   if (delete_native_event_)
151     ReleaseCopiedNativeEvent(native_event_);
152 }
153 
AsGestureEvent()154 GestureEvent* Event::AsGestureEvent() {
155   CHECK(IsGestureEvent());
156   return static_cast<GestureEvent*>(this);
157 }
158 
AsGestureEvent() const159 const GestureEvent* Event::AsGestureEvent() const {
160   CHECK(IsGestureEvent());
161   return static_cast<const GestureEvent*>(this);
162 }
163 
HasNativeEvent() const164 bool Event::HasNativeEvent() const {
165   base::NativeEvent null_event;
166   std::memset(&null_event, 0, sizeof(null_event));
167   return !!std::memcmp(&native_event_, &null_event, sizeof(null_event));
168 }
169 
StopPropagation()170 void Event::StopPropagation() {
171   // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
172   // events.
173   // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
174   CHECK(cancelable_);
175   result_ = static_cast<EventResult>(result_ | ER_CONSUMED);
176 }
177 
SetHandled()178 void Event::SetHandled() {
179   // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
180   // events.
181   // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
182   CHECK(cancelable_);
183   result_ = static_cast<EventResult>(result_ | ER_HANDLED);
184 }
185 
Event(EventType type,base::TimeDelta time_stamp,int flags)186 Event::Event(EventType type, base::TimeDelta time_stamp, int flags)
187     : type_(type),
188       time_stamp_(time_stamp),
189       flags_(flags),
190       native_event_(base::NativeEvent()),
191       delete_native_event_(false),
192       cancelable_(true),
193       target_(NULL),
194       phase_(EP_PREDISPATCH),
195       result_(ER_UNHANDLED),
196       source_device_id_(ED_UNKNOWN_DEVICE) {
197   if (type_ < ET_LAST)
198     name_ = EventTypeName(type_);
199 }
200 
Event(const base::NativeEvent & native_event,EventType type,int flags)201 Event::Event(const base::NativeEvent& native_event,
202              EventType type,
203              int flags)
204     : type_(type),
205       time_stamp_(EventTimeFromNative(native_event)),
206       flags_(flags),
207       native_event_(native_event),
208       delete_native_event_(false),
209       cancelable_(true),
210       target_(NULL),
211       phase_(EP_PREDISPATCH),
212       result_(ER_UNHANDLED),
213       source_device_id_(ED_UNKNOWN_DEVICE) {
214   base::TimeDelta delta = EventTimeForNow() - time_stamp_;
215   if (type_ < ET_LAST)
216     name_ = EventTypeName(type_);
217   UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser",
218                               delta.InMicroseconds(), 1, 1000000, 100);
219   std::string name_for_event =
220       base::StringPrintf("Event.Latency.Browser.%s", name_.c_str());
221   base::HistogramBase* counter_for_type =
222       base::Histogram::FactoryGet(
223           name_for_event,
224           1,
225           1000000,
226           100,
227           base::HistogramBase::kUmaTargetedHistogramFlag);
228   counter_for_type->Add(delta.InMicroseconds());
229 
230 #if defined(USE_X11)
231   if (native_event->type == GenericEvent) {
232     XIDeviceEvent* xiev =
233         static_cast<XIDeviceEvent*>(native_event->xcookie.data);
234     source_device_id_ = xiev->sourceid;
235   }
236 #endif
237 }
238 
Event(const Event & copy)239 Event::Event(const Event& copy)
240     : type_(copy.type_),
241       time_stamp_(copy.time_stamp_),
242       latency_(copy.latency_),
243       flags_(copy.flags_),
244       native_event_(CopyNativeEvent(copy.native_event_)),
245       delete_native_event_(true),
246       cancelable_(true),
247       target_(NULL),
248       phase_(EP_PREDISPATCH),
249       result_(ER_UNHANDLED),
250       source_device_id_(copy.source_device_id_) {
251   if (type_ < ET_LAST)
252     name_ = EventTypeName(type_);
253 }
254 
SetType(EventType type)255 void Event::SetType(EventType type) {
256   if (type_ < ET_LAST)
257     name_ = std::string();
258   type_ = type;
259   if (type_ < ET_LAST)
260     name_ = EventTypeName(type_);
261 }
262 
263 ////////////////////////////////////////////////////////////////////////////////
264 // CancelModeEvent
265 
CancelModeEvent()266 CancelModeEvent::CancelModeEvent()
267     : Event(ET_CANCEL_MODE, base::TimeDelta(), 0) {
268   set_cancelable(false);
269 }
270 
~CancelModeEvent()271 CancelModeEvent::~CancelModeEvent() {
272 }
273 
274 ////////////////////////////////////////////////////////////////////////////////
275 // LocatedEvent
276 
~LocatedEvent()277 LocatedEvent::~LocatedEvent() {
278 }
279 
LocatedEvent(const base::NativeEvent & native_event)280 LocatedEvent::LocatedEvent(const base::NativeEvent& native_event)
281     : Event(native_event,
282             EventTypeFromNative(native_event),
283             EventFlagsFromNative(native_event)),
284       location_(EventLocationFromNative(native_event)),
285       root_location_(location_) {
286 }
287 
LocatedEvent(EventType type,const gfx::PointF & location,const gfx::PointF & root_location,base::TimeDelta time_stamp,int flags)288 LocatedEvent::LocatedEvent(EventType type,
289                            const gfx::PointF& location,
290                            const gfx::PointF& root_location,
291                            base::TimeDelta time_stamp,
292                            int flags)
293     : Event(type, time_stamp, flags),
294       location_(location),
295       root_location_(root_location) {
296 }
297 
UpdateForRootTransform(const gfx::Transform & reversed_root_transform)298 void LocatedEvent::UpdateForRootTransform(
299     const gfx::Transform& reversed_root_transform) {
300   // Transform has to be done at root level.
301   gfx::Point3F p(location_);
302   reversed_root_transform.TransformPoint(&p);
303   location_ = p.AsPointF();
304   root_location_ = location_;
305 }
306 
307 ////////////////////////////////////////////////////////////////////////////////
308 // MouseEvent
309 
MouseEvent(const base::NativeEvent & native_event)310 MouseEvent::MouseEvent(const base::NativeEvent& native_event)
311     : LocatedEvent(native_event),
312       changed_button_flags_(
313           GetChangedMouseButtonFlagsFromNative(native_event)) {
314   if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED)
315     SetClickCount(GetRepeatCount(*this));
316 }
317 
MouseEvent(EventType type,const gfx::PointF & location,const gfx::PointF & root_location,int flags,int changed_button_flags)318 MouseEvent::MouseEvent(EventType type,
319                        const gfx::PointF& location,
320                        const gfx::PointF& root_location,
321                        int flags,
322                        int changed_button_flags)
323     : LocatedEvent(type, location, root_location, EventTimeForNow(), flags),
324       changed_button_flags_(changed_button_flags) {
325   if (this->type() == ET_MOUSE_MOVED && IsAnyButton())
326     SetType(ET_MOUSE_DRAGGED);
327 }
328 
329 // static
IsRepeatedClickEvent(const MouseEvent & event1,const MouseEvent & event2)330 bool MouseEvent::IsRepeatedClickEvent(
331     const MouseEvent& event1,
332     const MouseEvent& event2) {
333   // These values match the Windows defaults.
334   static const int kDoubleClickTimeMS = 500;
335   static const int kDoubleClickWidth = 4;
336   static const int kDoubleClickHeight = 4;
337 
338   if (event1.type() != ET_MOUSE_PRESSED ||
339       event2.type() != ET_MOUSE_PRESSED)
340     return false;
341 
342   // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks.
343   if ((event1.flags() & ~EF_IS_DOUBLE_CLICK) !=
344       (event2.flags() & ~EF_IS_DOUBLE_CLICK))
345     return false;
346 
347   base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp();
348 
349   if (time_difference.InMilliseconds() > kDoubleClickTimeMS)
350     return false;
351 
352   if (std::abs(event2.x() - event1.x()) > kDoubleClickWidth / 2)
353     return false;
354 
355   if (std::abs(event2.y() - event1.y()) > kDoubleClickHeight / 2)
356     return false;
357 
358   return true;
359 }
360 
361 // static
GetRepeatCount(const MouseEvent & event)362 int MouseEvent::GetRepeatCount(const MouseEvent& event) {
363   int click_count = 1;
364   if (last_click_event_) {
365     if (event.type() == ui::ET_MOUSE_RELEASED) {
366       if (event.changed_button_flags() ==
367               last_click_event_->changed_button_flags()) {
368         last_click_complete_ = true;
369         return last_click_event_->GetClickCount();
370       } else {
371         // If last_click_event_ has changed since this button was pressed
372         // return a click count of 1.
373         return click_count;
374       }
375     }
376     if (event.time_stamp() != last_click_event_->time_stamp())
377       last_click_complete_ = true;
378     if (!last_click_complete_ ||
379         IsX11SendEventTrue(event.native_event())) {
380       click_count = last_click_event_->GetClickCount();
381     } else if (IsRepeatedClickEvent(*last_click_event_, event)) {
382       click_count = last_click_event_->GetClickCount() + 1;
383     }
384     delete last_click_event_;
385   }
386   last_click_event_ = new MouseEvent(event);
387   last_click_complete_ = false;
388   if (click_count > 3)
389     click_count = 3;
390   last_click_event_->SetClickCount(click_count);
391   return click_count;
392 }
393 
ResetLastClickForTest()394 void MouseEvent::ResetLastClickForTest() {
395   if (last_click_event_) {
396     delete last_click_event_;
397     last_click_event_ = NULL;
398     last_click_complete_ = false;
399   }
400 }
401 
402 // static
403 MouseEvent* MouseEvent::last_click_event_ = NULL;
404 bool MouseEvent::last_click_complete_ = false;
405 
GetClickCount() const406 int MouseEvent::GetClickCount() const {
407   if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
408     return 0;
409 
410   if (flags() & EF_IS_TRIPLE_CLICK)
411     return 3;
412   else if (flags() & EF_IS_DOUBLE_CLICK)
413     return 2;
414   else
415     return 1;
416 }
417 
SetClickCount(int click_count)418 void MouseEvent::SetClickCount(int click_count) {
419   if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
420     return;
421 
422   DCHECK(click_count > 0);
423   DCHECK(click_count <= 3);
424 
425   int f = flags();
426   switch (click_count) {
427     case 1:
428       f &= ~EF_IS_DOUBLE_CLICK;
429       f &= ~EF_IS_TRIPLE_CLICK;
430       break;
431     case 2:
432       f |= EF_IS_DOUBLE_CLICK;
433       f &= ~EF_IS_TRIPLE_CLICK;
434       break;
435     case 3:
436       f &= ~EF_IS_DOUBLE_CLICK;
437       f |= EF_IS_TRIPLE_CLICK;
438       break;
439   }
440   set_flags(f);
441 }
442 
443 ////////////////////////////////////////////////////////////////////////////////
444 // MouseWheelEvent
445 
MouseWheelEvent(const base::NativeEvent & native_event)446 MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event)
447     : MouseEvent(native_event),
448       offset_(GetMouseWheelOffset(native_event)) {
449 }
450 
MouseWheelEvent(const ScrollEvent & scroll_event)451 MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event)
452     : MouseEvent(scroll_event),
453       offset_(scroll_event.x_offset(), scroll_event.y_offset()){
454   SetType(ET_MOUSEWHEEL);
455 }
456 
MouseWheelEvent(const MouseEvent & mouse_event,int x_offset,int y_offset)457 MouseWheelEvent::MouseWheelEvent(const MouseEvent& mouse_event,
458                                  int x_offset,
459                                  int y_offset)
460     : MouseEvent(mouse_event), offset_(x_offset, y_offset) {
461   DCHECK(type() == ET_MOUSEWHEEL);
462 }
463 
MouseWheelEvent(const MouseWheelEvent & mouse_wheel_event)464 MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event)
465     : MouseEvent(mouse_wheel_event),
466       offset_(mouse_wheel_event.offset()) {
467   DCHECK(type() == ET_MOUSEWHEEL);
468 }
469 
MouseWheelEvent(const gfx::Vector2d & offset,const gfx::PointF & location,const gfx::PointF & root_location,int flags,int changed_button_flags)470 MouseWheelEvent::MouseWheelEvent(const gfx::Vector2d& offset,
471                                  const gfx::PointF& location,
472                                  const gfx::PointF& root_location,
473                                  int flags,
474                                  int changed_button_flags)
475     : MouseEvent(ui::ET_MOUSEWHEEL, location, root_location, flags,
476                  changed_button_flags),
477       offset_(offset) {
478 }
479 
480 #if defined(OS_WIN)
481 // This value matches windows WHEEL_DELTA.
482 // static
483 const int MouseWheelEvent::kWheelDelta = 120;
484 #else
485 // This value matches GTK+ wheel scroll amount.
486 const int MouseWheelEvent::kWheelDelta = 53;
487 #endif
488 
UpdateForRootTransform(const gfx::Transform & inverted_root_transform)489 void MouseWheelEvent::UpdateForRootTransform(
490     const gfx::Transform& inverted_root_transform) {
491   LocatedEvent::UpdateForRootTransform(inverted_root_transform);
492   gfx::DecomposedTransform decomp;
493   bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
494   DCHECK(success);
495   if (decomp.scale[0])
496     offset_.set_x(offset_.x() * decomp.scale[0]);
497   if (decomp.scale[1])
498     offset_.set_y(offset_.y() * decomp.scale[1]);
499 }
500 
501 ////////////////////////////////////////////////////////////////////////////////
502 // TouchEvent
503 
TouchEvent(const base::NativeEvent & native_event)504 TouchEvent::TouchEvent(const base::NativeEvent& native_event)
505     : LocatedEvent(native_event),
506       touch_id_(GetTouchId(native_event)),
507       radius_x_(GetTouchRadiusX(native_event)),
508       radius_y_(GetTouchRadiusY(native_event)),
509       rotation_angle_(GetTouchAngle(native_event)),
510       force_(GetTouchForce(native_event)) {
511   latency()->AddLatencyNumberWithTimestamp(
512       INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
513       0,
514       0,
515       base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()),
516       1);
517 
518   latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
519 
520   if (type() == ET_TOUCH_PRESSED)
521     IncrementTouchIdRefCount(native_event);
522 }
523 
TouchEvent(EventType type,const gfx::PointF & location,int touch_id,base::TimeDelta time_stamp)524 TouchEvent::TouchEvent(EventType type,
525                        const gfx::PointF& location,
526                        int touch_id,
527                        base::TimeDelta time_stamp)
528     : LocatedEvent(type, location, location, time_stamp, 0),
529       touch_id_(touch_id),
530       radius_x_(0.0f),
531       radius_y_(0.0f),
532       rotation_angle_(0.0f),
533       force_(0.0f) {
534   latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
535 }
536 
TouchEvent(EventType type,const gfx::PointF & location,int flags,int touch_id,base::TimeDelta time_stamp,float radius_x,float radius_y,float angle,float force)537 TouchEvent::TouchEvent(EventType type,
538                        const gfx::PointF& location,
539                        int flags,
540                        int touch_id,
541                        base::TimeDelta time_stamp,
542                        float radius_x,
543                        float radius_y,
544                        float angle,
545                        float force)
546     : LocatedEvent(type, location, location, time_stamp, flags),
547       touch_id_(touch_id),
548       radius_x_(radius_x),
549       radius_y_(radius_y),
550       rotation_angle_(angle),
551       force_(force) {
552   latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
553 }
554 
~TouchEvent()555 TouchEvent::~TouchEvent() {
556   // In ctor TouchEvent(native_event) we call GetTouchId() which in X11
557   // platform setups the tracking_id to slot mapping. So in dtor here,
558   // if this touch event is a release event, we clear the mapping accordingly.
559   if (HasNativeEvent())
560     ClearTouchIdIfReleased(native_event());
561 }
562 
UpdateForRootTransform(const gfx::Transform & inverted_root_transform)563 void TouchEvent::UpdateForRootTransform(
564     const gfx::Transform& inverted_root_transform) {
565   LocatedEvent::UpdateForRootTransform(inverted_root_transform);
566   gfx::DecomposedTransform decomp;
567   bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
568   DCHECK(success);
569   if (decomp.scale[0])
570     radius_x_ *= decomp.scale[0];
571   if (decomp.scale[1])
572     radius_y_ *= decomp.scale[1];
573 }
574 
575 ////////////////////////////////////////////////////////////////////////////////
576 // KeyEvent
577 
578 // static
579 KeyEvent* KeyEvent::last_key_event_ = NULL;
580 
581 // static
IsRepeated(const KeyEvent & event)582 bool KeyEvent::IsRepeated(const KeyEvent& event) {
583   // A safe guard in case if there were continous key pressed events that are
584   // not auto repeat.
585   const int kMaxAutoRepeatTimeMs = 2000;
586   // Ignore key events that have non standard state masks as it may be
587   // reposted by an IME. IBUS-GTK uses this field to detect the
588   // re-posted event for example. crbug.com/385873.
589   if (X11EventHasNonStandardState(event.native_event()))
590     return false;
591   if (event.is_char())
592     return false;
593   if (event.type() == ui::ET_KEY_RELEASED) {
594     delete last_key_event_;
595     last_key_event_ = NULL;
596     return false;
597   }
598   CHECK_EQ(ui::ET_KEY_PRESSED, event.type());
599   if (!last_key_event_) {
600     last_key_event_ = new KeyEvent(event);
601     return false;
602   }
603   if (event.key_code() == last_key_event_->key_code() &&
604       event.flags() == last_key_event_->flags() &&
605       (event.time_stamp() - last_key_event_->time_stamp()).InMilliseconds() <
606       kMaxAutoRepeatTimeMs) {
607     return true;
608   }
609   delete last_key_event_;
610   last_key_event_ = new KeyEvent(event);
611   return false;
612 }
613 
KeyEvent(const base::NativeEvent & native_event)614 KeyEvent::KeyEvent(const base::NativeEvent& native_event)
615     : Event(native_event,
616             EventTypeFromNative(native_event),
617             EventFlagsFromNative(native_event)),
618       key_code_(KeyboardCodeFromNative(native_event)),
619       code_(CodeFromNative(native_event)),
620       is_char_(IsCharFromNative(native_event)),
621       platform_keycode_(PlatformKeycodeFromNative(native_event)),
622       character_(0) {
623   if (IsRepeated(*this))
624     set_flags(flags() | ui::EF_IS_REPEAT);
625 
626 #if defined(USE_X11)
627   NormalizeFlags();
628 #endif
629 #if defined(OS_WIN)
630   // Only Windows has native character events.
631   if (is_char_)
632     character_ = native_event.wParam;
633 #endif
634 }
635 
KeyEvent(EventType type,KeyboardCode key_code,int flags)636 KeyEvent::KeyEvent(EventType type,
637                    KeyboardCode key_code,
638                    int flags)
639     : Event(type, EventTimeForNow(), flags),
640       key_code_(key_code),
641       is_char_(false),
642       platform_keycode_(0),
643       character_() {
644 }
645 
KeyEvent(EventType type,KeyboardCode key_code,const std::string & code,int flags)646 KeyEvent::KeyEvent(EventType type,
647                    KeyboardCode key_code,
648                    const std::string& code,
649                    int flags)
650     : Event(type, EventTimeForNow(), flags),
651       key_code_(key_code),
652       code_(code),
653       is_char_(false),
654       platform_keycode_(0),
655       character_(0) {
656 }
657 
KeyEvent(base::char16 character,KeyboardCode key_code,int flags)658 KeyEvent::KeyEvent(base::char16 character, KeyboardCode key_code, int flags)
659     : Event(ET_KEY_PRESSED, EventTimeForNow(), flags),
660       key_code_(key_code),
661       code_(""),
662       is_char_(true),
663       platform_keycode_(0),
664       character_(character) {
665 }
666 
KeyEvent(const KeyEvent & rhs)667 KeyEvent::KeyEvent(const KeyEvent& rhs)
668     : Event(rhs),
669       key_code_(rhs.key_code_),
670       code_(rhs.code_),
671       is_char_(rhs.is_char_),
672       platform_keycode_(rhs.platform_keycode_),
673       character_(rhs.character_) {
674   if (rhs.extended_key_event_data_)
675     extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone());
676 }
677 
operator =(const KeyEvent & rhs)678 KeyEvent& KeyEvent::operator=(const KeyEvent& rhs) {
679   if (this != &rhs) {
680     Event::operator=(rhs);
681     key_code_ = rhs.key_code_;
682     code_ = rhs.code_;
683     is_char_ = rhs.is_char_;
684     platform_keycode_ = rhs.platform_keycode_;
685     character_ = rhs.character_;
686 
687     if (rhs.extended_key_event_data_)
688       extended_key_event_data_.reset(rhs.extended_key_event_data_->Clone());
689   }
690   return *this;
691 }
692 
~KeyEvent()693 KeyEvent::~KeyEvent() {}
694 
SetExtendedKeyEventData(scoped_ptr<ExtendedKeyEventData> data)695 void KeyEvent::SetExtendedKeyEventData(scoped_ptr<ExtendedKeyEventData> data) {
696   extended_key_event_data_ = data.Pass();
697 }
698 
GetCharacter() const699 base::char16 KeyEvent::GetCharacter() const {
700   if (is_char_ || character_)
701     return character_;
702 
703   // TODO(kpschoedel): streamline these cases after settling Ozone
704   // positional coding.
705 #if defined(OS_WIN)
706   // Native Windows character events always have is_char_ == true,
707   // so this is a synthetic or native keystroke event.
708   character_ = GetCharacterFromKeyCode(key_code_, flags());
709   return character_;
710 #elif defined(USE_X11)
711   if (!native_event()) {
712     character_ = GetCharacterFromKeyCode(key_code_, flags());
713     return character_;
714   }
715 
716   DCHECK(native_event()->type == KeyPress ||
717          native_event()->type == KeyRelease ||
718          (native_event()->type == GenericEvent &&
719           (native_event()->xgeneric.evtype == XI_KeyPress ||
720            native_event()->xgeneric.evtype == XI_KeyRelease)));
721 
722   // When a control key is held, prefer ASCII characters to non ASCII
723   // characters in order to use it for shortcut keys.  GetCharacterFromKeyCode
724   // returns 'a' for VKEY_A even if the key is actually bound to 'à' in X11.
725   // GetCharacterFromXEvent returns 'à' in that case.
726   return IsControlDown() ?
727       GetCharacterFromKeyCode(key_code_, flags()) :
728       GetCharacterFromXEvent(native_event());
729 #else
730   if (native_event()) {
731     DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED ||
732            EventTypeFromNative(native_event()) == ET_KEY_RELEASED);
733   }
734 
735   return GetCharacterFromKeyCode(key_code_, flags());
736 #endif
737 }
738 
GetText() const739 base::char16 KeyEvent::GetText() const {
740   if ((flags() & EF_CONTROL_DOWN) != 0) {
741     return GetControlCharacterForKeycode(key_code_,
742                                          (flags() & EF_SHIFT_DOWN) != 0);
743   }
744   return GetUnmodifiedText();
745 }
746 
GetUnmodifiedText() const747 base::char16 KeyEvent::GetUnmodifiedText() const {
748   if (!is_char_ && (key_code_ == VKEY_RETURN))
749     return '\r';
750   return GetCharacter();
751 }
752 
IsUnicodeKeyCode() const753 bool KeyEvent::IsUnicodeKeyCode() const {
754 #if defined(OS_WIN)
755   if (!IsAltDown())
756     return false;
757   const int key = key_code();
758   if (key >= VKEY_NUMPAD0 && key <= VKEY_NUMPAD9)
759     return true;
760   // Check whether the user is using the numeric keypad with num-lock off.
761   // In that case, EF_EXTENDED will not be set; if it is set, the key event
762   // originated from the relevant non-numpad dedicated key, e.g. [Insert].
763   return (!(flags() & EF_EXTENDED) &&
764           (key == VKEY_INSERT || key == VKEY_END  || key == VKEY_DOWN ||
765            key == VKEY_NEXT   || key == VKEY_LEFT || key == VKEY_CLEAR ||
766            key == VKEY_RIGHT  || key == VKEY_HOME || key == VKEY_UP ||
767            key == VKEY_PRIOR));
768 #else
769   return false;
770 #endif
771 }
772 
NormalizeFlags()773 void KeyEvent::NormalizeFlags() {
774   int mask = 0;
775   switch (key_code()) {
776     case VKEY_CONTROL:
777       mask = EF_CONTROL_DOWN;
778       break;
779     case VKEY_SHIFT:
780       mask = EF_SHIFT_DOWN;
781       break;
782     case VKEY_MENU:
783       mask = EF_ALT_DOWN;
784       break;
785     case VKEY_CAPITAL:
786       mask = EF_CAPS_LOCK_DOWN;
787       break;
788     default:
789       return;
790   }
791   if (type() == ET_KEY_PRESSED)
792     set_flags(flags() | mask);
793   else
794     set_flags(flags() & ~mask);
795 }
796 
IsTranslated() const797 bool KeyEvent::IsTranslated() const {
798   switch (type()) {
799     case ET_KEY_PRESSED:
800     case ET_KEY_RELEASED:
801       return false;
802     case ET_TRANSLATED_KEY_PRESS:
803     case ET_TRANSLATED_KEY_RELEASE:
804       return true;
805     default:
806       NOTREACHED();
807       return false;
808   }
809 }
810 
SetTranslated(bool translated)811 void KeyEvent::SetTranslated(bool translated) {
812   switch (type()) {
813     case ET_KEY_PRESSED:
814     case ET_TRANSLATED_KEY_PRESS:
815       SetType(translated ? ET_TRANSLATED_KEY_PRESS : ET_KEY_PRESSED);
816       break;
817     case ET_KEY_RELEASED:
818     case ET_TRANSLATED_KEY_RELEASE:
819       SetType(translated ? ET_TRANSLATED_KEY_RELEASE : ET_KEY_RELEASED);
820       break;
821     default:
822       NOTREACHED();
823   }
824 }
825 
IsRightSideKey() const826 bool KeyEvent::IsRightSideKey() const {
827   switch (key_code_) {
828     case VKEY_CONTROL:
829     case VKEY_SHIFT:
830     case VKEY_MENU:
831     case VKEY_LWIN:
832 #if defined(USE_X11)
833       // Under X11, setting code_ requires platform-dependent information, and
834       // currently assumes that X keycodes are based on Linux evdev keycodes.
835       // In certain test environments this is not the case, and code_ is not
836       // set accurately, so we need a different mechanism. Fortunately X11 key
837       // mapping preserves the left-right distinction, so testing keysyms works
838       // if the value is available (as it is for all X11 native-based events).
839       if (platform_keycode_) {
840         return (platform_keycode_ == XK_Shift_R) ||
841                (platform_keycode_ == XK_Control_R) ||
842                (platform_keycode_ == XK_Alt_R) ||
843                (platform_keycode_ == XK_Meta_R) ||
844                (platform_keycode_ == XK_Super_R) ||
845                (platform_keycode_ == XK_Hyper_R);
846       }
847       // Fall through to the generic code if we have no platform_keycode_.
848       // Under X11, this must be a synthetic event, so we can require that
849       // code_ be set correctly.
850 #endif
851       return ((code_.size() > 5) &&
852               (code_.compare(code_.size() - 5, 5, "Right", 5)) == 0);
853     default:
854       return false;
855   }
856 }
857 
GetLocatedWindowsKeyboardCode() const858 KeyboardCode KeyEvent::GetLocatedWindowsKeyboardCode() const {
859   switch (key_code_) {
860     case VKEY_SHIFT:
861       return IsRightSideKey() ? VKEY_RSHIFT : VKEY_LSHIFT;
862     case VKEY_CONTROL:
863       return IsRightSideKey() ? VKEY_RCONTROL : VKEY_LCONTROL;
864     case VKEY_MENU:
865       return IsRightSideKey() ? VKEY_RMENU : VKEY_LMENU;
866     case VKEY_LWIN:
867       return IsRightSideKey() ? VKEY_RWIN : VKEY_LWIN;
868     // TODO(kpschoedel): EF_NUMPAD_KEY is present only on X11. Currently this
869     // function is only called on X11. Likely the tests here will be replaced
870     // with a DOM-based code enumeration test in the course of Ozone
871     // platform-indpendent key event work.
872     case VKEY_0:
873       return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD0 : VKEY_0;
874     case VKEY_1:
875       return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD1 : VKEY_1;
876     case VKEY_2:
877       return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD2 : VKEY_2;
878     case VKEY_3:
879       return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD3 : VKEY_3;
880     case VKEY_4:
881       return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD4 : VKEY_4;
882     case VKEY_5:
883       return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD5 : VKEY_5;
884     case VKEY_6:
885       return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD6 : VKEY_6;
886     case VKEY_7:
887       return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD7 : VKEY_7;
888     case VKEY_8:
889       return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD8 : VKEY_8;
890     case VKEY_9:
891       return (flags() & EF_NUMPAD_KEY) ? VKEY_NUMPAD9 : VKEY_9;
892     default:
893       return key_code_;
894   }
895 }
896 
GetConflatedWindowsKeyCode() const897 uint16 KeyEvent::GetConflatedWindowsKeyCode() const {
898   if (is_char_)
899     return character_;
900   return key_code_;
901 }
902 
903 ////////////////////////////////////////////////////////////////////////////////
904 // ScrollEvent
905 
ScrollEvent(const base::NativeEvent & native_event)906 ScrollEvent::ScrollEvent(const base::NativeEvent& native_event)
907     : MouseEvent(native_event) {
908   if (type() == ET_SCROLL) {
909     GetScrollOffsets(native_event,
910                      &x_offset_, &y_offset_,
911                      &x_offset_ordinal_, &y_offset_ordinal_,
912                      &finger_count_);
913   } else if (type() == ET_SCROLL_FLING_START ||
914              type() == ET_SCROLL_FLING_CANCEL) {
915     GetFlingData(native_event,
916                  &x_offset_, &y_offset_,
917                  &x_offset_ordinal_, &y_offset_ordinal_,
918                  NULL);
919   } else {
920     NOTREACHED() << "Unexpected event type " << type()
921         << " when constructing a ScrollEvent.";
922   }
923 }
924 
ScrollEvent(EventType type,const gfx::PointF & location,base::TimeDelta time_stamp,int flags,float x_offset,float y_offset,float x_offset_ordinal,float y_offset_ordinal,int finger_count)925 ScrollEvent::ScrollEvent(EventType type,
926                          const gfx::PointF& location,
927                          base::TimeDelta time_stamp,
928                          int flags,
929                          float x_offset,
930                          float y_offset,
931                          float x_offset_ordinal,
932                          float y_offset_ordinal,
933                          int finger_count)
934     : MouseEvent(type, location, location, flags, 0),
935       x_offset_(x_offset),
936       y_offset_(y_offset),
937       x_offset_ordinal_(x_offset_ordinal),
938       y_offset_ordinal_(y_offset_ordinal),
939       finger_count_(finger_count) {
940   set_time_stamp(time_stamp);
941   CHECK(IsScrollEvent());
942 }
943 
Scale(const float factor)944 void ScrollEvent::Scale(const float factor) {
945   x_offset_ *= factor;
946   y_offset_ *= factor;
947   x_offset_ordinal_ *= factor;
948   y_offset_ordinal_ *= factor;
949 }
950 
951 ////////////////////////////////////////////////////////////////////////////////
952 // GestureEvent
953 
GestureEvent(float x,float y,int flags,base::TimeDelta time_stamp,const GestureEventDetails & details)954 GestureEvent::GestureEvent(float x,
955                            float y,
956                            int flags,
957                            base::TimeDelta time_stamp,
958                            const GestureEventDetails& details)
959     : LocatedEvent(details.type(),
960                    gfx::PointF(x, y),
961                    gfx::PointF(x, y),
962                    time_stamp,
963                    flags | EF_FROM_TOUCH),
964       details_(details) {
965 }
966 
~GestureEvent()967 GestureEvent::~GestureEvent() {
968 }
969 
970 }  // namespace ui
971