Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(460)

Side by Side Diff: ui/base/x/events_x.cc

Issue 8907005: Add support for new scroll valuators coming from CMT (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed comment Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/base/events.h" 5 #include "ui/base/events.h"
6 6
7 #include <X11/Xlib.h> 7 #include <X11/Xlib.h>
8 #include <X11/extensions/XInput.h>
8 #include <X11/extensions/XInput2.h> 9 #include <X11/extensions/XInput2.h>
9 #include <string.h> 10 #include <string.h>
10 11
11 #include "base/logging.h" 12 #include "base/logging.h"
12 #include "ui/base/keycodes/keyboard_code_conversion_x.h" 13 #include "ui/base/keycodes/keyboard_code_conversion_x.h"
13 #include "ui/base/touch/touch_factory.h" 14 #include "ui/base/touch/touch_factory.h"
14 #include "ui/base/x/x11_util.h" 15 #include "ui/base/x/x11_util.h"
15 #include "ui/gfx/point.h" 16 #include "ui/gfx/point.h"
16 17
17 #if !defined(TOOLKIT_USES_GTK) 18 #if !defined(TOOLKIT_USES_GTK)
18 #include "base/message_pump_x.h" 19 #include "base/message_pump_x.h"
19 #endif 20 #endif
20 21
22 // Copied from xserver-properties.h
23 #define AXIS_LABEL_PROP_REL_HWHEEL "Rel Horiz Wheel"
Daniel Erat 2011/12/14 21:49:07 nit: just one space between symbol name and string
DaveMoore 2011/12/15 17:07:21 Done.
24 #define AXIS_LABEL_PROP_REL_WHEEL "Rel Vert Wheel"
25
21 namespace { 26 namespace {
22 27
23 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+. 28 // Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
24 static const int kWheelScrollAmount = 53; 29 static const int kWheelScrollAmount = 53;
25 30
26 static const int kMinWheelButton = 4; 31 static const int kMinWheelButton = 4;
27 #if defined(OS_CHROMEOS) 32 #if defined(OS_CHROMEOS)
28 // TODO(davemoore) For now use the button to decide how much to scroll by. 33 // TODO(davemoore) For now use the button to decide how much to scroll by.
29 // When we go to XI2 scroll events this won't be necessary. If this doesn't 34 // When we go to XI2 scroll events this won't be necessary. If this doesn't
30 // happen for some reason we can better detect which devices are touchpads. 35 // happen for some reason we can better detect which devices are touchpads.
31 static const int kTouchpadScrollAmount = 3; 36 static const int kTouchpadScrollAmount = 3;
32 // Chrome OS also uses buttons 8 and 9 for scrolling. 37 // Chrome OS also uses buttons 8 and 9 for scrolling.
33 static const int kMaxWheelButton = 9; 38 static const int kMaxWheelButton = 9;
34 #else 39 #else
35 static const int kMaxWheelButton = 7; 40 static const int kMaxWheelButton = 7;
36 #endif 41 #endif
37 42
43 // A class to support the detection of scroll events, using X11 valuators.
44 class UI_EXPORT ScrollEventData {
45 public:
46 // Returns the ScrollEventData singleton.
47 static ScrollEventData* GetInstance() {
48 return Singleton<ScrollEventData>::get();
49 }
50
51 // Updates the list of devices.
52 void UpdateDeviceList(Display* display) {
53 int count;
Daniel Erat 2011/12/14 21:49:07 nit: initialize to 0
DaveMoore 2011/12/15 17:07:21 Done.
54 scroll_devices_.reset();
55 device_to_valuators_.clear();
56 XDeviceInfo* dev_list = XListInputDevices(display, &count);
57 Atom xi_touchpad = XInternAtom(display, XI_TOUCHPAD, false);
58 for (int i = 0; i < count; ++i) {
59 XDeviceInfo* dev = dev_list + i;
60 if (dev->type == xi_touchpad)
61 scroll_devices_[dev_list[i].id] = true;
62 }
63 if (dev_list)
64 XFreeDeviceList(dev_list);
65
66 XIDeviceInfo* info_list = XIQueryDevice(display, XIAllDevices, &count);
67 Atom x_axis = XInternAtom(display, AXIS_LABEL_PROP_REL_HWHEEL, false);
68 Atom y_axis = XInternAtom(display, AXIS_LABEL_PROP_REL_WHEEL, false);
69 for (int i = 0; i < count; ++i) {
70 XIDeviceInfo* info = info_list + i;
71
72 if (!scroll_devices_[info->deviceid])
73 continue;
74
75 if (info->use != XISlavePointer && info->use != XIFloatingSlave) {
76 scroll_devices_[info->deviceid] = false;
77 continue;
78 }
79
80 Valuators valuators = {-1, -1};
81 for (int j = 0; j < info->num_classes; ++j) {
82 if (info->classes[j]->type != XIValuatorClass)
83 continue;
84
85 XIValuatorClassInfo* v =
86 reinterpret_cast<XIValuatorClassInfo*>(info->classes[j]);
87 if (v->label == x_axis)
88 valuators.x_scroll = v->number;
89 else if (v->label == y_axis)
90 valuators.y_scroll = v->number;
91 }
92 if (valuators.x_scroll >= 0 && valuators.y_scroll >= 0)
93 device_to_valuators_[info->deviceid] = valuators;
94 else
95 scroll_devices_[info->deviceid] = false;
96 }
97 }
98
99 // Returns true if this is a scroll event (a motion event with the necessary
100 // valuators. Also returns the offsets. |x_offset| and |y_offset| can be
Daniel Erat 2011/12/14 21:49:07 nit: add ')' after 'valuators' either initialize
DaveMoore 2011/12/15 17:07:21 Done.
101 // NULL.
102 bool GetScrollOffsets(const XEvent& xev, float* x_offset, float* y_offset) {
103 XIDeviceEvent* xiev = static_cast<XIDeviceEvent*>(xev.xcookie.data);
104 if (!scroll_devices_[xiev->deviceid])
105 return false;
106
107 int x_scroll = device_to_valuators_[xiev->deviceid].x_scroll;
108 int y_scroll = device_to_valuators_[xiev->deviceid].y_scroll;
109
110 bool has_x_offset = XIMaskIsSet(xiev->valuators.mask, x_scroll);
111 bool has_y_offset = XIMaskIsSet(xiev->valuators.mask, y_scroll);
112 bool is_scroll = has_x_offset || has_y_offset;
113
114 if (!x_offset && !y_offset)
115 return is_scroll;
116
117 double* valuators = xiev->valuators.values;
118 for (int i = 0; i < xiev->valuators.mask_len * 8; ++i) {
119 if (XIMaskIsSet(xiev->valuators.mask, i)) {
120 if (x_offset && x_scroll == i)
121 *x_offset = -(*valuators);
122 else if (y_offset && y_scroll == i)
123 *y_offset = -(*valuators);
124 valuators++;
125 }
126 }
127
128 return is_scroll;
129 }
130
131 private:
132 // Requirement for Singleton
133 friend struct DefaultSingletonTraits<ScrollEventData>;
134
135 struct Valuators {
136 int x_scroll;
137 int y_scroll;
138 };
139
140 ScrollEventData() {
141 UpdateDeviceList(ui::GetXDisplay());
142 }
143
144 ~ScrollEventData() {}
145
146 // A quick lookup table for determining if events from the pointer device
147 // should be processed.
148 static const int kMaxDeviceNum = 128;
149 std::bitset<kMaxDeviceNum> scroll_devices_;
150 std::map<int, Valuators> device_to_valuators_;
151
152 DISALLOW_COPY_AND_ASSIGN(ScrollEventData);
153 };
154
38 int GetEventFlagsFromXState(unsigned int state) { 155 int GetEventFlagsFromXState(unsigned int state) {
39 int flags = 0; 156 int flags = 0;
40 if (state & ControlMask) 157 if (state & ControlMask)
41 flags |= ui::EF_CONTROL_DOWN; 158 flags |= ui::EF_CONTROL_DOWN;
42 if (state & ShiftMask) 159 if (state & ShiftMask)
43 flags |= ui::EF_SHIFT_DOWN; 160 flags |= ui::EF_SHIFT_DOWN;
44 if (state & Mod1Mask) 161 if (state & Mod1Mask)
45 flags |= ui::EF_ALT_DOWN; 162 flags |= ui::EF_ALT_DOWN;
46 if (state & LockMask) 163 if (state & LockMask)
47 flags |= ui::EF_CAPS_LOCK_DOWN; 164 flags |= ui::EF_CAPS_LOCK_DOWN;
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 return ET_MOUSE_MOVED; 302 return ET_MOUSE_MOVED;
186 case EnterNotify: 303 case EnterNotify:
187 return ET_MOUSE_ENTERED; 304 return ET_MOUSE_ENTERED;
188 case LeaveNotify: 305 case LeaveNotify:
189 return ET_MOUSE_EXITED; 306 return ET_MOUSE_EXITED;
190 case GenericEvent: { 307 case GenericEvent: {
191 XIDeviceEvent* xievent = 308 XIDeviceEvent* xievent =
192 static_cast<XIDeviceEvent*>(native_event->xcookie.data); 309 static_cast<XIDeviceEvent*>(native_event->xcookie.data);
193 if (TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid)) 310 if (TouchFactory::GetInstance()->IsTouchDevice(xievent->sourceid))
194 return GetTouchEventType(native_event); 311 return GetTouchEventType(native_event);
195 int button = EventButtonFromNative(native_event);
196 switch (xievent->evtype) { 312 switch (xievent->evtype) {
197 case XI_ButtonPress: 313 case XI_ButtonPress:
198 if (button >= kMinWheelButton && 314 case XI_ButtonRelease: {
199 button <= kMaxWheelButton) 315 int button = EventButtonFromNative(native_event);
316 if (button >= kMinWheelButton && button <= kMaxWheelButton)
200 return ET_MOUSEWHEEL; 317 return ET_MOUSEWHEEL;
201 return ET_MOUSE_PRESSED; 318 return xievent->evtype == XI_ButtonPress ?
202 case XI_ButtonRelease: 319 ET_MOUSE_PRESSED : ET_MOUSE_RELEASED;
203 if (button >= kMinWheelButton && 320 }
204 button <= kMaxWheelButton)
205 return ET_MOUSEWHEEL;
206 return ET_MOUSE_RELEASED;
207 case XI_Motion: 321 case XI_Motion:
208 return GetButtonMaskForX2Event(xievent) ? 322 if (GetScrollOffsets(native_event, NULL, NULL))
209 ET_MOUSE_DRAGGED : ET_MOUSE_MOVED; 323 return ET_SCROLL;
324 else if (GetButtonMaskForX2Event(xievent))
325 return ET_MOUSE_DRAGGED;
326 else
327 return ET_MOUSE_MOVED;
210 } 328 }
211 } 329 }
212 default: 330 default:
213 break; 331 break;
214 } 332 }
215 return ET_UNKNOWN; 333 return ET_UNKNOWN;
216 } 334 }
217 335
218 int EventFlagsFromNative(const base::NativeEvent& native_event) { 336 int EventFlagsFromNative(const base::NativeEvent& native_event) {
219 switch (native_event->type) { 337 switch (native_event->type) {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 0.0); 516 0.0);
399 unsigned int deviceid = 517 unsigned int deviceid =
400 static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid; 518 static_cast<XIDeviceEvent*>(native_event->xcookie.data)->sourceid;
401 // Force is normalized to fall into [0, 1] 519 // Force is normalized to fall into [0, 1]
402 if (!ui::TouchFactory::GetInstance()->NormalizeTouchParam( 520 if (!ui::TouchFactory::GetInstance()->NormalizeTouchParam(
403 deviceid, ui::TouchFactory::TP_PRESSURE, &force)) 521 deviceid, ui::TouchFactory::TP_PRESSURE, &force))
404 force = 0.0; 522 force = 0.0;
405 return force; 523 return force;
406 } 524 }
407 525
526 bool GetScrollOffsets(const base::NativeEvent& native_event,
527 float* x_offset,
528 float* y_offset) {
529 return ScrollEventData::GetInstance()->GetScrollOffsets(
530 *native_event, x_offset, y_offset);
531 }
532
533 void UpdateDeviceList() {
534 Display* display = GetXDisplay();
535 ScrollEventData::GetInstance()->UpdateDeviceList(display);
536 TouchFactory::GetInstance()->UpdateDeviceList(display);
537 }
538
408 base::NativeEvent CreateNoopEvent() { 539 base::NativeEvent CreateNoopEvent() {
409 static XEvent* noop = NULL; 540 static XEvent* noop = NULL;
410 if (!noop) { 541 if (!noop) {
411 noop = new XEvent(); 542 noop = new XEvent();
412 memset(noop, 0, sizeof(XEvent)); 543 memset(noop, 0, sizeof(XEvent));
413 noop->xclient.type = ClientMessage; 544 noop->xclient.type = ClientMessage;
414 noop->xclient.window = None; 545 noop->xclient.window = None;
415 noop->xclient.format = 8; 546 noop->xclient.format = 8;
416 DCHECK(!noop->xclient.display); 547 DCHECK(!noop->xclient.display);
417 } 548 }
418 // TODO(oshima): Remove ifdef once gtk is removed from views. 549 // TODO(oshima): Remove ifdef once gtk is removed from views.
419 #if defined(TOOLKIT_USES_GTK) 550 #if defined(TOOLKIT_USES_GTK)
420 NOTREACHED(); 551 NOTREACHED();
421 #else 552 #else
422 // Make sure we use atom from current xdisplay, which may 553 // Make sure we use atom from current xdisplay, which may
423 // change during the test. 554 // change during the test.
424 noop->xclient.message_type = XInternAtom( 555 noop->xclient.message_type = XInternAtom(
425 base::MessagePumpX::GetDefaultXDisplay(), 556 base::MessagePumpX::GetDefaultXDisplay(),
426 "noop", False); 557 "noop", False);
427 #endif 558 #endif
428 return noop; 559 return noop;
429 } 560 }
430 561
431 } // namespace ui 562 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698