Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / display / chromeos / x11 / touchscreen_delegate_x11.cc
1 // Copyright 2014 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/display/chromeos/x11/touchscreen_delegate_x11.h"
6
7 #include <X11/extensions/XInput.h>
8 #include <X11/extensions/XInput2.h>
9
10 #include <cmath>
11 #include <set>
12
13 #include "ui/display/types/chromeos/display_mode.h"
14 #include "ui/display/types/chromeos/display_snapshot.h"
15 #include "ui/gfx/x/x11_types.h"
16
17 namespace ui {
18
19 TouchscreenDelegateX11::TouchscreenDelegateX11()
20     : display_(gfx::GetXDisplay()) {}
21
22 TouchscreenDelegateX11::~TouchscreenDelegateX11() {}
23
24 void TouchscreenDelegateX11::AssociateTouchscreens(
25     DisplayConfigurator::DisplayStateList* outputs) {
26   int ndevices = 0;
27   Atom valuator_x = XInternAtom(display_, "Abs MT Position X", False);
28   Atom valuator_y = XInternAtom(display_, "Abs MT Position Y", False);
29   if (valuator_x == None || valuator_y == None)
30     return;
31
32   std::set<int> no_match_touchscreen;
33   XIDeviceInfo* info = XIQueryDevice(display_, XIAllDevices, &ndevices);
34   for (int i = 0; i < ndevices; i++) {
35     if (!info[i].enabled || info[i].use != XIFloatingSlave)
36       continue;  // Assume all touchscreens are floating slaves
37
38     double width = -1.0;
39     double height = -1.0;
40     bool is_direct_touch = false;
41
42     for (int j = 0; j < info[i].num_classes; j++) {
43       XIAnyClassInfo* class_info = info[i].classes[j];
44
45       if (class_info->type == XIValuatorClass) {
46         XIValuatorClassInfo* valuator_info =
47             reinterpret_cast<XIValuatorClassInfo*>(class_info);
48
49         if (valuator_x == valuator_info->label) {
50           // Ignore X axis valuator with unexpected properties
51           if (valuator_info->number == 0 && valuator_info->mode == Absolute &&
52               valuator_info->min == 0.0) {
53             width = valuator_info->max;
54           }
55         } else if (valuator_y == valuator_info->label) {
56           // Ignore Y axis valuator with unexpected properties
57           if (valuator_info->number == 1 && valuator_info->mode == Absolute &&
58               valuator_info->min == 0.0) {
59             height = valuator_info->max;
60           }
61         }
62       }
63 #if defined(USE_XI2_MT)
64       if (class_info->type == XITouchClass) {
65         XITouchClassInfo* touch_info =
66             reinterpret_cast<XITouchClassInfo*>(class_info);
67         is_direct_touch = touch_info->mode == XIDirectTouch;
68       }
69 #endif
70     }
71
72     // Touchscreens should have absolute X and Y axes,
73     // and be direct touch devices.
74     if (width > 0.0 && height > 0.0 && is_direct_touch) {
75       size_t k = 0;
76       for (; k < outputs->size(); k++) {
77         DisplayConfigurator::DisplayState* output = &(*outputs)[k];
78         if (output->touch_device_id != None)
79           continue;
80
81         const DisplayMode* mode_info = output->display->native_mode();
82         if (!mode_info)
83           continue;
84
85         // Allow 1 pixel difference between screen and touchscreen
86         // resolutions.  Because in some cases for monitor resolution
87         // 1024x768 touchscreen's resolution would be 1024x768, but for
88         // some 1023x767.  It really depends on touchscreen's firmware
89         // configuration.
90         if (std::abs(mode_info->size().width() - width) <= 1.0 &&
91             std::abs(mode_info->size().height() - height) <= 1.0) {
92           output->touch_device_id = info[i].deviceid;
93
94           VLOG(2) << "Found touchscreen for output #" << k << " id "
95                   << output->touch_device_id << " width " << width << " height "
96                   << height;
97           break;
98         }
99       }
100
101       if (k == outputs->size()) {
102         no_match_touchscreen.insert(info[i].deviceid);
103         VLOG(2) << "No matching output for touchscreen"
104                 << " id " << info[i].deviceid << " width " << width
105                 << " height " << height;
106       }
107     }
108   }
109
110   // Sometimes we can't find a matching screen for the touchscreen, e.g.
111   // due to the touchscreen's reporting range having no correlation with the
112   // screen's resolution. In this case, we arbitrarily assign unmatched
113   // touchscreens to unmatched screens.
114   for (std::set<int>::iterator it = no_match_touchscreen.begin();
115        it != no_match_touchscreen.end();
116        it++) {
117     for (size_t i = 0; i < outputs->size(); i++) {
118       if ((*outputs)[i].display->type() != DISPLAY_CONNECTION_TYPE_INTERNAL &&
119           (*outputs)[i].display->native_mode() != NULL &&
120           (*outputs)[i].touch_device_id == None) {
121         (*outputs)[i].touch_device_id = *it;
122         VLOG(2) << "Arbitrarily matching touchscreen "
123                 << (*outputs)[i].touch_device_id << " to output #" << i;
124         break;
125       }
126     }
127   }
128
129   XIFreeDeviceInfo(info);
130 }
131
132 void TouchscreenDelegateX11::ConfigureCTM(
133     int touch_device_id,
134     const DisplayConfigurator::CoordinateTransformation& ctm) {
135   VLOG(1) << "ConfigureCTM: id=" << touch_device_id << " scale=" << ctm.x_scale
136           << "x" << ctm.y_scale << " offset=(" << ctm.x_offset << ", "
137           << ctm.y_offset << ")";
138   int ndevices = 0;
139   XIDeviceInfo* info = XIQueryDevice(display_, touch_device_id, &ndevices);
140   Atom prop = XInternAtom(display_, "Coordinate Transformation Matrix", False);
141   Atom float_atom = XInternAtom(display_, "FLOAT", False);
142   if (ndevices == 1 && prop != None && float_atom != None) {
143     Atom type;
144     int format;
145     unsigned long num_items;
146     unsigned long bytes_after;
147     unsigned char* data = NULL;
148     // Verify that the property exists with correct format, type, etc.
149     int status = XIGetProperty(display_,
150                                info->deviceid,
151                                prop,
152                                0,
153                                0,
154                                False,
155                                AnyPropertyType,
156                                &type,
157                                &format,
158                                &num_items,
159                                &bytes_after,
160                                &data);
161     if (data)
162       XFree(data);
163     if (status == Success && type == float_atom && format == 32) {
164       float value[3][3] = {
165         { ctm.x_scale,         0.0, ctm.x_offset },
166         {         0.0, ctm.y_scale, ctm.y_offset },
167         {         0.0,         0.0,          1.0 }
168       };
169       XIChangeProperty(display_,
170                        info->deviceid,
171                        prop,
172                        type,
173                        format,
174                        PropModeReplace,
175                        reinterpret_cast<unsigned char*>(value),
176                        9);
177     }
178   }
179   XIFreeDeviceInfo(info);
180 }
181
182 }  // namespace ui