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