| Index: ui/base/touch/touch_factory.cc
|
| ===================================================================
|
| --- ui/base/touch/touch_factory.cc (revision 126124)
|
| +++ ui/base/touch/touch_factory.cc (working copy)
|
| @@ -4,6 +4,11 @@
|
|
|
| #include "ui/base/touch/touch_factory.h"
|
|
|
| +#include <string>
|
| +
|
| +#include "ui/base/touch/multi_touch_device.h"
|
| +#include "ui/base/touch/multi_touch_device_x11.h"
|
| +
|
| #include <X11/cursorfont.h>
|
| #include <X11/extensions/XInput.h>
|
| #include <X11/extensions/XInput2.h>
|
| @@ -20,6 +25,35 @@
|
| // The X cursor is hidden if it is idle for kCursorIdleSeconds seconds.
|
| int kCursorIdleSeconds = 5;
|
|
|
| +ui::Axis::Type TouchParamToAxisType(ui::TouchFactory::TouchParam tp) {
|
| + ui::Axis::Type type = ui::Axis::AXIS_TYPE_UNKNOWN;
|
| + switch (tp) {
|
| + case ui::TouchFactory::TP_TOUCH_MAJOR:
|
| + // Length of the touch area.
|
| + type = ui::Axis::AXIS_TYPE_TOUCH_MAJOR;
|
| + break;
|
| + case ui::TouchFactory::TP_TOUCH_MINOR:
|
| + // Width of the touch area.
|
| + type = ui::Axis::AXIS_TYPE_TOUCH_MINOR;
|
| + break;
|
| + case ui::TouchFactory::TP_ORIENTATION:
|
| + // Angle between the X-axis and the major axis of the
|
| + // touch area.
|
| + type = ui::Axis::AXIS_TYPE_ORIENTATION;
|
| + break;
|
| + case ui::TouchFactory::TP_PRESSURE:
|
| + // Pressure of the touch contact.
|
| + type = ui::Axis::AXIS_TYPE_PRESSURE;
|
| + case ui::TouchFactory::TP_TRACKING_ID:
|
| + // ID of the touch point.
|
| + type = ui::Axis::AXIS_TYPE_TRACKING_ID;
|
| + default:
|
| + break;
|
| + }
|
| +
|
| + return type;
|
| +}
|
| +
|
| // Given the TouchParam, return the correspoding XIValuatorClassInfo using
|
| // the X device information through Atom name matching.
|
| XIValuatorClassInfo* FindTPValuator(Display* display,
|
| @@ -72,7 +106,6 @@
|
|
|
| return NULL;
|
| }
|
| -
|
| } // namespace
|
|
|
| namespace ui {
|
| @@ -83,12 +116,18 @@
|
| }
|
|
|
| TouchFactory::TouchFactory()
|
| - : is_cursor_visible_(true),
|
| + : device_observer_list_(
|
| + new ObserverListThreadSafe<TouchFactory::DeviceObserver>()),
|
| + is_cursor_visible_(true),
|
| cursor_timer_(),
|
| pointer_device_lookup_(),
|
| touch_device_available_(false),
|
| touch_device_list_(),
|
| #if defined(USE_XI2_MT)
|
| +#if defined(USE_AURA)
|
| + native_root_window_aura_(ui::GetX11RootWindow()),
|
| +#endif
|
| + utouch_frame_handle_(NULL),
|
| min_available_slot_(0),
|
| #endif
|
| slots_used_() {
|
| @@ -101,13 +140,23 @@
|
| XColor black;
|
| black.red = black.green = black.blue = 0;
|
| Display* display = ui::GetXDisplay();
|
| +
|
| + if (UFStatusSuccess != frame_x11_new(display, &utouch_frame_handle_)) {
|
| + LOG(ERROR) << "Failed to create utouch frame instance";
|
| + } else {
|
| + fd_set set;
|
| + FD_ZERO(&set);
|
| + FD_SET(frame_get_fd(utouch_frame_handle_), &set);
|
| + }
|
| +
|
| Pixmap blank = XCreateBitmapFromData(display, ui::GetX11RootWindow(),
|
| nodata, 8, 8);
|
| invisible_cursor_ = XCreatePixmapCursor(display, blank, blank,
|
| &black, &black, 0, 0);
|
| arrow_cursor_ = XCreateFontCursor(display, XC_arrow);
|
|
|
| - SetCursorVisible(false, false);
|
| + // TODO(tvoss): Selectively enable visibility for indirect touch devs.
|
| + // SetCursorVisible(false, false);
|
| UpdateDeviceList(display);
|
|
|
| // Make sure the list of devices is kept up-to-date by listening for
|
| @@ -125,6 +174,10 @@
|
| }
|
|
|
| TouchFactory::~TouchFactory() {
|
| + device_observer_list_->Release();
|
| + ObserverListThreadSafeTraits<DeviceObserver>::Destruct(
|
| + device_observer_list_);
|
| +
|
| #if defined(USE_AURA)
|
| if (!base::MessagePumpForUI::HasXInput2())
|
| return;
|
| @@ -139,7 +192,25 @@
|
| }
|
| }
|
|
|
| +void TouchFactory::AddDeviceObserver(TouchFactory::DeviceObserver * observer) {
|
| + device_observer_list_->AddObserver(observer);
|
| +
|
| + base::AutoLock al(touch_device_list_lock_);
|
| + // Make sure that every new observer is provided with an
|
| + // initial list of devices.
|
| + device_observer_list_->Notify(
|
| + &DeviceObserver::OnDevicesUpdated,
|
| + touch_device_list_);
|
| +}
|
| +
|
| +void TouchFactory::RemoveDeviceObserver(
|
| + TouchFactory::DeviceObserver * observer) {
|
| + device_observer_list_->RemoveObserver(observer);
|
| +}
|
| +
|
| void TouchFactory::UpdateDeviceList(Display* display) {
|
| + base::AutoLock al(touch_device_list_lock_);
|
| +
|
| // Detect touch devices.
|
| // NOTE: The new API for retrieving the list of devices (XIQueryDevice) does
|
| // not provide enough information to detect a touch device. As a result, the
|
| @@ -183,16 +254,24 @@
|
| for (int i = 0; i < count; i++) {
|
| XIDeviceInfo* devinfo = devices + i;
|
| #if defined(USE_XI2_MT)
|
| + MultiTouchDevice mtDevice;
|
| + if (ui::xi_device_info_to_mt_device(devinfo, mtDevice))
|
| + touch_device_list_[devinfo->deviceid] = mtDevice;
|
| +
|
| for (int k = 0; k < devinfo->num_classes; ++k) {
|
| XIAnyClassInfo* xiclassinfo = devinfo->classes[k];
|
| if (xiclassinfo->type == XITouchClass) {
|
| XITouchClassInfo* tci =
|
| reinterpret_cast<XITouchClassInfo *>(xiclassinfo);
|
| - // Only care direct touch device (such as touch screen) right now
|
| - if (tci->mode == XIDirectTouch) {
|
| - touch_device_lookup_[devinfo->deviceid] = true;
|
| - touch_device_list_[devinfo->deviceid] = true;
|
| - touch_device_available_ = true;
|
| + switch (tci->mode) {
|
| + case XIDirectTouch:
|
| + touch_device_lookup_[devinfo->deviceid] = true;
|
| + touch_device_available_ = true;
|
| + break;
|
| + case XIDependentTouch:
|
| + touch_device_lookup_[devinfo->deviceid] = true;
|
| + touch_device_available_ = true;
|
| + break;
|
| }
|
| }
|
| }
|
| @@ -204,6 +283,9 @@
|
| XIFreeDeviceInfo(devices);
|
|
|
| SetupValuator();
|
| +
|
| + device_observer_list_->Notify(
|
| + &DeviceObserver::OnDevicesUpdated, touch_device_list_);
|
| }
|
|
|
| bool TouchFactory::ShouldProcessXI2Event(XEvent* xev) {
|
| @@ -212,6 +294,8 @@
|
| XIDeviceEvent* xiev = reinterpret_cast<XIDeviceEvent*>(event);
|
|
|
| #if defined(USE_XI2_MT)
|
| + if (event->evtype == XI_HierarchyChanged)
|
| + return true;
|
| if (event->evtype == XI_TouchBegin ||
|
| event->evtype == XI_TouchUpdate ||
|
| event->evtype == XI_TouchEnd) {
|
| @@ -226,6 +310,22 @@
|
| return pointer_device_lookup_[xiev->deviceid];
|
| }
|
|
|
| +void TouchFactory::ProcessXI2Event(XEvent* event) {
|
| + // Commented out under the assumption that the window host
|
| + // already loaded all event data.
|
| + /* XGenericEventCookie *xcookie = &event->xcookie;
|
| + if(!XGetEventData(ui::GetXDisplay(), xcookie)) {
|
| + LOG(ERROR) << "Failed to get X generic event data";
|
| + return;
|
| + }else
|
| + printf( "Successfully retrieved X generic event data\n" );
|
| + */
|
| + if (UFStatusSuccess !=
|
| + frame_x11_process_event(utouch_frame_handle_, &event->xcookie)) {
|
| + LOG(ERROR) << "Failed to inject X event";
|
| + }
|
| +}
|
| +
|
| void TouchFactory::SetupXI2ForXWindow(Window window) {
|
| // Setup mask for mouse events. It is possible that a device is loaded/plugged
|
| // in after we have setup XInput2 on a window. In such cases, we need to
|
| @@ -243,17 +343,25 @@
|
| XISetMask(mask, XI_TouchBegin);
|
| XISetMask(mask, XI_TouchUpdate);
|
| XISetMask(mask, XI_TouchEnd);
|
| -#endif
|
| + XISetMask(mask, XI_TouchOwnership);
|
| + XISetMask(mask, XI_HierarchyChanged);
|
| +#else
|
| XISetMask(mask, XI_ButtonPress);
|
| XISetMask(mask, XI_ButtonRelease);
|
| XISetMask(mask, XI_Motion);
|
| -
|
| +#endif
|
| XIEventMask evmask;
|
| evmask.deviceid = XIAllDevices;
|
| evmask.mask_len = sizeof(mask);
|
| evmask.mask = mask;
|
| XISelectEvents(display, window, &evmask, 1);
|
| XFlush(display);
|
| +
|
| +#if defined(USE_XI2_MT)
|
| +#if defined(USE_AURA)
|
| + native_root_window_aura_ = window;
|
| +#endif
|
| +#endif
|
| }
|
|
|
| void TouchFactory::SetTouchDeviceList(
|
| @@ -264,7 +372,6 @@
|
| iter != devices.end(); ++iter) {
|
| DCHECK(*iter < touch_device_lookup_.size());
|
| touch_device_lookup_[*iter] = true;
|
| - touch_device_list_[*iter] = false;
|
| }
|
|
|
| SetupValuator();
|
| @@ -278,8 +385,8 @@
|
| bool TouchFactory::IsMultiTouchDevice(unsigned int deviceid) const {
|
| return (deviceid < touch_device_lookup_.size() &&
|
| touch_device_lookup_[deviceid]) ?
|
| - touch_device_list_.find(deviceid)->second :
|
| - false;
|
| + touch_device_list_.find(deviceid) != touch_device_list_.end() :
|
| + false;
|
| }
|
|
|
| #if defined(USE_XI2_MT)
|
| @@ -343,15 +450,18 @@
|
| XISetMask(mask, XI_TouchBegin);
|
| XISetMask(mask, XI_TouchUpdate);
|
| XISetMask(mask, XI_TouchEnd);
|
| -#endif
|
| + XISetMask(mask, XI_TouchOwnership);
|
| + XISetMask(mask, XI_HierarchyChanged);
|
| +#else
|
| XISetMask(mask, XI_ButtonPress);
|
| XISetMask(mask, XI_ButtonRelease);
|
| XISetMask(mask, XI_Motion);
|
| +#endif
|
|
|
| XIEventMask evmask;
|
| evmask.mask_len = sizeof(mask);
|
| evmask.mask = mask;
|
| - for (std::map<int, bool>::const_iterator iter =
|
| + for (TouchDeviceList::const_iterator iter =
|
| touch_device_list_.begin();
|
| iter != touch_device_list_.end(); ++iter) {
|
| evmask.deviceid = iter->first;
|
| @@ -370,7 +480,7 @@
|
| #endif
|
|
|
| bool success = true;
|
| - for (std::map<int, bool>::const_iterator iter =
|
| + for (TouchDeviceList::const_iterator iter =
|
| touch_device_list_.begin();
|
| iter != touch_device_list_.end(); ++iter) {
|
| Status status = XIUngrabDevice(display, iter->first, CurrentTime);
|
| @@ -445,13 +555,13 @@
|
| // tracking_id valuator. Without these we'll treat the device as a
|
| // single-touch device (like a mouse).
|
| // TODO(rbyers): Multi-touch is disabled: http://crbug.com/112329
|
| - //if (valuator_lookup_[info->deviceid][TP_SLOT_ID] == -1 ||
|
| + // if (valuator_lookup_[info->deviceid][TP_SLOT_ID] == -1 ||
|
| // valuator_lookup_[info->deviceid][TP_TRACKING_ID] == -1) {
|
| DVLOG(1) << "Touch device " << info->deviceid <<
|
| " does not provide enough information for multi-touch, treating as "
|
| "a single-touch device.";
|
| touch_device_list_[info->deviceid] = false;
|
| - //}
|
| + // }
|
| #endif
|
| }
|
|
|
| @@ -499,12 +609,29 @@
|
| TouchParam tp,
|
| float* min,
|
| float* max) {
|
| +#if defined(USE_XI2_MT)
|
| + TouchDeviceList::const_iterator it = touch_device_list_.find(deviceid);
|
| + if (it == touch_device_list_.end())
|
| + return false;
|
| +
|
| + MultiTouchDevice::Axes::const_iterator ita =
|
| + it->second.axes().find(TouchParamToAxisType(tp));
|
| +
|
| + if (ita == it->second.axes().end())
|
| + return false;
|
| +
|
| + *min = ita->second.min();
|
| + *max = ita->second.max();
|
| +
|
| + return true;
|
| +#else
|
| if (valuator_lookup_[deviceid][tp] >= 0) {
|
| *min = touch_param_min_[deviceid][tp];
|
| *max = touch_param_max_[deviceid][tp];
|
| return true;
|
| }
|
| return false;
|
| +#endif
|
| }
|
|
|
| } // namespace ui
|
|
|