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/Xlib.h>
9 #endif
10
11 #include <cmath>
12 #include <cstring>
13
14 #include "base/metrics/histogram.h"
15 #include "base/strings/stringprintf.h"
16 #include "ui/events/event_utils.h"
17 #include "ui/events/keycodes/keyboard_code_conversion.h"
18 #include "ui/gfx/point3_f.h"
19 #include "ui/gfx/point_conversions.h"
20 #include "ui/gfx/transform.h"
21 #include "ui/gfx/transform_util.h"
22
23 #if defined(USE_X11)
24 #include "ui/events/keycodes/keyboard_code_conversion_x.h"
25 #elif defined(USE_OZONE)
26 #include "ui/events/keycodes/keyboard_code_conversion.h"
27 #endif
28
29 namespace {
30
CopyNativeEvent(const base::NativeEvent & event)31 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
32 #if defined(USE_X11)
33 if (!event || event->type == GenericEvent)
34 return NULL;
35 XEvent* copy = new XEvent;
36 *copy = *event;
37 return copy;
38 #elif defined(OS_WIN)
39 return event;
40 #elif defined(USE_OZONE)
41 return NULL;
42 #else
43 NOTREACHED() <<
44 "Don't know how to copy base::NativeEvent for this platform";
45 return NULL;
46 #endif
47 }
48
EventTypeName(ui::EventType type)49 std::string EventTypeName(ui::EventType type) {
50 #define RETURN_IF_TYPE(t) if (type == ui::t) return #t
51 #define CASE_TYPE(t) case ui::t: return #t
52 switch (type) {
53 CASE_TYPE(ET_UNKNOWN);
54 CASE_TYPE(ET_MOUSE_PRESSED);
55 CASE_TYPE(ET_MOUSE_DRAGGED);
56 CASE_TYPE(ET_MOUSE_RELEASED);
57 CASE_TYPE(ET_MOUSE_MOVED);
58 CASE_TYPE(ET_MOUSE_ENTERED);
59 CASE_TYPE(ET_MOUSE_EXITED);
60 CASE_TYPE(ET_KEY_PRESSED);
61 CASE_TYPE(ET_KEY_RELEASED);
62 CASE_TYPE(ET_MOUSEWHEEL);
63 CASE_TYPE(ET_MOUSE_CAPTURE_CHANGED);
64 CASE_TYPE(ET_TOUCH_RELEASED);
65 CASE_TYPE(ET_TOUCH_PRESSED);
66 CASE_TYPE(ET_TOUCH_MOVED);
67 CASE_TYPE(ET_TOUCH_STATIONARY);
68 CASE_TYPE(ET_TOUCH_CANCELLED);
69 CASE_TYPE(ET_DROP_TARGET_EVENT);
70 CASE_TYPE(ET_TRANSLATED_KEY_PRESS);
71 CASE_TYPE(ET_TRANSLATED_KEY_RELEASE);
72 CASE_TYPE(ET_GESTURE_SCROLL_BEGIN);
73 CASE_TYPE(ET_GESTURE_SCROLL_END);
74 CASE_TYPE(ET_GESTURE_SCROLL_UPDATE);
75 CASE_TYPE(ET_GESTURE_SHOW_PRESS);
76 CASE_TYPE(ET_GESTURE_TAP);
77 CASE_TYPE(ET_GESTURE_TAP_DOWN);
78 CASE_TYPE(ET_GESTURE_TAP_CANCEL);
79 CASE_TYPE(ET_GESTURE_BEGIN);
80 CASE_TYPE(ET_GESTURE_END);
81 CASE_TYPE(ET_GESTURE_TWO_FINGER_TAP);
82 CASE_TYPE(ET_GESTURE_PINCH_BEGIN);
83 CASE_TYPE(ET_GESTURE_PINCH_END);
84 CASE_TYPE(ET_GESTURE_PINCH_UPDATE);
85 CASE_TYPE(ET_GESTURE_LONG_PRESS);
86 CASE_TYPE(ET_GESTURE_LONG_TAP);
87 CASE_TYPE(ET_GESTURE_MULTIFINGER_SWIPE);
88 CASE_TYPE(ET_SCROLL);
89 CASE_TYPE(ET_SCROLL_FLING_START);
90 CASE_TYPE(ET_SCROLL_FLING_CANCEL);
91 CASE_TYPE(ET_CANCEL_MODE);
92 CASE_TYPE(ET_UMA_DATA);
93 case ui::ET_LAST: NOTREACHED(); return std::string();
94 // Don't include default, so that we get an error when new type is added.
95 }
96 #undef CASE_TYPE
97
98 NOTREACHED();
99 return std::string();
100 }
101
IsX11SendEventTrue(const base::NativeEvent & event)102 bool IsX11SendEventTrue(const base::NativeEvent& event) {
103 #if defined(USE_X11)
104 if (event && event->xany.send_event)
105 return true;
106 #endif
107 return false;
108 }
109
110 } // namespace
111
112 namespace ui {
113
114 ////////////////////////////////////////////////////////////////////////////////
115 // Event
116
~Event()117 Event::~Event() {
118 #if defined(USE_X11)
119 if (delete_native_event_)
120 delete native_event_;
121 #endif
122 }
123
HasNativeEvent() const124 bool Event::HasNativeEvent() const {
125 base::NativeEvent null_event;
126 std::memset(&null_event, 0, sizeof(null_event));
127 return !!std::memcmp(&native_event_, &null_event, sizeof(null_event));
128 }
129
StopPropagation()130 void Event::StopPropagation() {
131 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
132 // events.
133 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
134 CHECK(cancelable_);
135 result_ = static_cast<EventResult>(result_ | ER_CONSUMED);
136 }
137
SetHandled()138 void Event::SetHandled() {
139 // TODO(sad): Re-enable these checks once View uses dispatcher to dispatch
140 // events.
141 // CHECK(phase_ != EP_PREDISPATCH && phase_ != EP_POSTDISPATCH);
142 CHECK(cancelable_);
143 result_ = static_cast<EventResult>(result_ | ER_HANDLED);
144 }
145
Event(EventType type,base::TimeDelta time_stamp,int flags)146 Event::Event(EventType type, base::TimeDelta time_stamp, int flags)
147 : type_(type),
148 time_stamp_(time_stamp),
149 flags_(flags),
150 #if defined(USE_X11)
151 native_event_(NULL),
152 #endif
153 delete_native_event_(false),
154 cancelable_(true),
155 target_(NULL),
156 phase_(EP_PREDISPATCH),
157 result_(ER_UNHANDLED) {
158 if (type_ < ET_LAST)
159 name_ = EventTypeName(type_);
160 Init();
161 }
162
Event(const base::NativeEvent & native_event,EventType type,int flags)163 Event::Event(const base::NativeEvent& native_event,
164 EventType type,
165 int flags)
166 : type_(type),
167 time_stamp_(EventTimeFromNative(native_event)),
168 flags_(flags),
169 delete_native_event_(false),
170 cancelable_(true),
171 target_(NULL),
172 phase_(EP_PREDISPATCH),
173 result_(ER_UNHANDLED) {
174 base::TimeDelta delta = EventTimeForNow() - time_stamp_;
175 if (type_ < ET_LAST)
176 name_ = EventTypeName(type_);
177 UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser",
178 delta.InMicroseconds(), 0, 1000000, 100);
179 std::string name_for_event =
180 base::StringPrintf("Event.Latency.Browser.%s", name_.c_str());
181 base::HistogramBase* counter_for_type =
182 base::Histogram::FactoryGet(
183 name_for_event,
184 0,
185 1000000,
186 100,
187 base::HistogramBase::kUmaTargetedHistogramFlag);
188 counter_for_type->Add(delta.InMicroseconds());
189 InitWithNativeEvent(native_event);
190 }
191
Event(const Event & copy)192 Event::Event(const Event& copy)
193 : type_(copy.type_),
194 time_stamp_(copy.time_stamp_),
195 latency_(copy.latency_),
196 flags_(copy.flags_),
197 native_event_(::CopyNativeEvent(copy.native_event_)),
198 delete_native_event_(false),
199 cancelable_(true),
200 target_(NULL),
201 phase_(EP_PREDISPATCH),
202 result_(ER_UNHANDLED) {
203 if (type_ < ET_LAST)
204 name_ = EventTypeName(type_);
205 #if defined(USE_X11)
206 if (native_event_)
207 delete_native_event_ = true;
208 #endif
209 }
210
SetType(EventType type)211 void Event::SetType(EventType type) {
212 if (type_ < ET_LAST)
213 name_ = std::string();
214 type_ = type;
215 if (type_ < ET_LAST)
216 name_ = EventTypeName(type_);
217 }
218
Init()219 void Event::Init() {
220 std::memset(&native_event_, 0, sizeof(native_event_));
221 }
222
InitWithNativeEvent(const base::NativeEvent & native_event)223 void Event::InitWithNativeEvent(const base::NativeEvent& native_event) {
224 native_event_ = native_event;
225 }
226
227 ////////////////////////////////////////////////////////////////////////////////
228 // CancelModeEvent
229
CancelModeEvent()230 CancelModeEvent::CancelModeEvent()
231 : Event(ET_CANCEL_MODE, base::TimeDelta(), 0) {
232 set_cancelable(false);
233 }
234
~CancelModeEvent()235 CancelModeEvent::~CancelModeEvent() {
236 }
237
238 ////////////////////////////////////////////////////////////////////////////////
239 // LocatedEvent
240
~LocatedEvent()241 LocatedEvent::~LocatedEvent() {
242 }
243
LocatedEvent(const base::NativeEvent & native_event)244 LocatedEvent::LocatedEvent(const base::NativeEvent& native_event)
245 : Event(native_event,
246 EventTypeFromNative(native_event),
247 EventFlagsFromNative(native_event)),
248 location_(EventLocationFromNative(native_event)),
249 root_location_(location_) {
250 }
251
LocatedEvent(EventType type,const gfx::Point & location,const gfx::Point & root_location,base::TimeDelta time_stamp,int flags)252 LocatedEvent::LocatedEvent(EventType type,
253 const gfx::Point& location,
254 const gfx::Point& root_location,
255 base::TimeDelta time_stamp,
256 int flags)
257 : Event(type, time_stamp, flags),
258 location_(location),
259 root_location_(root_location) {
260 }
261
UpdateForRootTransform(const gfx::Transform & reversed_root_transform)262 void LocatedEvent::UpdateForRootTransform(
263 const gfx::Transform& reversed_root_transform) {
264 // Transform has to be done at root level.
265 gfx::Point3F p(location_);
266 reversed_root_transform.TransformPoint(&p);
267 root_location_ = location_ = gfx::ToFlooredPoint(p.AsPointF());
268 }
269
270 ////////////////////////////////////////////////////////////////////////////////
271 // MouseEvent
272
MouseEvent(const base::NativeEvent & native_event)273 MouseEvent::MouseEvent(const base::NativeEvent& native_event)
274 : LocatedEvent(native_event),
275 changed_button_flags_(
276 GetChangedMouseButtonFlagsFromNative(native_event)) {
277 if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED)
278 SetClickCount(GetRepeatCount(*this));
279 }
280
MouseEvent(EventType type,const gfx::Point & location,const gfx::Point & root_location,int flags)281 MouseEvent::MouseEvent(EventType type,
282 const gfx::Point& location,
283 const gfx::Point& root_location,
284 int flags)
285 : LocatedEvent(type, location, root_location, EventTimeForNow(), flags),
286 changed_button_flags_(0) {
287 if (this->type() == ET_MOUSE_MOVED && IsAnyButton())
288 SetType(ET_MOUSE_DRAGGED);
289 }
290
291 // static
IsRepeatedClickEvent(const MouseEvent & event1,const MouseEvent & event2)292 bool MouseEvent::IsRepeatedClickEvent(
293 const MouseEvent& event1,
294 const MouseEvent& event2) {
295 // These values match the Windows defaults.
296 static const int kDoubleClickTimeMS = 500;
297 static const int kDoubleClickWidth = 4;
298 static const int kDoubleClickHeight = 4;
299
300 if (event1.type() != ET_MOUSE_PRESSED ||
301 event2.type() != ET_MOUSE_PRESSED)
302 return false;
303
304 // Compare flags, but ignore EF_IS_DOUBLE_CLICK to allow triple clicks.
305 if ((event1.flags() & ~EF_IS_DOUBLE_CLICK) !=
306 (event2.flags() & ~EF_IS_DOUBLE_CLICK))
307 return false;
308
309 base::TimeDelta time_difference = event2.time_stamp() - event1.time_stamp();
310
311 if (time_difference.InMilliseconds() > kDoubleClickTimeMS)
312 return false;
313
314 if (abs(event2.x() - event1.x()) > kDoubleClickWidth / 2)
315 return false;
316
317 if (abs(event2.y() - event1.y()) > kDoubleClickHeight / 2)
318 return false;
319
320 return true;
321 }
322
323 // static
GetRepeatCount(const MouseEvent & event)324 int MouseEvent::GetRepeatCount(const MouseEvent& event) {
325 int click_count = 1;
326 if (last_click_event_) {
327 if (event.type() == ui::ET_MOUSE_RELEASED)
328 return last_click_event_->GetClickCount();
329 if (IsX11SendEventTrue(event.native_event()))
330 click_count = last_click_event_->GetClickCount();
331 else if (IsRepeatedClickEvent(*last_click_event_, event))
332 click_count = last_click_event_->GetClickCount() + 1;
333 delete last_click_event_;
334 }
335 last_click_event_ = new MouseEvent(event);
336 if (click_count > 3)
337 click_count = 3;
338 last_click_event_->SetClickCount(click_count);
339 return click_count;
340 }
341
342 // static
343 MouseEvent* MouseEvent::last_click_event_ = NULL;
344
GetClickCount() const345 int MouseEvent::GetClickCount() const {
346 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
347 return 0;
348
349 if (flags() & EF_IS_TRIPLE_CLICK)
350 return 3;
351 else if (flags() & EF_IS_DOUBLE_CLICK)
352 return 2;
353 else
354 return 1;
355 }
356
SetClickCount(int click_count)357 void MouseEvent::SetClickCount(int click_count) {
358 if (type() != ET_MOUSE_PRESSED && type() != ET_MOUSE_RELEASED)
359 return;
360
361 DCHECK(click_count > 0);
362 DCHECK(click_count <= 3);
363
364 int f = flags();
365 switch (click_count) {
366 case 1:
367 f &= ~EF_IS_DOUBLE_CLICK;
368 f &= ~EF_IS_TRIPLE_CLICK;
369 break;
370 case 2:
371 f |= EF_IS_DOUBLE_CLICK;
372 f &= ~EF_IS_TRIPLE_CLICK;
373 break;
374 case 3:
375 f &= ~EF_IS_DOUBLE_CLICK;
376 f |= EF_IS_TRIPLE_CLICK;
377 break;
378 }
379 set_flags(f);
380 }
381
382 ////////////////////////////////////////////////////////////////////////////////
383 // MouseWheelEvent
384
MouseWheelEvent(const base::NativeEvent & native_event)385 MouseWheelEvent::MouseWheelEvent(const base::NativeEvent& native_event)
386 : MouseEvent(native_event),
387 offset_(GetMouseWheelOffset(native_event)) {
388 }
389
MouseWheelEvent(const ScrollEvent & scroll_event)390 MouseWheelEvent::MouseWheelEvent(const ScrollEvent& scroll_event)
391 : MouseEvent(scroll_event),
392 offset_(scroll_event.x_offset(), scroll_event.y_offset()){
393 SetType(ET_MOUSEWHEEL);
394 }
395
MouseWheelEvent(const MouseEvent & mouse_event,int x_offset,int y_offset)396 MouseWheelEvent::MouseWheelEvent(const MouseEvent& mouse_event,
397 int x_offset,
398 int y_offset)
399 : MouseEvent(mouse_event), offset_(x_offset, y_offset) {
400 DCHECK(type() == ET_MOUSEWHEEL);
401 }
402
MouseWheelEvent(const MouseWheelEvent & mouse_wheel_event)403 MouseWheelEvent::MouseWheelEvent(const MouseWheelEvent& mouse_wheel_event)
404 : MouseEvent(mouse_wheel_event),
405 offset_(mouse_wheel_event.offset()) {
406 DCHECK(type() == ET_MOUSEWHEEL);
407 }
408
409 #if defined(OS_WIN)
410 // This value matches windows WHEEL_DELTA.
411 // static
412 const int MouseWheelEvent::kWheelDelta = 120;
413 #else
414 // This value matches GTK+ wheel scroll amount.
415 const int MouseWheelEvent::kWheelDelta = 53;
416 #endif
417
UpdateForRootTransform(const gfx::Transform & inverted_root_transform)418 void MouseWheelEvent::UpdateForRootTransform(
419 const gfx::Transform& inverted_root_transform) {
420 LocatedEvent::UpdateForRootTransform(inverted_root_transform);
421 gfx::DecomposedTransform decomp;
422 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
423 DCHECK(success);
424 if (decomp.scale[0])
425 offset_.set_x(offset_.x() * decomp.scale[0]);
426 if (decomp.scale[1])
427 offset_.set_y(offset_.y() * decomp.scale[1]);
428 }
429
430 ////////////////////////////////////////////////////////////////////////////////
431 // TouchEvent
432
TouchEvent(const base::NativeEvent & native_event)433 TouchEvent::TouchEvent(const base::NativeEvent& native_event)
434 : LocatedEvent(native_event),
435 touch_id_(GetTouchId(native_event)),
436 radius_x_(GetTouchRadiusX(native_event)),
437 radius_y_(GetTouchRadiusY(native_event)),
438 rotation_angle_(GetTouchAngle(native_event)),
439 force_(GetTouchForce(native_event)) {
440 latency()->AddLatencyNumberWithTimestamp(
441 INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
442 0,
443 0,
444 base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()),
445 1,
446 true);
447 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
448 }
449
TouchEvent(EventType type,const gfx::Point & location,int touch_id,base::TimeDelta time_stamp)450 TouchEvent::TouchEvent(EventType type,
451 const gfx::Point& location,
452 int touch_id,
453 base::TimeDelta time_stamp)
454 : LocatedEvent(type, location, location, time_stamp, 0),
455 touch_id_(touch_id),
456 radius_x_(0.0f),
457 radius_y_(0.0f),
458 rotation_angle_(0.0f),
459 force_(0.0f) {
460 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
461 }
462
TouchEvent(EventType type,const gfx::Point & location,int flags,int touch_id,base::TimeDelta time_stamp,float radius_x,float radius_y,float angle,float force)463 TouchEvent::TouchEvent(EventType type,
464 const gfx::Point& location,
465 int flags,
466 int touch_id,
467 base::TimeDelta time_stamp,
468 float radius_x,
469 float radius_y,
470 float angle,
471 float force)
472 : LocatedEvent(type, location, location, time_stamp, flags),
473 touch_id_(touch_id),
474 radius_x_(radius_x),
475 radius_y_(radius_y),
476 rotation_angle_(angle),
477 force_(force) {
478 latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
479 }
480
~TouchEvent()481 TouchEvent::~TouchEvent() {
482 // In ctor TouchEvent(native_event) we call GetTouchId() which in X11
483 // platform setups the tracking_id to slot mapping. So in dtor here,
484 // if this touch event is a release event, we clear the mapping accordingly.
485 if (HasNativeEvent())
486 ClearTouchIdIfReleased(native_event());
487 }
488
Relocate(const gfx::Point & origin)489 void TouchEvent::Relocate(const gfx::Point& origin) {
490 location_ -= origin.OffsetFromOrigin();
491 root_location_ -= origin.OffsetFromOrigin();
492 }
493
UpdateForRootTransform(const gfx::Transform & inverted_root_transform)494 void TouchEvent::UpdateForRootTransform(
495 const gfx::Transform& inverted_root_transform) {
496 LocatedEvent::UpdateForRootTransform(inverted_root_transform);
497 gfx::DecomposedTransform decomp;
498 bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
499 DCHECK(success);
500 if (decomp.scale[0])
501 radius_x_ *= decomp.scale[0];
502 if (decomp.scale[1])
503 radius_y_ *= decomp.scale[1];
504 }
505
506 ////////////////////////////////////////////////////////////////////////////////
507 // KeyEvent
508
KeyEvent(const base::NativeEvent & native_event,bool is_char)509 KeyEvent::KeyEvent(const base::NativeEvent& native_event, bool is_char)
510 : Event(native_event,
511 EventTypeFromNative(native_event),
512 EventFlagsFromNative(native_event)),
513 key_code_(KeyboardCodeFromNative(native_event)),
514 code_(CodeFromNative(native_event)),
515 is_char_(is_char),
516 character_(0) {
517 #if defined(USE_X11)
518 NormalizeFlags();
519 #endif
520 }
521
KeyEvent(EventType type,KeyboardCode key_code,int flags,bool is_char)522 KeyEvent::KeyEvent(EventType type,
523 KeyboardCode key_code,
524 int flags,
525 bool is_char)
526 : Event(type, EventTimeForNow(), flags),
527 key_code_(key_code),
528 is_char_(is_char),
529 character_(GetCharacterFromKeyCode(key_code, flags)) {
530 }
531
KeyEvent(EventType type,KeyboardCode key_code,const std::string & code,int flags,bool is_char)532 KeyEvent::KeyEvent(EventType type,
533 KeyboardCode key_code,
534 const std::string& code,
535 int flags,
536 bool is_char)
537 : Event(type, EventTimeForNow(), flags),
538 key_code_(key_code),
539 code_(code),
540 is_char_(is_char),
541 character_(GetCharacterFromKeyCode(key_code, flags)) {
542 }
543
GetCharacter() const544 uint16 KeyEvent::GetCharacter() const {
545 if (character_)
546 return character_;
547
548 #if defined(OS_WIN)
549 return (native_event().message == WM_CHAR) ? key_code_ :
550 GetCharacterFromKeyCode(key_code_, flags());
551 #elif defined(USE_X11)
552 if (!native_event())
553 return GetCharacterFromKeyCode(key_code_, flags());
554
555 DCHECK(native_event()->type == KeyPress ||
556 native_event()->type == KeyRelease);
557
558 uint16 ch = 0;
559 if (!IsControlDown())
560 ch = GetCharacterFromXEvent(native_event());
561 return ch ? ch : GetCharacterFromKeyCode(key_code_, flags());
562 #else
563 if (native_event()) {
564 DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED ||
565 EventTypeFromNative(native_event()) == ET_KEY_RELEASED);
566 }
567
568 return GetCharacterFromKeyCode(key_code_, flags());
569 #endif
570 }
571
IsUnicodeKeyCode() const572 bool KeyEvent::IsUnicodeKeyCode() const {
573 if (!IsAltDown())
574 return false;
575 const int key = key_code();
576 if (key >= VKEY_NUMPAD0 && key <= VKEY_NUMPAD9)
577 return true;
578 // Check whether the user is using the numeric keypad with num-lock off.
579 // In that case, EF_EXTENDED will not be set; if it is set, the key event
580 // originated from the relevant non-numpad dedicated key, e.g. [Insert].
581 return (!(flags() & EF_EXTENDED) &&
582 (key == VKEY_INSERT || key == VKEY_END || key == VKEY_DOWN ||
583 key == VKEY_NEXT || key == VKEY_LEFT || key == VKEY_CLEAR ||
584 key == VKEY_RIGHT || key == VKEY_HOME || key == VKEY_UP ||
585 key == VKEY_PRIOR));
586 }
587
NormalizeFlags()588 void KeyEvent::NormalizeFlags() {
589 int mask = 0;
590 switch (key_code()) {
591 case VKEY_CONTROL:
592 mask = EF_CONTROL_DOWN;
593 break;
594 case VKEY_SHIFT:
595 mask = EF_SHIFT_DOWN;
596 break;
597 case VKEY_MENU:
598 mask = EF_ALT_DOWN;
599 break;
600 case VKEY_CAPITAL:
601 mask = EF_CAPS_LOCK_DOWN;
602 break;
603 default:
604 return;
605 }
606 if (type() == ET_KEY_PRESSED)
607 set_flags(flags() | mask);
608 else
609 set_flags(flags() & ~mask);
610 }
611
612 ////////////////////////////////////////////////////////////////////////////////
613 // TranslatedKeyEvent
614
TranslatedKeyEvent(const base::NativeEvent & native_event,bool is_char)615 TranslatedKeyEvent::TranslatedKeyEvent(const base::NativeEvent& native_event,
616 bool is_char)
617 : KeyEvent(native_event, is_char) {
618 SetType(type() == ET_KEY_PRESSED ?
619 ET_TRANSLATED_KEY_PRESS : ET_TRANSLATED_KEY_RELEASE);
620 }
621
TranslatedKeyEvent(bool is_press,KeyboardCode key_code,int flags)622 TranslatedKeyEvent::TranslatedKeyEvent(bool is_press,
623 KeyboardCode key_code,
624 int flags)
625 : KeyEvent((is_press ? ET_TRANSLATED_KEY_PRESS : ET_TRANSLATED_KEY_RELEASE),
626 key_code,
627 flags,
628 false) {
629 }
630
ConvertToKeyEvent()631 void TranslatedKeyEvent::ConvertToKeyEvent() {
632 SetType(type() == ET_TRANSLATED_KEY_PRESS ?
633 ET_KEY_PRESSED : ET_KEY_RELEASED);
634 }
635
636 ////////////////////////////////////////////////////////////////////////////////
637 // ScrollEvent
638
ScrollEvent(const base::NativeEvent & native_event)639 ScrollEvent::ScrollEvent(const base::NativeEvent& native_event)
640 : MouseEvent(native_event) {
641 if (type() == ET_SCROLL) {
642 GetScrollOffsets(native_event,
643 &x_offset_, &y_offset_,
644 &x_offset_ordinal_, &y_offset_ordinal_,
645 &finger_count_);
646 } else if (type() == ET_SCROLL_FLING_START ||
647 type() == ET_SCROLL_FLING_CANCEL) {
648 GetFlingData(native_event,
649 &x_offset_, &y_offset_,
650 &x_offset_ordinal_, &y_offset_ordinal_,
651 NULL);
652 } else {
653 NOTREACHED() << "Unexpected event type " << type()
654 << " when constructing a ScrollEvent.";
655 }
656 }
657
ScrollEvent(EventType type,const gfx::Point & location,base::TimeDelta time_stamp,int flags,float x_offset,float y_offset,float x_offset_ordinal,float y_offset_ordinal,int finger_count)658 ScrollEvent::ScrollEvent(EventType type,
659 const gfx::Point& location,
660 base::TimeDelta time_stamp,
661 int flags,
662 float x_offset,
663 float y_offset,
664 float x_offset_ordinal,
665 float y_offset_ordinal,
666 int finger_count)
667 : MouseEvent(type, location, location, flags),
668 x_offset_(x_offset),
669 y_offset_(y_offset),
670 x_offset_ordinal_(x_offset_ordinal),
671 y_offset_ordinal_(y_offset_ordinal),
672 finger_count_(finger_count) {
673 set_time_stamp(time_stamp);
674 CHECK(IsScrollEvent());
675 }
676
Scale(const float factor)677 void ScrollEvent::Scale(const float factor) {
678 x_offset_ *= factor;
679 y_offset_ *= factor;
680 x_offset_ordinal_ *= factor;
681 y_offset_ordinal_ *= factor;
682 }
683
684 ////////////////////////////////////////////////////////////////////////////////
685 // GestureEvent
686
GestureEvent(EventType type,int x,int y,int flags,base::TimeDelta time_stamp,const GestureEventDetails & details,unsigned int touch_ids_bitfield)687 GestureEvent::GestureEvent(EventType type,
688 int x,
689 int y,
690 int flags,
691 base::TimeDelta time_stamp,
692 const GestureEventDetails& details,
693 unsigned int touch_ids_bitfield)
694 : LocatedEvent(type,
695 gfx::Point(x, y),
696 gfx::Point(x, y),
697 time_stamp,
698 flags | EF_FROM_TOUCH),
699 details_(details),
700 touch_ids_bitfield_(touch_ids_bitfield) {
701 }
702
~GestureEvent()703 GestureEvent::~GestureEvent() {
704 }
705
GetLowestTouchId() const706 int GestureEvent::GetLowestTouchId() const {
707 if (touch_ids_bitfield_ == 0)
708 return -1;
709 int i = -1;
710 // Find the index of the least significant 1 bit
711 while (!(1 << ++i & touch_ids_bitfield_));
712 return i;
713 }
714
715 } // namespace ui
716