diff options
author | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-17 17:10:26 +0000 |
---|---|---|
committer | davemoore@chromium.org <davemoore@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-01-17 17:10:26 +0000 |
commit | ec7b271972848c075878d14fe07f29197ebec6d6 (patch) | |
tree | 1bcb43f652089f561c4ee4aa009b8f08a0324acc /ui/base | |
parent | 1b62b89312329852d43103c6ab718bd60cfacdcf (diff) | |
download | chromium_src-ec7b271972848c075878d14fe07f29197ebec6d6.zip chromium_src-ec7b271972848c075878d14fe07f29197ebec6d6.tar.gz chromium_src-ec7b271972848c075878d14fe07f29197ebec6d6.tar.bz2 |
Use times from the initiation of events to determine whether two
successive clicks should be considered a double click.
Also implements triple click for web content in aura.
BUG=None
TEST=aura_unittests::EventTest.*
Review URL: https://chromiumcodereview.appspot.com/9133013
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@117907 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base')
-rw-r--r-- | ui/base/events.h | 14 | ||||
-rw-r--r-- | ui/base/win/events_win.cc | 28 | ||||
-rw-r--r-- | ui/base/x/events_x.cc | 147 |
3 files changed, 146 insertions, 43 deletions
diff --git a/ui/base/events.h b/ui/base/events.h index 2128df5..d9cac3d 100644 --- a/ui/base/events.h +++ b/ui/base/events.h @@ -14,6 +14,10 @@ namespace gfx { class Point; } +namespace base { +class TimeDelta; +} + namespace ui { // Event types. (prefixed because of a conflict with windows headers) @@ -64,7 +68,8 @@ enum EventFlags { // Flags specific to mouse events enum MouseEventFlags { EF_IS_DOUBLE_CLICK = 1 << 16, - EF_IS_NON_CLIENT = 1 << 17 + EF_IS_TRIPLE_CLICK = 1 << 17, + EF_IS_NON_CLIENT = 1 << 18 }; enum TouchStatus { @@ -100,6 +105,9 @@ UI_EXPORT EventType EventTypeFromNative(const base::NativeEvent& native_event); // Get the EventFlags from a native event. UI_EXPORT int EventFlagsFromNative(const base::NativeEvent& native_event); +UI_EXPORT base::TimeDelta EventTimeFromNative( + const base::NativeEvent& native_event); + // Get the location from a native event. The coordinate system of the resultant // |Point| has the origin at top-left of the "root window". The nature of // this "root window" and how it maps to platform-specific drawing surfaces is @@ -144,6 +152,10 @@ UI_EXPORT bool GetScrollOffsets(const base::NativeEvent& native_event, float* x_offset, float* y_offset); +UI_EXPORT bool GetGestureTimes(const base::NativeEvent& native_event, + double* start_time, + double* end_time); + // Creates and returns no-op event. UI_EXPORT base::NativeEvent CreateNoopEvent(); diff --git a/ui/base/win/events_win.cc b/ui/base/win/events_win.cc index c6657f4..d3557f2 100644 --- a/ui/base/win/events_win.cc +++ b/ui/base/win/events_win.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,6 +7,7 @@ #include "ui/base/events.h" #include "base/logging.h" +#include "base/time.h" #include "ui/base/keycodes/keyboard_code_conversion_win.h" #include "ui/gfx/point.h" @@ -71,17 +72,6 @@ bool IsMouseWheelEvent(const base::NativeEvent& native_event) { native_event.message == WM_MOUSEHWHEEL; } -bool IsDoubleClickMouseEvent(const base::NativeEvent& native_event) { - return native_event.message == WM_NCLBUTTONDBLCLK || - native_event.message == WM_NCMBUTTONDBLCLK || - native_event.message == WM_NCRBUTTONDBLCLK || - native_event.message == WM_NCXBUTTONDBLCLK || - native_event.message == WM_LBUTTONDBLCLK || - native_event.message == WM_MBUTTONDBLCLK || - native_event.message == WM_RBUTTONDBLCLK || - native_event.message == WM_XBUTTONDBLCLK; -} - bool IsKeyEvent(const base::NativeEvent& native_event) { return native_event.message == WM_KEYDOWN || native_event.message == WM_SYSKEYDOWN || @@ -129,7 +119,6 @@ int MouseStateFlagsFromNative(const base::NativeEvent& native_event) { flags |= (win_flags & MK_LBUTTON) ? ui::EF_LEFT_MOUSE_BUTTON : 0; flags |= (win_flags & MK_MBUTTON) ? ui::EF_MIDDLE_MOUSE_BUTTON : 0; flags |= (win_flags & MK_RBUTTON) ? ui::EF_RIGHT_MOUSE_BUTTON : 0; - flags |= IsDoubleClickMouseEvent(native_event) ? ui::EF_IS_DOUBLE_CLICK: 0; flags |= IsNonClientMouseEvent(native_event) ? ui::EF_IS_NON_CLIENT : 0; return flags; } @@ -198,6 +187,10 @@ int EventFlagsFromNative(const base::NativeEvent& native_event) { return flags; } +base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) { + return base::TimeDelta::FromMilliseconds(native_event.time); +} + gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) { // Note: Wheel events are considered client, but their position is in screen // coordinates. @@ -260,6 +253,15 @@ bool GetScrollOffsets(const base::NativeEvent& native_event, return false; } +bool GetGestureTimes(const base::NativeEvent& native_event, + double* start_time, + double* end_time) { + // Not supported in Windows. + *start_time = 0; + *end_time = 0; + return false; +} + void UpdateDeviceList() { NOTIMPLEMENTED(); } diff --git a/ui/base/x/events_x.cc b/ui/base/x/events_x.cc index d0e57e6..0b8c5c7 100644 --- a/ui/base/x/events_x.cc +++ b/ui/base/x/events_x.cc @@ -23,6 +23,10 @@ #define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel" #define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel" +// CMT specific timings +#define AXIS_LABEL_PROP_ABS_START_TIME "Abs Start Timestamp" +#define AXIS_LABEL_PROP_ABS_END_TIME "Abs End Timestamp" + namespace { // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+. @@ -41,16 +45,16 @@ static const int kMaxWheelButton = 7; #endif // A class to support the detection of scroll events, using X11 valuators. -class UI_EXPORT ScrollEventData { +class UI_EXPORT CMTEventData { public: // Returns the ScrollEventData singleton. - static ScrollEventData* GetInstance() { - return Singleton<ScrollEventData>::get(); + static CMTEventData* GetInstance() { + return Singleton<CMTEventData>::get(); } // Updates the list of devices. void UpdateDeviceList(Display* display) { - scroll_devices_.reset(); + cmt_devices_.reset(); device_to_valuators_.clear(); int count = 0; @@ -59,7 +63,7 @@ class UI_EXPORT ScrollEventData { for (int i = 0; i < count; ++i) { XDeviceInfo* dev = dev_list + i; if (dev->type == xi_touchpad) - scroll_devices_[dev_list[i].id] = true; + cmt_devices_[dev_list[i].id] = true; } if (dev_list) XFreeDeviceList(dev_list); @@ -67,34 +71,45 @@ class UI_EXPORT ScrollEventData { XIDeviceInfo* info_list = XIQueryDevice(display, XIAllDevices, &count); Atom x_axis = XInternAtom(display, AXIS_LABEL_PROP_REL_HWHEEL, false); Atom y_axis = XInternAtom(display, AXIS_LABEL_PROP_REL_WHEEL, false); + Atom start_time = + XInternAtom(display, AXIS_LABEL_PROP_ABS_START_TIME, false); + Atom end_time = XInternAtom(display, AXIS_LABEL_PROP_ABS_END_TIME, false); for (int i = 0; i < count; ++i) { XIDeviceInfo* info = info_list + i; - if (!scroll_devices_[info->deviceid]) + if (!cmt_devices_[info->deviceid]) continue; if (info->use != XISlavePointer && info->use != XIFloatingSlave) { - scroll_devices_[info->deviceid] = false; + cmt_devices_[info->deviceid] = false; continue; } - Valuators valuators = {-1, -1}; + Valuators valuators; for (int j = 0; j < info->num_classes; ++j) { if (info->classes[j]->type != XIValuatorClass) continue; XIValuatorClassInfo* v = reinterpret_cast<XIValuatorClassInfo*>(info->classes[j]); + int number = v->number; + if (number > valuators.max) + valuators.max = number; if (v->label == x_axis) - valuators.x_scroll = v->number; + valuators.x_scroll = number; else if (v->label == y_axis) - valuators.y_scroll = v->number; + valuators.y_scroll = number; + else if (v->label == start_time) + valuators.start_time = number; + else if (v->label == end_time) + valuators.end_time = number; } if (valuators.x_scroll >= 0 && valuators.y_scroll >= 0) device_to_valuators_[info->deviceid] = valuators; else - scroll_devices_[info->deviceid] = false; + cmt_devices_[info->deviceid] = false; } + XIFreeDeviceInfo(info_list); } // Returns true if this is a scroll event (a motion event with the necessary @@ -108,25 +123,23 @@ class UI_EXPORT ScrollEventData { if (y_offset) *y_offset = 0; - if (!scroll_devices_[xiev->deviceid]) + if (!cmt_devices_[xiev->deviceid]) return false; - int x_scroll = device_to_valuators_[xiev->deviceid].x_scroll; - int y_scroll = device_to_valuators_[xiev->deviceid].y_scroll; - - bool has_x_offset = XIMaskIsSet(xiev->valuators.mask, x_scroll); - bool has_y_offset = XIMaskIsSet(xiev->valuators.mask, y_scroll); + const Valuators v = device_to_valuators_[xiev->deviceid]; + bool has_x_offset = XIMaskIsSet(xiev->valuators.mask, v.x_scroll); + bool has_y_offset = XIMaskIsSet(xiev->valuators.mask, v.y_scroll); bool is_scroll = has_x_offset || has_y_offset; if (!x_offset && !y_offset) return is_scroll; double* valuators = xiev->valuators.values; - for (int i = 0; i < xiev->valuators.mask_len * 8; ++i) { + for (int i = 0; i <= v.max; ++i) { if (XIMaskIsSet(xiev->valuators.mask, i)) { - if (x_offset && x_scroll == i) + if (x_offset && v.x_scroll == i) *x_offset = -(*valuators); - else if (y_offset && y_scroll == i) + else if (y_offset && v.y_scroll == i) *y_offset = -(*valuators); valuators++; } @@ -135,28 +148,68 @@ class UI_EXPORT ScrollEventData { return is_scroll; } + bool GetGestureTimes(const XEvent& xev, + double* start_time, + double* end_time) { + *start_time = 0; + *end_time = 0; + + XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data); + if (!cmt_devices_[xiev->deviceid]) + return false; + + Valuators v = device_to_valuators_[xiev->deviceid]; + if (!XIMaskIsSet(xiev->valuators.mask, v.start_time) || + !XIMaskIsSet(xiev->valuators.mask, v.end_time)) + return false; + + double* valuators = xiev->valuators.values; + for (int i = 0; i <= v.max; ++i) { + if (XIMaskIsSet(xiev->valuators.mask, i)) { + // Convert values to unsigned ints represending ms before storing them, + // as that is how they were encoded before conversion to doubles. + if (v.start_time == i) + *start_time = + static_cast<double>(static_cast<unsigned int>(*valuators)) / 1000; + else if (v.end_time == i) + *end_time = + static_cast<double>(static_cast<unsigned int>(*valuators)) / 1000; + valuators++; + } + } + + return true; + } + private: // Requirement for Singleton - friend struct DefaultSingletonTraits<ScrollEventData>; + friend struct DefaultSingletonTraits<CMTEventData>; struct Valuators { + int max; int x_scroll; int y_scroll; + int start_time; + int end_time; + + Valuators() + : max(-1), x_scroll(-1), y_scroll(-1), start_time(-1), end_time(-1) {} + }; - ScrollEventData() { + CMTEventData() { UpdateDeviceList(ui::GetXDisplay()); } - ~ScrollEventData() {} + ~CMTEventData() {} // A quick lookup table for determining if events from the pointer device // should be processed. static const int kMaxDeviceNum = 128; - std::bitset<kMaxDeviceNum> scroll_devices_; + std::bitset<kMaxDeviceNum> cmt_devices_; std::map<int, Valuators> device_to_valuators_; - DISALLOW_COPY_AND_ASSIGN(ScrollEventData); + DISALLOW_COPY_AND_ASSIGN(CMTEventData); }; int GetEventFlagsFromXState(unsigned int state) { @@ -328,9 +381,9 @@ EventType EventTypeFromNative(const base::NativeEvent& native_event) { case XI_Motion: if (GetScrollOffsets(native_event, NULL, NULL)) return ET_SCROLL; - else if (GetButtonMaskForX2Event(xievent)) + else if (GetButtonMaskForX2Event(xievent)) { return ET_MOUSE_DRAGGED; - else + } else return ET_MOUSE_MOVED; } } @@ -380,6 +433,35 @@ int EventFlagsFromNative(const base::NativeEvent& native_event) { return 0; } +base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) { + switch(native_event->type) { + case KeyPress: + case KeyRelease: + return base::TimeDelta::FromMilliseconds(native_event->xkey.time); + case ButtonPress: + case ButtonRelease: + return base::TimeDelta::FromMilliseconds(native_event->xbutton.time); + break; + case MotionNotify: + return base::TimeDelta::FromMilliseconds(native_event->xmotion.time); + break; + case GenericEvent: { + double start, end; + if (GetGestureTimes(native_event, &start, &end)) { + // If the driver supports gesture times, use them. + return base::TimeDelta::FromMicroseconds(start * 1000000); + } else { + XIDeviceEvent* xide = + static_cast<XIDeviceEvent*>(native_event->xcookie.data); + return base::TimeDelta::FromMilliseconds(xide->time); + } + break; + } + } + NOTREACHED(); + return base::TimeDelta(); +} + gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) { switch (native_event->type) { case ButtonPress: @@ -542,13 +624,20 @@ float GetTouchForce(const base::NativeEvent& native_event) { bool GetScrollOffsets(const base::NativeEvent& native_event, float* x_offset, float* y_offset) { - return ScrollEventData::GetInstance()->GetScrollOffsets( + return CMTEventData::GetInstance()->GetScrollOffsets( *native_event, x_offset, y_offset); } +bool GetGestureTimes(const base::NativeEvent& native_event, + double* start_time, + double* end_time) { + return CMTEventData::GetInstance()->GetGestureTimes( + *native_event, start_time, end_time); +} + void UpdateDeviceList() { Display* display = GetXDisplay(); - ScrollEventData::GetInstance()->UpdateDeviceList(display); + CMTEventData::GetInstance()->UpdateDeviceList(display); TouchFactory::GetInstance()->UpdateDeviceList(display); } |