| Index: ui/display/chromeos/x11/touchscreen_device_manager_x11.cc
|
| diff --git a/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc b/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc
|
| index 6c8137b1cb47e7893fbd3d33c8181ed6dba931f7..f61353244f59c881bab4f278804e7b06a342d4af 100644
|
| --- a/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc
|
| +++ b/ui/display/chromeos/x11/touchscreen_device_manager_x11.cc
|
| @@ -9,9 +9,88 @@
|
|
|
| #include <cmath>
|
| #include <set>
|
| -
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "base/command_line.h"
|
| +#include "base/files/file_enumerator.h"
|
| +#include "base/logging.h"
|
| +#include "base/process/launch.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "base/sys_info.h"
|
| #include "ui/gfx/x/x11_types.h"
|
|
|
| +namespace {
|
| +
|
| +// We consider the touchscreen to be internal if it is an I2c device.
|
| +// With the device id, we can query X to get the device's dev input
|
| +// node eventXXX. Then we search all the dev input nodes registered
|
| +// by I2C devices to see if we can find eventXXX.
|
| +bool IsTouchscreenInternal(XDisplay* dpy, int device_id) {
|
| + using base::FileEnumerator;
|
| + using base::FilePath;
|
| +
|
| + if (!base::SysInfo::IsRunningOnChromeOS())
|
| + return false;
|
| +
|
| + // Input device has a property "Device Node" pointing to its dev input node,
|
| + // e.g. Device Node (250): "/dev/input/event8"
|
| + Atom device_node = XInternAtom(dpy, "Device Node", False);
|
| + if (device_node == None)
|
| + return false;
|
| +
|
| + Atom actual_type;
|
| + int actual_format;
|
| + unsigned long nitems, bytes_after;
|
| + unsigned char* data;
|
| + XDevice* dev = XOpenDevice(dpy, device_id);
|
| + if (!dev)
|
| + return false;
|
| +
|
| + if (XGetDeviceProperty(dpy, dev, device_node, 0, 1000, False,
|
| + AnyPropertyType, &actual_type, &actual_format,
|
| + &nitems, &bytes_after, &data) != Success) {
|
| + XCloseDevice(dpy, dev);
|
| + return false;
|
| + }
|
| + base::FilePath dev_node_path(reinterpret_cast<char*>(data));
|
| + XFree(data);
|
| + XCloseDevice(dpy, dev);
|
| +
|
| + std::string event_node = dev_node_path.BaseName().value();
|
| + if (event_node.empty() ||
|
| + !StartsWithASCII(event_node, "event", false)) {
|
| + return false;
|
| + }
|
| +
|
| + // Extract id "XXX" from "eventXXX"
|
| + std::string event_node_id = event_node.substr(5);
|
| +
|
| + // I2C input device registers its dev input node at
|
| + // /sys/bus/i2c/devices/*/input/inputXXX/eventXXX
|
| + FileEnumerator i2c_enum(FilePath(FILE_PATH_LITERAL("/sys/bus/i2c/devices/")),
|
| + false,
|
| + base::FileEnumerator::DIRECTORIES);
|
| + for (FilePath i2c_name = i2c_enum.Next();
|
| + !i2c_name.empty();
|
| + i2c_name = i2c_enum.Next()) {
|
| + FileEnumerator input_enum(i2c_name.Append(FILE_PATH_LITERAL("input")),
|
| + false,
|
| + base::FileEnumerator::DIRECTORIES,
|
| + FILE_PATH_LITERAL("input*"));
|
| + for (base::FilePath input = input_enum.Next();
|
| + !input.empty();
|
| + input = input_enum.Next()) {
|
| + if (input.BaseName().value().substr(5) == event_node_id)
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + return false;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| namespace ui {
|
|
|
| TouchscreenDeviceManagerX11::TouchscreenDeviceManagerX11()
|
| @@ -70,8 +149,10 @@ std::vector<TouchscreenDevice> TouchscreenDeviceManagerX11::GetDevices() {
|
| // Touchscreens should have absolute X and Y axes, and be direct touch
|
| // devices.
|
| if (width > 0.0 && height > 0.0 && is_direct_touch) {
|
| + bool is_internal = IsTouchscreenInternal(display_, info[i].deviceid);
|
| devices.push_back(TouchscreenDevice(info[i].deviceid,
|
| - gfx::Size(width, height)));
|
| + gfx::Size(width, height),
|
| + is_internal));
|
| }
|
| }
|
|
|
|
|