| Index: ui/base/x/scroll_factory.cc
|
| diff --git a/ui/base/x/scroll_factory.cc b/ui/base/x/scroll_factory.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5df8f5d9b588ae9a4afcf639ed1470135728bde1
|
| --- /dev/null
|
| +++ b/ui/base/x/scroll_factory.cc
|
| @@ -0,0 +1,110 @@
|
| +// Copyright (c) 2011 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.
|
| +
|
| +#include "ui/base/x/scroll_factory.h"
|
| +
|
| +#include <stdio.h>
|
| +#include <X11/cursorfont.h>
|
| +#include <X11/extensions/XInput.h>
|
| +#include <X11/extensions/XInput2.h>
|
| +#include <X11/extensions/XIproto.h>
|
| +
|
| +#include "ui/base/x/x11_util.h"
|
| +
|
| +// Copied from xserver-properties.h
|
| +#define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel"
|
| +#define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel"
|
| +
|
| +namespace ui {
|
| +
|
| +// static
|
| +ScrollFactory* ScrollFactory::GetInstance() {
|
| + return Singleton<ScrollFactory>::get();
|
| +}
|
| +
|
| +void ScrollFactory::UpdateDeviceList(Display* display) {
|
| + int count;
|
| + scroll_devices_.reset();
|
| + device_to_valuators_.clear();
|
| + XDeviceInfo* dev_list = XListInputDevices(display, &count);
|
| + Atom xi_touchpad = XInternAtom(display, XI_TOUCHPAD, false);
|
| + for (int i = 0; i < count; ++i) {
|
| + XDeviceInfo* dev = dev_list + i;
|
| + if (dev->type == xi_touchpad)
|
| + scroll_devices_[dev_list[i].id] = true;
|
| + }
|
| + if (dev_list)
|
| + XFreeDeviceList(dev_list);
|
| +
|
| + 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);
|
| + for (int i = 0; i < count; ++i) {
|
| + XIDeviceInfo* info = info_list + i;
|
| +
|
| + if (!scroll_devices_[info->deviceid])
|
| + continue;
|
| +
|
| + if (info->use != XISlavePointer && info->use != XIFloatingSlave) {
|
| + scroll_devices_[info->deviceid] = false;
|
| + continue;
|
| + }
|
| +
|
| + Valuators valuators = {-1, -1};
|
| + for (int j = 0; j < info->num_classes; ++j) {
|
| + if (info->classes[j]->type != XIValuatorClass)
|
| + continue;
|
| +
|
| + XIValuatorClassInfo* v =
|
| + reinterpret_cast<XIValuatorClassInfo*>(info->classes[j]);
|
| + if (v->label == x_axis)
|
| + valuators.x_scroll = v->number;
|
| + else if (v->label == y_axis)
|
| + valuators.y_scroll = v->number;
|
| + }
|
| + if (valuators.x_scroll >= 0 && valuators.y_scroll >= 0)
|
| + device_to_valuators_[info->deviceid] = valuators;
|
| + else
|
| + scroll_devices_[info->deviceid] = false;
|
| + }
|
| +}
|
| +
|
| +bool ScrollFactory::GetScrollOffsets(const XEvent& xev,
|
| + float* x_offset,
|
| + float* y_offset) {
|
| + XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
|
| + if (!scroll_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);
|
| + 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) {
|
| + if (XIMaskIsSet(xiev->valuators.mask, i)) {
|
| + if (x_offset && x_scroll == i)
|
| + *x_offset = -(*valuators);
|
| + else if (y_offset && y_scroll == i)
|
| + *y_offset = -(*valuators);
|
| + valuators++;
|
| + }
|
| + }
|
| +
|
| + return is_scroll;
|
| +}
|
| +
|
| +ScrollFactory::ScrollFactory() {
|
| + UpdateDeviceList(ui::GetXDisplay());
|
| +}
|
| +
|
| +ScrollFactory::~ScrollFactory() {}
|
| +
|
| +} // namespace ui
|
|
|