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

Side by Side Diff: ui/events/ozone/evdev/libgestures_glue/gesture_property_provider.cc

Issue 545063006: ozone: evdev: Add gesture property provider (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed all previous comments and removed pointer type-castings. Created 6 years, 2 months 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
OLDNEW
(Empty)
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/events/ozone/evdev/libgestures_glue/gesture_property_provider.h"
6
7 #include <gestures/gestures.h>
8 #include <libevdev/libevdev.h>
9
10 #include <fnmatch.h>
11 #include <string.h>
12
13 #include <algorithm>
14 #include <iostream>
15 #include <set>
16
17 #include "base/files/file_enumerator.h"
18 #include "base/files/file_util.h"
19 #include "base/logging.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/string_split.h"
22 #include "base/strings/string_tokenizer.h"
23 #include "base/strings/string_util.h"
24 #include "base/strings/stringize_macros.h"
25 #include "base/strings/stringprintf.h"
26 #include "ui/events/ozone/evdev/libgestures_glue/gesture_interpreter_libevdev_cr os.h"
27
28 // Severity level for general info logging purpose.
29 #define GPROP_LOG DVLOG
30 #define INFO_SEVERITY 1
31
32 /* Implementation of GesturesProp declared in gestures.h
33 *
34 * libgestures requires that this be in the top level namespace.
35 * */
36 struct GesturesProp {
spang 2014/10/03 21:40:11 This is nontrivial and should not be a struct. Cha
Shecky Lin 2014/10/08 10:51:00 Done.
37 typedef ui::GesturePropertyProvider::PropertyType PropertyType;
38 GesturesProp(const std::string& n,
39 const PropertyType tp,
40 const size_t c)
41 : name(n),
42 type(tp),
43 count(c),
44 is_allocated(false),
45 is_read_only(false),
46 handler_data(NULL),
47 get(NULL),
48 set(NULL) {
49 }
50 virtual ~GesturesProp() {}
51
52 // Get the memory size of one element of the property data type.
53 virtual size_t GetElementSize() const = 0;
54
55 // Variant-ish interfaces for accessing the property value. Each type of
56 // property should override the corresponding interfaces for it.
57 virtual bool GetIntValue(int* v) const {
spang 2014/10/03 21:40:11 You've lost all bounds checking here (in my sugges
Shecky Lin 2014/10/08 10:51:00 Done.
58 NOTREACHED();
59 return false;
60 }
61 virtual bool SetIntValue(const int* v) {
62 NOTREACHED();
63 return false;
64 }
65 virtual bool GetShortValue(short* v) const {
66 NOTREACHED();
67 return false;
68 }
69 virtual bool SetShortValue(const short* v) {
70 NOTREACHED();
71 return false;
72 }
73 virtual bool GetBoolValue(bool* v) const {
74 NOTREACHED();
75 return false;
76 }
77 virtual bool SetBoolValue(const bool* v) {
78 NOTREACHED();
79 return false;
80 }
81 virtual bool GetStringValue(std::string* v) const {
82 NOTREACHED();
83 return false;
84 }
85 virtual bool SetStringValue(const std::string* v) {
86 NOTREACHED();
87 return false;
88 }
89 virtual bool GetDoubleValue(double* v) const {
90 NOTREACHED();
91 return false;
92 }
93 virtual bool SetDoubleValue(const double* v) {
94 NOTREACHED();
95 return false;
96 }
97
98 // Interfaces for getting the data pointer and stuff.
99 virtual int* GetIntValuePtr() const {
100 NOTREACHED();
101 return NULL;
102 }
103 virtual short* GetShortValuePtr() const {
104 NOTREACHED();
105 return NULL;
106 }
107 virtual GesturesPropBool* GetBoolValuePtr() const {
108 NOTREACHED();
109 return NULL;
110 }
111 virtual std::string* GetStringValuePtr() const {
112 NOTREACHED();
113 return NULL;
114 }
115 virtual const char** GetStringWritebackPtr() const {
116 NOTREACHED();
117 return NULL;
118 }
119 virtual double* GetDoubleValuePtr() const {
120 NOTREACHED();
121 return NULL;
122 }
123
124 // Property name, type and number of elements.
125 std::string name;
126 PropertyType type;
127 size_t count;
128
129 // If the flag is on, it means the memory that the data pointer points to is
130 // allocated here. We will need to free the memory by ourselves when the
131 // GesturesProp is destroyed.
132 bool is_allocated;
133
134 // If the flag is on, it means the GesturesProp is created by passing a NULL
135 // data pointer to the creator functions. We define the property as a
136 // read-only one and that no value change will be allowed for it. Note that
137 // the flag is different from is_allocated in that StringProperty will always
138 // allocate no matter it is created with NULL or not.
139 bool is_read_only;
140
141 // Handler function pointers and the data to be passed to them when the
142 // property is accessed.
143 void* handler_data;
144 GesturesPropGetHandler get;
145 GesturesPropSetHandler set;
146 protected:
147 void OnGet() const {
148 // We don't have the X server now so there is currently nothing to do when
149 // the get handler returns true.
150 // TODO(sheckylin): Re-visit this if we use handlers that modifies the
151 // property.
152 if (get)
153 get(handler_data);
154 }
155
156 void OnSet() const {
157 // Call the property set handler if available.
158 if (set)
159 set(handler_data);
160 }
161
162 private:
163 // For logging purpose.
164 friend std::ostream& operator<<(std::ostream& os, const GesturesProp& prop);
165 };
166
167 template <typename T>
168 class TypedGesturesProp : public GesturesProp {
169 public:
170 TypedGesturesProp(const std::string& n,
171 const PropertyType tp,
172 const size_t c,
173 T* v)
174 : GesturesProp(n, tp, c), val_(v) {
175 if (!val_) {
176 if (count > 1)
spang 2014/10/03 21:40:11 I think you can remove the if{} here (and below).
Shecky Lin 2014/10/08 10:51:00 Done.
177 val_ = new T[count];
178 else
179 val_ = new T;
180 is_allocated = true;
181 is_read_only = true;
182 }
183 }
184 virtual ~TypedGesturesProp() {
185 if (is_allocated) {
186 if (count > 1)
187 delete[] val_;
188 else
189 delete val_;
190 }
191 }
192 virtual size_t GetElementSize() const { return sizeof(T); }
193
194 protected:
195 // Functions for setting/getting numerical properties.
196 template <typename U>
197 bool GetNumericalValue(U* v) const {
spang 2014/10/03 21:40:11 If you use vectors: std::vector<U> GetNumericalVe
Shecky Lin 2014/10/08 10:51:00 Done.
198 // We do type-casting because the numerical types may not totally match.
199 // For example, we store bool as GesturesPropBool to be compatible with the
200 // gesture library. Also, all parsed xorg-conf property values are stored
201 // as double because we can't identify their original type lexically.
202 // TODO(sheckylin): Handle value out-of-range (e.g., double to int).
203 for (size_t i = 0; i < count; ++i)
204 v[i] = static_cast<U>(val_[i]);
205 return true;
206 }
207
208 template <typename U>
209 bool SetNumericalValue(const U* v) {
spang 2014/10/03 21:40:11 void SetNumericalVector(const std::vector<U>& v)
Shecky Lin 2014/10/08 10:51:00 Done.
210 for (size_t i = 0; i < count; ++i)
211 val_[i] = static_cast<T>(v[i]);
212 return true;
213 }
214
215 // These two functions calls the set/get handler and should only be used in
216 // Get*Value/Set*Value functions.
217 template <typename U>
218 bool GetNumericalPropertyValue(U* v) const {
spang 2014/10/03 21:40:11 std::vector<U> GetNumericalPropertyVector()
Shecky Lin 2014/10/08 10:51:00 Done.
219 bool ret = this->template GetNumericalValue(v);
220 OnGet();
221 return ret;
222 }
223
224 template <typename U>
225 bool SetNumericalPropertyValue(const U* v) {
spang 2014/10/03 21:40:11 void SetNumericalPropertyVector(const std::vector<
Shecky Lin 2014/10/08 10:51:00 Done.
226 bool ret = this->template SetNumericalValue(v);
227 OnSet();
228 return ret;
229 }
230
231 // Check if a default property usable for (numerical) initialization. Derived
232 // classes may override it when necessary.
233 virtual bool IsDefaultPropertyUsable(GesturesProp* default_prop) {
234 // We currently assumed that we won't specify any array property in the
235 // configuration files. The code needs to be updated if the assumption
236 // becomes invalid in the future.
237 return (count == 1 && default_prop &&
238 default_prop->type != PropertyType::PT_STRING);
239 }
240
241 // Initialize a numerical property's value. Note that a (numerical) default
242 // property's value is always stored in double.
243 void InitializeNumericalProperty(const T* init, GesturesProp* default_prop) {
244 if (IsDefaultPropertyUsable(default_prop)) {
245 GPROP_LOG(INFO_SEVERITY) << "Default property found. Using its value ...";
246 this->template SetNumericalValue(default_prop->GetDoubleValuePtr());
247 } else {
248 this->template SetNumericalValue(init);
249 }
250 }
251
252 // Data pointer.
253 T* val_;
254 };
255
256 class GesturesIntProp : public TypedGesturesProp<int> {
257 public:
258 GesturesIntProp(const std::string& n,
259 const size_t c,
260 int* v,
261 const int* init,
262 GesturesProp* default_prop)
263 : TypedGesturesProp<int>(n, PropertyType::PT_INT, c, v) {
264 InitializeNumericalProperty(init, default_prop);
265 }
266
267 virtual bool GetIntValue(int* v) const {
268 return this->template GetNumericalPropertyValue(v);
269 }
270 virtual bool SetIntValue(const int* v) {
271 return this->template SetNumericalPropertyValue(v);
272 }
273 virtual int* GetIntValuePtr() const { return val_; }
274 };
275
276 class GesturesShortProp : public TypedGesturesProp<short> {
277 public:
278 GesturesShortProp(const std::string& n,
279 const size_t c,
280 short* v,
281 const short* init,
282 GesturesProp* default_prop)
283 : TypedGesturesProp<short>(n, PropertyType::PT_SHORT, c, v) {
284 InitializeNumericalProperty(init, default_prop);
285 }
286 virtual bool GetShortValue(short* v) const {
287 return this->template GetNumericalPropertyValue(v);
288 }
289 virtual bool SetShortValue(const short* v) {
290 return this->template SetNumericalPropertyValue(v);
291 }
292 virtual short* GetShortValuePtr() const { return val_; }
293 };
294
295 class GesturesBoolProp : public TypedGesturesProp<GesturesPropBool> {
296 public:
297 GesturesBoolProp(const std::string& n,
298 const size_t c,
299 GesturesPropBool* v,
300 const GesturesPropBool* init,
301 GesturesProp* default_prop)
302 : TypedGesturesProp<GesturesPropBool>(n, PropertyType::PT_BOOL, c, v) {
303 InitializeNumericalProperty(init, default_prop);
304 }
305 virtual bool GetBoolValue(bool* v) const {
306 return this->template GetNumericalPropertyValue(v);
307 }
308 virtual bool SetBoolValue(const bool* v) {
309 return this->template SetNumericalPropertyValue(v);
310 }
311 virtual GesturesPropBool* GetBoolValuePtr() const { return val_; }
312 };
313
314 class GesturesDoubleProp : public TypedGesturesProp<double> {
315 public:
316 GesturesDoubleProp(const std::string& n,
317 const size_t c,
318 double* v,
319 const double* init,
320 GesturesProp* default_prop)
321 : TypedGesturesProp<double>(n, PropertyType::PT_REAL, c, v) {
322 InitializeNumericalProperty(init, default_prop);
323 }
324 virtual bool GetDoubleValue(double* v) const {
325 return this->template GetNumericalPropertyValue(v);
326 }
327 virtual bool SetDoubleValue(const double* v) {
328 return this->template SetNumericalPropertyValue(v);
329 }
330 virtual double* GetDoubleValuePtr() const { return val_; }
331 };
332
333 class GesturesStringProp : public TypedGesturesProp<std::string> {
334 public:
335 // StringProperty's memory is always allocated on this side instead of
336 // externally in the gesture lib as the original one will be destroyed right
337 // after the constructor call (check the design of StringProperty). To do
338 // this, we call the TypedGesturesProp constructor with NULL pointer so that
339 // it always allocates.
340 GesturesStringProp(const std::string& n,
341 const char** v,
342 const char* init,
343 GesturesProp* default_prop)
344 : TypedGesturesProp<std::string>(n, PropertyType::PT_STRING, 1, NULL),
345 write_back_(NULL) {
346 // Initialize the property value similar to the numerical types.
347 if (IsDefaultPropertyUsable(default_prop)) {
348 GPROP_LOG(INFO_SEVERITY) << "Default property found. Using its value ...";
349 *val_ = *(default_prop->GetStringValuePtr());
350 } else {
351 *val_ = init;
352 }
353
354 // If the provided pointer is not NULL, replace its content
355 // (val_ of StringProperty) with the address of our allocated string.
356 // Note that we don't have to do this for the other data types as they will
357 // use the original data pointer if possible and it is unnecessary to do so
358 // if the pointer is NULL.
359 if (v) {
360 *v = val_->c_str();
361 write_back_ = v;
362 // Set the read-only flag back to false.
363 is_read_only = false;
364 }
365 }
366 virtual bool GetStringValue(std::string* v) const {
367 *v = *val_;
368 OnGet();
369 return true;
370 }
371 virtual bool SetStringValue(const std::string* v) {
372 *val_ = *v;
373
374 // Write back the pointer in case it may change (e.g., string
375 // re-allocation).
376 if (write_back_)
377 *(write_back_) = val_->c_str();
378 OnSet();
379 return true;
380 }
381 virtual std::string* GetStringValuePtr() const { return val_; }
382 virtual const char** GetStringWritebackPtr() const {
383 return write_back_;
384 }
385
386 protected:
387 // Override the function as we want string properties now.
388 virtual bool IsDefaultPropertyUsable(GesturesProp* default_prop) {
389 return (default_prop && default_prop->type == PropertyType::PT_STRING);
390 }
391
392 private:
393 // In some cases, we don't directly use the data pointer provided by the
394 // creators due to its limitation and instead use our own types (e.g., in
395 // the case of string). We thus need to store the write back pointer so that
396 // we can update the value in the gesture lib if the property value gets
397 // changed.
398 const char** write_back_;
399 };
400
401 // Property type logging function.
402 std::ostream& operator<<(std::ostream& out,
403 const ui::GesturePropertyProvider::PropertyType type) {
404 std::string s;
405 #define TYPE_CASE(TYPE) \
406 case (ui::GesturePropertyProvider::TYPE): \
407 s = #TYPE; \
408 break;
409 switch (type) {
410 TYPE_CASE(PT_INT);
411 TYPE_CASE(PT_SHORT);
412 TYPE_CASE(PT_BOOL);
413 TYPE_CASE(PT_STRING);
414 TYPE_CASE(PT_REAL);
415 default:
416 NOTREACHED();
417 break;
418 }
419 #undef TYPE_CASE
420 return out << s;
421 }
422
423 // GesturesProp logging function.
424 std::ostream& operator<<(std::ostream& os, const GesturesProp& p) {
425 const GesturesProp* prop = &p;
426
427 // Output the property content.
428 os << "\"" << prop->name << "\", " << prop->type << ", " << prop->count
429 << ", (" << prop->is_allocated << ", " << prop->is_read_only << "), ";
430
431 // Only the string property has the write back pointer.
432 if (prop->type == ui::GesturePropertyProvider::PT_STRING)
433 os << prop->GetStringWritebackPtr();
434 else
435 os << "NULL";
436
437 // Output the property values.
438 os << ", (";
439 for (size_t i = 0; i < prop->count; i++) {
440 switch (prop->type) {
441 case ui::GesturePropertyProvider::PT_INT:
442 os << prop->GetIntValuePtr()[i];
443 break;
444 case ui::GesturePropertyProvider::PT_SHORT:
445 os << prop->GetShortValuePtr()[i];
446 break;
447 case ui::GesturePropertyProvider::PT_BOOL:
448 // Prevent the value being printed as characters.
449 os << static_cast<bool>(prop->GetBoolValuePtr()[i]);
450 break;
451 case ui::GesturePropertyProvider::PT_STRING:
452 os << prop->GetStringValuePtr()[i];
453 break;
454 case ui::GesturePropertyProvider::PT_REAL:
455 os << prop->GetDoubleValuePtr()[i];
456 break;
457 default:
458 LOG(ERROR) << "Unknown gesture property type: " << prop->type;
459 NOTREACHED();
460 break;
461 }
462 os << ", ";
463 }
464 os << ")";
465 return os;
466 }
467
468 // Anonymous namespace for utility functions and internal constants.
469 namespace {
470
471 // The path that we will look for conf files.
472 const char kConfigurationFilePath[] = "/etc/gesture";
473
474 // We support only match types that have already been used. One should change
475 // this if we start using new types in the future. Note that most unsupported
476 // match types are either useless in CrOS or inapplicable to the non-X
477 // environment.
478 const char* kSupportedMatchTypes[] = {"MatchProduct",
479 "MatchDevicePath",
480 "MatchUSBID",
481 "MatchIsPointer",
482 "MatchIsTouchpad",
483 "MatchIsTouchscreen"};
484 const char* kUnsupportedMatchTypes[] = {"MatchVendor",
485 "MatchOS",
486 "MatchPnPID",
487 "MatchDriver",
488 "MatchTag",
489 "MatchLayout",
490 "MatchIsKeyboard",
491 "MatchIsJoystick",
492 "MatchIsTablet"};
493
494 // Special keywords for boolean values.
495 const char* kTrue[] = {"on", "true", "yes"};
496 const char* kFalse[] = {"off", "false", "no"};
497
498 // Max number of devices that we track.
499 const ui::GesturePropertyProvider::DeviceId kMaxDeviceNum = 0xffff;
500
501 // Check if a device falls into one device type category.
502 bool IsDeviceOfType(ui::GesturePropertyProvider::DevicePtr device,
503 const ui::GesturePropertyProvider::DeviceType type) {
504 EvdevClass evdev_class = device->info.evdev_class;
505 switch (type) {
506 case ui::GesturePropertyProvider::DT_MOUSE:
507 return (evdev_class == EvdevClassMouse ||
508 evdev_class == EvdevClassMultitouchMouse);
509 break;
510 case ui::GesturePropertyProvider::DT_TOUCHPAD:
511 // Note that the behavior here is different from the inputcontrol script
512 // which actually returns touchscreen devices as well.
513 return (evdev_class == EvdevClassTouchpad);
514 break;
515 case ui::GesturePropertyProvider::DT_TOUCHSCREEN:
516 return (evdev_class == EvdevClassTouchscreen);
517 break;
518 case ui::GesturePropertyProvider::DT_MULTITOUCH:
519 return (evdev_class == EvdevClassTouchpad ||
520 evdev_class == EvdevClassTouchscreen ||
521 evdev_class == EvdevClassMultitouchMouse);
522 break;
523 case ui::GesturePropertyProvider::DT_MULTITOUCH_MOUSE:
524 return (evdev_class == EvdevClassMultitouchMouse);
525 break;
526 case ui::GesturePropertyProvider::DT_ALL:
527 return true;
528 break;
529 default:
530 NOTREACHED();
531 break;
532 }
533 return false;
534 }
535
536 // Trick to get the device path from a file descriptor.
537 std::string GetDeviceNodePath(void* dev) {
538 std::string proc_symlink =
539 "/proc/self/fd/" + base::IntToString(static_cast<Evdev*>(dev)->fd);
540 base::FilePath path;
541 if (!base::ReadSymbolicLink(base::FilePath(proc_symlink), &path))
542 return std::string();
543 return path.value();
544 }
545
546 // Check if a match criteria is currently implemented. Note that we didn't
547 // implemented all of them as some are inapplicable in the non-X world.
548 bool IsMatchTypeSupported(
549 const std::string& match_type) {
550 for (size_t i = 0; i < arraysize(kSupportedMatchTypes); i++)
551 if (match_type == kSupportedMatchTypes[i])
552 return true;
553 for (size_t i = 0; i < arraysize(kUnsupportedMatchTypes); i++) {
554 if (match_type == kUnsupportedMatchTypes[i]) {
555 LOG(ERROR) << "Unsupported gestures input class match type: "
556 << match_type;
557 return false;
558 }
559 }
560 return false;
561 }
562
563 // Check if a match criteria is a device type one.
564 bool IsMatchDeviceType(
565 const std::string& match_type) {
566 return StartsWithASCII(match_type, "MatchIs", true);
567 }
568
569 // Parse a boolean value keyword (e.g., on/off, true/false).
570 int ParseBooleanKeyword(const std::string& value) {
571 for (size_t i = 0; i < arraysize(kTrue); i++)
572 if (LowerCaseEqualsASCII(value, kTrue[i]))
573 return 1;
574 for (size_t i = 0; i < arraysize(kFalse); i++)
575 if (LowerCaseEqualsASCII(value, kFalse[i]))
576 return -1;
577 return 0;
578 }
579
580 } // namespace
581
582 namespace ui {
583 namespace internal {
584
585 // Base class for device match criterias in conf files.
586 // Check the xorg-conf spec for more detailed information.
587 class MatchCriteria {
588 public:
589 typedef ui::GesturePropertyProvider::DevicePtr DevicePtr;
590 MatchCriteria(const std::string& arg);
591 virtual ~MatchCriteria() {};
592 virtual bool Match(DevicePtr device) = 0;
593 protected:
594 std::vector<std::string> args_;
595 };
596
597 // Match a device based on its evdev name string.
598 class MatchProduct : public MatchCriteria {
599 public:
600 MatchProduct(const std::string& arg);
601 virtual ~MatchProduct() {};
602 virtual bool Match(DevicePtr device);
603 };
604
605 // Math a device based on its device node path.
606 class MatchDevicePath : public MatchCriteria {
607 public:
608 MatchDevicePath(const std::string& arg);
609 virtual ~MatchDevicePath() {};
610 virtual bool Match(DevicePtr device);
611 };
612
613 // Math a USB device based on its USB vid and pid.
614 // Mostly used for external mice and touchpads.
615 class MatchUSBID : public MatchCriteria {
616 public:
617 MatchUSBID(const std::string& arg);
618 virtual ~MatchUSBID() {};
619 virtual bool Match(DevicePtr device);
620 private:
621 bool IsValidPattern(const std::string &pattern);
622 std::vector<std::string> vid_patterns_;
623 std::vector<std::string> pid_patterns_;
624 };
625
626 // Generic base class for device type math criteria.
627 class MatchDeviceType : public MatchCriteria {
628 public:
629 MatchDeviceType(const std::string& arg);
630 virtual ~MatchDeviceType() {};
631 virtual bool Match(DevicePtr device) = 0;
632 protected:
633 bool value_;
634 bool is_valid_;
635 };
636
637 // Check if a device is a pointer device.
638 class MatchIsPointer : public MatchDeviceType {
639 public:
640 MatchIsPointer(const std::string& arg);
641 virtual ~MatchIsPointer() {};
642 virtual bool Match(DevicePtr device);
643 };
644
645 // Check if a device is a touchpad.
646 class MatchIsTouchpad : public MatchDeviceType {
647 public:
648 MatchIsTouchpad(const std::string& arg);
649 virtual ~MatchIsTouchpad() {};
650 virtual bool Match(DevicePtr device);
651 };
652
653 // Check if a device is a touchscreen.
654 class MatchIsTouchscreen : public MatchDeviceType {
655 public:
656 MatchIsTouchscreen(const std::string& arg);
657 virtual ~MatchIsTouchscreen() {};
658 virtual bool Match(DevicePtr device);
659 };
660
661 // Struct for sections in xorg conf files.
662 struct ConfigurationSection {
663 typedef ui::GesturePropertyProvider::DevicePtr DevicePtr;
664 bool Match(DevicePtr device);
665 std::string identifier;
666 ScopedVector<MatchCriteria> criterias;
667 ScopedVector<GesturesProp> properties;
668 };
669
670 MatchCriteria::MatchCriteria(const std::string& arg) {
671 // TODO(sheckylin): Should we trim all tokens here?
672 Tokenize(arg, "|", &args_);
673 if (args_.empty()) {
674 LOG(ERROR) << "Empty match pattern found, will evaluate to the default "
675 "value (true): \"" << arg << "\"";
676 }
677 }
678
679 MatchProduct::MatchProduct(const std::string& arg)
680 : MatchCriteria(arg) {
681 }
682
683 bool MatchProduct::Match(DevicePtr device) {
684 if (args_.empty())
685 return true;
686 std::string name(device->info.name);
687 for (size_t i = 0; i < args_.size(); i++)
688 if (name.find(args_[i]) != std::string::npos)
689 return true;
690 return false;
691 }
692
693 MatchDevicePath::MatchDevicePath(
694 const std::string& arg)
695 : MatchCriteria(arg) {
696 }
697
698 bool MatchDevicePath::Match(DevicePtr device) {
699 if (args_.empty())
700 return true;
701
702 // Check if the device path matches any pattern.
703 std::string path = GetDeviceNodePath(device);
704 if (path.empty())
705 return false;
706 for (size_t i = 0; i < args_.size(); i++)
707 if (fnmatch(args_[i].c_str(), path.c_str(), FNM_NOESCAPE) == 0)
708 return true;
709 return false;
710 }
711
712 MatchUSBID::MatchUSBID(const std::string& arg)
713 : MatchCriteria(arg) {
714 // Check each pattern and split valid ones into vids and pids.
715 for (size_t i = 0; i < args_.size(); i++) {
716 if (!IsValidPattern(args_[i])) {
717 LOG(ERROR) << "Invalid USB ID: " << args_[i];
718 continue;
719 }
720 std::vector<std::string> tokens;
721 base::SplitString(args_[i], ':', &tokens);
722 vid_patterns_.push_back(base::StringToLowerASCII(tokens[0]));
723 pid_patterns_.push_back(base::StringToLowerASCII(tokens[1]));
724 }
725 if (vid_patterns_.empty()) {
726 LOG(ERROR) << "No valid USB ID pattern found, will be ignored: \"" << arg
727 << "\"";
728 }
729 }
730
731 bool MatchUSBID::Match(DevicePtr device) {
732 if (vid_patterns_.empty())
733 return true;
734 std::string vid = base::StringPrintf("%04x", device->info.id.vendor);
735 std::string pid = base::StringPrintf("%04x", device->info.id.product);
736 for (size_t i = 0; i < vid_patterns_.size(); i++) {
737 if (fnmatch(vid_patterns_[i].c_str(), vid.c_str(), FNM_NOESCAPE) == 0 &&
738 fnmatch(pid_patterns_[i].c_str(), pid.c_str(), FNM_NOESCAPE) == 0) {
739 return true;
740 }
741 }
742 return false;
743 }
744
745 bool MatchUSBID::IsValidPattern(
746 const std::string& pattern) {
747 // Each USB id should be in the lsusb format, i.e., xxxx:xxxx. We choose to do
748 // a lazy check here: if the pattern contains wrong characters not in the hex
749 // number range, it won't be matched anyway.
750 int number_of_colons = 0;
751 size_t pos_of_colon = 0;
752 for (size_t i = 0; i < pattern.size(); i++)
753 if (pattern[i] == ':')
754 ++number_of_colons, pos_of_colon = i;
755 return (number_of_colons == 1) && (pos_of_colon != 0) &&
756 (pos_of_colon != pattern.size() - 1);
757 }
758
759 MatchDeviceType::MatchDeviceType(
760 const std::string& arg)
761 : MatchCriteria(arg), value_(true), is_valid_(false) {
762 // Default value of a match criteria is true.
763 if (args_.empty())
764 args_.push_back("on");
765
766 // We care only about the first argument.
767 int value = ParseBooleanKeyword(args_[0]);
768 if (value) {
769 is_valid_ = true;
770 value_ = value > 0;
771 }
772 if (!is_valid_) {
773 LOG(ERROR)
774 << "No valid device class boolean keyword found, will be ignored: \""
775 << arg << "\"";
776 }
777 }
778
779 MatchIsPointer::MatchIsPointer(const std::string& arg)
780 : MatchDeviceType(arg) {
781 }
782
783 bool MatchIsPointer::Match(DevicePtr device) {
784 if (!is_valid_)
785 return true;
786 return (value_ == (device->info.evdev_class == EvdevClassMouse ||
787 device->info.evdev_class == EvdevClassMultitouchMouse));
788 }
789
790 MatchIsTouchpad::MatchIsTouchpad(
791 const std::string& arg)
792 : MatchDeviceType(arg) {
793 }
794
795 bool MatchIsTouchpad::Match(DevicePtr device) {
796 if (!is_valid_)
797 return true;
798 return (value_ == (device->info.evdev_class == EvdevClassTouchpad));
799 }
800
801 MatchIsTouchscreen::MatchIsTouchscreen(
802 const std::string& arg)
803 : MatchDeviceType(arg) {
804 }
805
806 bool MatchIsTouchscreen::Match(DevicePtr device) {
807 if (!is_valid_)
808 return true;
809 return (value_ == (device->info.evdev_class == EvdevClassTouchscreen));
810 }
811
812 bool ConfigurationSection::Match(DevicePtr device) {
813 for (size_t i = 0; i < criterias.size(); ++i)
814 if (!criterias[i]->Match(device))
815 return false;
816 return true;
817 }
818
819 } // namespace internal
820
821 GesturePropertyProvider::GesturePropertyProvider() : device_id_counter_(0) {
822 LoadDeviceConfigurations();
823 }
824
825 GesturePropertyProvider::~GesturePropertyProvider() {
826 }
827
828 void GesturePropertyProvider::GetDeviceIdsByType(
829 const DeviceType type,
830 std::vector<DeviceId>* device_ids) {
831 device_ids->clear();
832 DeviceIdMap::iterator it = device_ids_map_.begin();
833 for (; it != device_ids_map_.end(); ++it)
834 if (IsDeviceOfType(it->first, type))
835 device_ids->push_back(it->second);
836 }
837
838 GesturePropertyProvider::DeviceId GesturePropertyProvider::GetDeviceId(
839 DevicePtr dev,
840 const bool do_create) {
841 DeviceIdMap::iterator it = device_ids_map_.find(dev);
842 if (it != device_ids_map_.end())
843 return it->second;
844 if (!do_create)
845 return -1;
846
847 // Insert a new one if not exists.
848 // TODO(sheckylin): Replace this id generation scheme with a better one.
849 // The current way may result in memory leaks.
850 DeviceId id = device_id_counter_;
851 device_ids_map_[dev] = id;
852 properties_maps_.set(id,
853 scoped_ptr<ScopedPropertyMap>(new ScopedPropertyMap));
854 device_id_counter_ = (device_id_counter_ + 1) % kMaxDeviceNum;
855
856 // Apply default prop values for the device.
857 SetupDefaultProperties(id, dev);
858 return id;
859 }
860
861 GesturesProp* GesturePropertyProvider::PreGetProperty(const DeviceId device_id,
862 const std::string& name,
863 PropertyType* type,
864 size_t* count) {
865 // Return if no property of the name is found.
866 GesturesProp* prop = FindProperty(device_id, name);
867 if (!prop)
868 return NULL;
869
870 // Get the property values.
871 if (type)
872 *type = prop->type;
873 if (count)
874 *count = prop->count;
875 return prop;
876 }
877
878 bool GesturePropertyProvider::GetPropertyType(const DeviceId device_id,
879 const std::string& name,
880 PropertyType* type) {
881 GesturesProp* prop = PreGetProperty(device_id, name, type, NULL);
882 return (prop != NULL);
883 }
884
885 bool GesturePropertyProvider::GetIntProperty(const DeviceId device_id,
886 const std::string& name,
887 int* val,
888 size_t* count) {
889 GesturesProp* prop = PreGetProperty(device_id, name, NULL, count);
890 return prop ? prop->GetIntValue(val) : false;
891 }
892
893 bool GesturePropertyProvider::GetShortProperty(const DeviceId device_id,
894 const std::string& name,
895 short* val,
896 size_t* count) {
897 GesturesProp* prop = PreGetProperty(device_id, name, NULL, count);
898 return prop ? prop->GetShortValue(val) : false;
899 }
900
901 bool GesturePropertyProvider::GetBoolProperty(const DeviceId device_id,
902 const std::string& name,
903 bool* val,
904 size_t* count) {
905 GesturesProp* prop = PreGetProperty(device_id, name, NULL, count);
906 return prop ? prop->GetBoolValue(val) : false;
907 }
908
909 bool GesturePropertyProvider::GetStringProperty(const DeviceId device_id,
910 const std::string& name,
911 std::string* val,
912 size_t* count) {
913 GesturesProp* prop = PreGetProperty(device_id, name, NULL, count);
914 return prop ? prop->GetStringValue(val) : false;
915 }
916
917 bool GesturePropertyProvider::GetDoubleProperty(const DeviceId device_id,
918 const std::string& name,
919 double* val,
920 size_t* count) {
921 GesturesProp* prop = PreGetProperty(device_id, name, NULL, count);
922 return prop ? prop->GetDoubleValue(val) : false;
923 }
924
925 template <typename T>
926 GesturesProp* GesturePropertyProvider::PreSetProperty(const DeviceId device_id,
927 const std::string& name,
928 const T* val) {
929 if (!val)
930 return NULL;
931
932 // Return if no property of the name is found.
933 GesturesProp* prop = FindProperty(device_id, name);
934 if (!prop)
935 return NULL;
936
937 // As per the legacy guideline, all read-only properties (created with NULL)
938 // can't be modified. If we want to change this in the future, re-think about
939 // the different cases here.
940 if (prop->is_read_only)
941 return NULL;
942 return prop;
943 }
944
945 bool GesturePropertyProvider::SetIntProperty(const DeviceId device_id,
946 const std::string& name,
947 const int* val) {
948 GesturesProp* prop = PreSetProperty(device_id, name, val);
949 return prop ? prop->SetIntValue(val) : false;
950 }
951
952 bool GesturePropertyProvider::SetShortProperty(const DeviceId device_id,
953 const std::string& name,
954 const short* val) {
955 GesturesProp* prop = PreSetProperty(device_id, name, val);
956 return prop ? prop->SetShortValue(val) : false;
957 }
958
959 bool GesturePropertyProvider::SetBoolProperty(const DeviceId device_id,
960 const std::string& name,
961 const bool* val) {
962 GesturesProp* prop = PreSetProperty(device_id, name, val);
963 return prop ? prop->SetBoolValue(val) : false;
964 }
965
966 bool GesturePropertyProvider::SetStringProperty(const DeviceId device_id,
967 const std::string& name,
968 const char* val) {
969 if (!val)
970 return false;
971 std::string s = val;
972 return SetStringProperty(device_id, name, &s);
973 }
974
975 bool GesturePropertyProvider::SetStringProperty(const DeviceId device_id,
976 const std::string& name,
977 const std::string* val) {
978 GesturesProp* prop = PreSetProperty(device_id, name, val);
979 return prop ? prop->SetStringValue(val) : false;
980 }
981
982 bool GesturePropertyProvider::SetDoubleProperty(const DeviceId device_id,
983 const std::string& name,
984 const double* val) {
985 GesturesProp* prop = PreSetProperty(device_id, name, val);
986 return prop ? prop->SetDoubleValue(val) : false;
987 }
988
989 void GesturePropertyProvider::AddProperty(const DeviceId device_id,
990 const std::string& name,
991 GesturesProp* prop) {
992 // The look-up should never fail because ideally a property can only be
993 // created with GesturesPropCreate* functions from the gesture lib side.
994 // Therefore, we simply return on failure.
995 ScopedDeviceScopedPropertyMap::iterator it = properties_maps_.find(device_id);
996 if (it != properties_maps_.end())
997 it->second->set(name, scoped_ptr<GesturesProp>(prop));
998 }
999
1000 void GesturePropertyProvider::DeleteProperty(const DeviceId device_id,
1001 const std::string& name) {
1002 ScopedDeviceScopedPropertyMap::iterator it = properties_maps_.find(device_id);
1003 if (it != properties_maps_.end())
1004 it->second->erase(name);
1005 }
1006
1007 GesturesProp* GesturePropertyProvider::FindProperty(const DeviceId device_id,
1008 const std::string& name) {
1009 ScopedDeviceScopedPropertyMap::const_iterator ia =
1010 properties_maps_.find(device_id);
1011 if (ia == properties_maps_.end())
1012 return NULL;
1013 ScopedPropertyMap::const_iterator ib = ia->second->find(name);
1014 if (ib == ia->second->end())
1015 return NULL;
1016 return ib->second;
1017 }
1018
1019 GesturesProp* GesturePropertyProvider::GetDefaultProperty(
1020 const DeviceId device_id,
1021 const std::string& name) {
1022 ScopedDevicePropertyMap::const_iterator ia =
1023 default_properties_maps_.find(device_id);
1024 if (ia == default_properties_maps_.end())
1025 return NULL;
1026 PropertyMap::const_iterator ib = ia->second->find(name);
1027 if (ib == ia->second->end())
1028 return NULL;
1029 return ib->second;
1030 }
1031
1032 void GesturePropertyProvider::LoadDeviceConfigurations() {
1033 // Enumerate conf files and sort them lexicographically.
1034 std::set<base::FilePath> files;
1035 base::FileEnumerator file_enum(base::FilePath(kConfigurationFilePath),
1036 false,
1037 base::FileEnumerator::FILES,
1038 "*.conf");
1039 for (base::FilePath path = file_enum.Next(); !path.empty();
1040 path = file_enum.Next()) {
1041 files.insert(path);
1042 }
1043 GPROP_LOG(INFO_SEVERITY) << files.size() << " conf files were found";
1044
1045 // Parse conf files one-by-one.
1046 for (std::set<base::FilePath>::iterator file_iter = files.begin();
1047 file_iter != files.end();
1048 ++file_iter) {
1049 GPROP_LOG(INFO_SEVERITY) << "Parsing conf file: " << (*file_iter).value();
1050 std::string content;
1051 if (!base::ReadFileToString(*file_iter, &content)) {
1052 LOG(ERROR) << "Can't loading gestures conf file: "
1053 << (*file_iter).value();
1054 continue;
1055 }
1056 ParseXorgConfFile(content);
1057 }
1058 }
1059
1060 void GesturePropertyProvider::ParseXorgConfFile(const std::string& content) {
1061 // To simplify the parsing work, we made some assumption about the conf file
1062 // format which doesn't exist in the original xorg-conf spec. Most important
1063 // ones are:
1064 // 1. All keywords and names are now case-sensitive. Also, underscores are not
1065 // ignored.
1066 // 2. Each entry takes up one and exactly one line in the file.
1067 // 3. No negation of the option value even if the option name is prefixed with
1068 // "No" as it may cause problems for option names that does start with "No"
1069 // (e.g., "Non-linearity").
1070
1071 // Break the content into sections, lines and then pieces.
1072 // Sections are delimited by the "EndSection" keyword.
1073 // Lines are delimited by "\n".
1074 // Pieces are delimited by all white-spaces.
1075 std::vector<std::string> sections;
1076 base::SplitStringUsingSubstr(content, "EndSection", &sections);
1077 for (size_t i = 0; i < sections.size(); ++i) {
1078 // Create a new configuration section.
1079 configurations_.push_back(new internal::ConfigurationSection());
1080 internal::ConfigurationSection* config = configurations_.back();
1081
1082 // Break the section into lines.
1083 base::StringTokenizer lines(sections[i], "\n");
1084 bool is_input_class_section = true;
1085 bool has_checked_section_type = false;
1086 while (is_input_class_section && lines.GetNext()) {
1087 // Parse the line w.r.t. the xorg-conf format.
1088 std::string line(lines.token());
1089
1090 // Skip empty lines.
1091 if (line.empty())
1092 continue;
1093
1094 // Treat all whitespaces as delimiters.
1095 base::StringTokenizer pieces(line, base::kWhitespaceASCII);
1096 pieces.set_quote_chars("\"");
1097 bool is_parsing = false;
1098 bool has_error = false;
1099 bool next_is_section_type = false;
1100 bool next_is_option_name = false;
1101 bool next_is_option_value = false;
1102 bool next_is_match_criteria = false;
1103 bool next_is_identifier = false;
1104 std::string match_type, option_name;
1105 while (pieces.GetNext()) {
1106 std::string piece(pieces.token());
1107
1108 // Skip empty pieces.
1109 if (piece.empty())
1110 continue;
1111
1112 // See if we are currently parsing an entry or are still looking for
1113 // one.
1114 if (is_parsing) {
1115 // Stop parsing the current line if the format is wrong.
1116 if (piece.size() <= 2 || piece[0] != '\"' ||
1117 piece[piece.size() - 1] != '\"') {
1118 LOG(ERROR) << "Error parsing line: " << lines.token();
1119 has_error = true;
1120 if (next_is_section_type)
1121 is_input_class_section = false;
1122 break;
1123 }
1124
1125 // Parse the arguments. Note that we don't break even if a whitespace
1126 // string is passed. It will just be handled in various ways based on
1127 // the entry type.
1128 std::string arg;
1129 base::TrimWhitespaceASCII(
1130 piece.substr(1, piece.size() - 2), base::TRIM_ALL, &arg);
1131 if (next_is_section_type) {
1132 // We only care about InputClass sections.
1133 if (arg != "InputClass") {
1134 has_error = true;
1135 is_input_class_section = false;
1136 } else {
1137 GPROP_LOG(INFO_SEVERITY) << "New InputClass section found";
1138 has_checked_section_type = true;
1139 }
1140 break;
1141 } else if (next_is_identifier) {
1142 GPROP_LOG(INFO_SEVERITY) << "Identifier: " << arg;
1143 config->identifier = arg;
1144 next_is_identifier = false;
1145 break;
1146 } else if (next_is_option_name) {
1147 // TODO(sheckylin): Support option "Ignore".
1148 option_name = arg;
1149 next_is_option_value = true;
1150 next_is_option_name = false;
1151 } else if (next_is_option_value) {
1152 GesturesProp* prop = CreateDefaultProperty(option_name, arg);
1153 if(prop)
1154 config->properties.push_back(prop);
1155 next_is_option_value = false;
1156 break;
1157 } else if (next_is_match_criteria) {
1158 // Skip all match types that are not supported.
1159 if (IsMatchTypeSupported(match_type)) {
1160 internal::MatchCriteria* criteria =
1161 CreateMatchCriteria(match_type, arg);
1162 if (criteria)
1163 config->criterias.push_back(criteria);
1164 }
1165 next_is_match_criteria = false;
1166 break;
1167 }
1168 } else {
1169 // If the section type hasn't been decided yet, look for it.
1170 // Otherwise, look for valid entries according to the spec.
1171 if (has_checked_section_type) {
1172 if (piece == "Driver") {
1173 // TODO(sheckylin): Support "Driver" so that we can force a device
1174 // not to use the gesture lib.
1175 NOTIMPLEMENTED();
1176 break;
1177 } else if (piece == "Identifier") {
1178 is_parsing = true;
1179 next_is_identifier = true;
1180 continue;
1181 } else if (piece == "Option") {
1182 is_parsing = true;
1183 next_is_option_name = true;
1184 continue;
1185 } else if (piece.size() > 5 && piece.compare(0, 5, "Match") == 0) {
1186 match_type = piece;
1187 is_parsing = true;
1188 next_is_match_criteria = true;
1189 continue;
1190 }
1191 } else if (piece == "Section") {
1192 is_parsing = true;
1193 next_is_section_type = true;
1194 continue;
1195 }
1196
1197 // If none of the above is found, check if the current piece starts a
1198 // comment.
1199 if (piece.empty() || piece[0] != '#') {
1200 LOG(ERROR) << "Error parsing line: " << lines.token();
1201 has_error = true;
1202 }
1203 break;
1204 }
1205 }
1206
1207 // The value of a boolean option is skipped (default is true).
1208 if (!has_error && (next_is_option_value || next_is_match_criteria)) {
1209 if (next_is_option_value) {
1210 GesturesProp* prop = CreateDefaultProperty(option_name, "on");
1211 if (prop)
1212 config->properties.push_back(prop);
1213 } else if (IsMatchTypeSupported(match_type) &&
1214 IsMatchDeviceType(match_type)) {
1215 internal::MatchCriteria* criteria =
1216 CreateMatchCriteria(match_type, "on");
1217 if (criteria)
1218 config->criterias.push_back(criteria);
1219 }
1220 }
1221 }
1222
1223 // Remove useless config sections.
1224 if (!is_input_class_section ||
1225 (config->criterias.empty() && config->properties.empty())) {
1226 configurations_.pop_back();
1227 }
1228 }
1229 }
1230
1231 internal::MatchCriteria*
1232 GesturePropertyProvider::CreateMatchCriteria(const std::string& match_type,
1233 const std::string& arg) {
1234 GPROP_LOG(INFO_SEVERITY) << "Creating match criteria: (" << match_type << ", "
1235 << arg << ")";
1236 if (match_type == "MatchProduct")
1237 return new internal::MatchProduct(arg);
1238 if (match_type == "MatchDevicePath")
1239 return new internal::MatchDevicePath(arg);
1240 if (match_type == "MatchUSBID")
1241 return new internal::MatchUSBID(arg);
1242 if (match_type == "MatchIsPointer")
1243 return new internal::MatchIsPointer(arg);
1244 if (match_type == "MatchIsTouchpad")
1245 return new internal::MatchIsTouchpad(arg);
1246 if (match_type == "MatchIsTouchscreen")
1247 return new internal::MatchIsTouchscreen(arg);
1248 NOTREACHED();
1249 return NULL;
1250 }
1251
1252 GesturesProp* GesturePropertyProvider::CreateDefaultProperty(
1253 const std::string& name,
1254 const std::string& value) {
1255 // Our parsing rule:
1256 // 1. No hex or oct number is accepted.
1257 // 2. All numbers will be stored as double.
1258 // 3. Array elements can be separated by both white-spaces or commas.
1259 // 4. A token is treated as numeric either if it is one of the special
1260 // keywords for boolean values (on, true, yes, off, false, no) or if
1261 // base::StringToDouble succeeds.
1262 // 5. The property is treated as numeric if and only if all of its elements
1263 // (if any) are numerics. Otherwise, it will be treated as a string.
1264 // 6. A string property will be trimmed before storing its value.
1265 GPROP_LOG(INFO_SEVERITY) << "Creating default property: (" << name << ", "
1266 << value << ")";
1267
1268 // Parse elements one-by-one.
1269 std::string delimiters(base::kWhitespaceASCII);
1270 delimiters.append(",");
1271 base::StringTokenizer tokens(value, delimiters);
1272 bool is_all_numeric = true;
1273 std::vector<double> numbers;
1274 while (tokens.GetNext()) {
1275 // Skip empty tokens.
1276 std::string token(tokens.token());
1277 if (token.empty())
1278 continue;
1279
1280 // Check if it is a boolean keyword.
1281 int bool_result = ParseBooleanKeyword(token);
1282 if (bool_result) {
1283 numbers.push_back(bool_result > 0);
1284 continue;
1285 }
1286
1287 // Check if it is a number.
1288 double real_result;
1289 bool success = base::StringToDouble(token, &real_result);
1290 if (!success) {
1291 is_all_numeric = false;
1292 break;
1293 }
1294 numbers.push_back(real_result);
1295 }
1296
1297 // Create the GesturesProp. Array properties need to contain at least one
1298 // number and may contain numbers only.
1299 GesturesProp* prop = NULL;
1300 if (is_all_numeric && numbers.size()) {
1301 prop = new GesturesDoubleProp(
1302 name, numbers.size(), NULL, numbers.data(), NULL);
1303 } else {
1304 prop = new GesturesStringProp(name, NULL, value.c_str(), NULL);
1305 }
1306
1307 GPROP_LOG(INFO_SEVERITY) << "Prop: " << *prop;
1308 // The function will always succeed for now but it may change later if we
1309 // specify some name or args as invalid.
1310 return prop;
1311 }
1312
1313 void GesturePropertyProvider::SetupDefaultProperties(
1314 const DeviceId device_id,
1315 DevicePtr dev) {
1316 GPROP_LOG(INFO_SEVERITY) << "Setting up default properties for (" << dev
1317 << ", " << device_id << ", " << dev->info.name
1318 << ")";
1319
1320 // Go through all parsed sections.
1321 scoped_ptr<PropertyMap> prop_map(new PropertyMap);
1322 for (size_t i = 0; i < configurations_.size(); i++) {
1323 if (configurations_[i]->Match(dev)) {
1324 GPROP_LOG(INFO_SEVERITY) << "Conf section \""
1325 << configurations_[i]->identifier
1326 << "\" is matched";
1327 for (size_t j = 0; j < configurations_[i]->properties.size(); j++) {
1328 GesturesProp* prop = configurations_[i]->properties[j];
1329 // We can't use insert here because a property may be set for several
1330 // times along the way.
1331 (*prop_map)[prop->name] = prop;
1332 }
1333 }
1334 }
1335 default_properties_maps_.set(device_id, prop_map.Pass());
1336 }
1337
1338 GesturesProp* GesturesPropFunctionsWrapper::PreCreateProperty(void* priv,
1339 const char* name) {
1340 GesturePropertyProvider* provider = GetPropertyProvider(priv);
1341 GesturePropertyProvider::DevicePtr dev = GetDevicePointer(priv);
1342
1343 // Create a new PropertyMap for the device if not exists already.
1344 GesturePropertyProvider::DeviceId device_id =
1345 provider->GetDeviceId(dev, true);
1346
1347 // First, see if the GesturesProp already exists.
1348 GPROP_LOG(3) << "Creating Property: \"" << name << "\"";
1349 GesturesProp* prop = provider->FindProperty(device_id, name);
1350
1351 // If so, delete it as we can't reuse the data structure (newly-created
1352 // property may have different data type and count, which are fixed upon
1353 // creation via the template mechanism).
1354 if (prop) {
1355 LOG(WARNING) << "Gesture property \"" << name
1356 << "\" re-created. This shouldn't happen at the normal usage.";
1357 Free(dev, prop);
1358 }
1359
1360 // Return the found default property from conf files (could be NULL).
1361 return provider->GetDefaultProperty(device_id, name);
1362 }
1363
1364 void GesturesPropFunctionsWrapper::PostCreateProperty(void* priv,
1365 const char* name,
1366 GesturesProp* prop) {
1367 GesturePropertyProvider* provider = GetPropertyProvider(priv);
1368 GesturePropertyProvider::DevicePtr dev = GetDevicePointer(priv);
1369
1370 // Add the property to the gesture property provider. The gesture property
1371 // provider will own it from now on.
1372 provider->AddProperty(provider->GetDeviceId(dev, false), name, prop);
1373
1374 // Log the creation.
1375 GPROP_LOG(INFO_SEVERITY) << "Created active prop: " << *prop;
1376 }
1377
1378 template <typename T, class PROPTYPE>
1379 GesturesProp* GesturesPropFunctionsWrapper::CreateProperty(void* priv,
alexst (slow to review) 2014/10/03 22:32:02 Please define parameter names in full without abbr
Shecky Lin 2014/10/08 10:51:00 Done.
1380 const char* name,
1381 T* val,
1382 size_t count,
1383 const T* init) {
1384 // Create the property. Use the default property value if possible.
1385 GesturesProp* prop =
1386 new PROPTYPE(name, count, val, init, PreCreateProperty(priv, name));
1387
1388 PostCreateProperty(priv, name, prop);
1389 return prop;
1390 }
1391
1392 GesturesProp* GesturesPropFunctionsWrapper::CreateInt(void* priv,
1393 const char* name,
1394 int* val,
1395 size_t count,
1396 const int* init) {
1397 return CreateProperty<int, GesturesIntProp>(
1398 priv, name, val, count, init);
1399 }
1400
1401 GesturesProp* GesturesPropFunctionsWrapper::CreateShort(void* priv,
1402 const char* name,
1403 short* val,
1404 size_t count,
1405 const short* init) {
1406 return CreateProperty<short, GesturesShortProp>(
1407 priv, name, val, count, init);
1408 }
1409
1410 GesturesProp* GesturesPropFunctionsWrapper::CreateBool(
1411 void* priv,
1412 const char* name,
1413 GesturesPropBool* val,
1414 size_t count,
1415 const GesturesPropBool* init) {
1416 return CreateProperty<GesturesPropBool, GesturesBoolProp>(
1417 priv, name, val, count, init);
1418 }
1419
1420 GesturesProp* GesturesPropFunctionsWrapper::CreateReal(void* priv,
1421 const char* name,
1422 double* val,
1423 size_t count,
1424 const double* init) {
1425 return CreateProperty<double, GesturesDoubleProp>(
1426 priv, name, val, count, init);
1427 }
1428
1429 GesturesProp* GesturesPropFunctionsWrapper::CreateString(void* priv,
1430 const char* name,
1431 const char** val,
1432 const char* init) {
1433 GesturesProp* prop =
1434 new GesturesStringProp(name, val, init, PreCreateProperty(priv, name));
1435
1436 PostCreateProperty(priv, name, prop);
1437 return prop;
1438 }
1439
1440 void GesturesPropFunctionsWrapper::RegisterHandlers(
1441 void* priv,
1442 GesturesProp* prop,
1443 void* handler_data,
1444 GesturesPropGetHandler get,
1445 GesturesPropSetHandler set) {
1446 // Sanity checks
1447 if (!priv || !prop)
1448 return;
1449
1450 prop->handler_data = handler_data;
1451 prop->get = get;
1452 prop->set = set;
1453 }
1454
1455 void GesturesPropFunctionsWrapper::Free(void* priv, GesturesProp* prop) {
1456 if (!prop)
1457 return;
1458
1459 GesturePropertyProvider* provider = GetPropertyProvider(priv);
1460 GesturePropertyProvider::DevicePtr dev = GetDevicePointer(priv);
1461 GesturePropertyProvider::DeviceId device_id =
1462 provider->GetDeviceId(dev, false);
1463 if (device_id < 0)
1464 return;
1465
1466 // No need to manually delete the prop pointer as it is implicitly handled
1467 // with scoped ptr.
1468 GPROP_LOG(3) << "Freeing Property: \"" << prop->name << "\"";
1469 provider->DeleteProperty(device_id, prop->name);
1470 }
1471
1472 GesturesProp* GesturesPropFunctionsWrapper::CreateIntSingle(
1473 void* priv,
1474 const char* name,
1475 int* val,
1476 int init) {
1477 return CreateInt(priv, name, val, 1, &init);
1478 }
1479
1480 GesturesProp* GesturesPropFunctionsWrapper::CreateBoolSingle(
1481 void* priv,
1482 const char* name,
1483 GesturesPropBool* val,
1484 GesturesPropBool init) {
1485 return CreateBool(priv, name, val, 1, &init);
1486 }
1487
1488 GesturePropertyProvider* GesturesPropFunctionsWrapper::GetPropertyProvider(
1489 void* priv) {
1490 return static_cast<GestureInterpreterLibevdevCros*>(priv)
1491 ->GetPropertyProvider();
1492 }
1493
1494 GesturePropertyProvider::DevicePtr
1495 GesturesPropFunctionsWrapper::GetDevicePointer(void* priv) {
1496 return static_cast<GestureInterpreterLibevdevCros*>(priv)->GetDevicePointer();
1497 }
1498
1499 bool GesturesPropFunctionsWrapper::InitializeDeviceProperties(
1500 void* priv,
1501 GestureDeviceProperties* props) {
1502 if (!priv)
1503 return false;
1504 GesturePropertyProvider::DevicePtr dev = GetDevicePointer(priv);
1505
1506 /* Create Device Properties */
1507
1508 // Read Only properties.
1509 CreateString(priv, "Device Node", NULL, GetDeviceNodePath(dev).c_str());
1510 short vid = static_cast<short>(dev->info.id.vendor);
1511 CreateShort(priv, "Device Vendor ID", NULL, 1, &vid);
1512 short pid = static_cast<short>(dev->info.id.product);
1513 CreateShort(priv, "Device Product ID", NULL, 1, &pid);
1514
1515 // Useable trackpad area. If not configured in .conf file,
1516 // use x/y valuator min/max as reported by kernel driver.
1517 CreateIntSingle(
1518 priv, "Active Area Left", &props->area_left, Event_Get_Left(dev));
1519 CreateIntSingle(
1520 priv, "Active Area Right", &props->area_right, Event_Get_Right(dev));
1521 CreateIntSingle(
1522 priv, "Active Area Top", &props->area_top, Event_Get_Top(dev));
1523 CreateIntSingle(
1524 priv, "Active Area Bottom", &props->area_bottom, Event_Get_Bottom(dev));
1525
1526 // Trackpad resolution (pixels/mm). If not configured in .conf file,
1527 // use x/y resolution as reported by kernel driver.
1528 CreateIntSingle(
1529 priv, "Vertical Resolution", &props->res_y, Event_Get_Res_Y(dev));
1530 CreateIntSingle(
1531 priv, "Horizontal Resolution", &props->res_x, Event_Get_Res_X(dev));
1532
1533 // Trackpad orientation minimum/maximum. If not configured in .conf file,
1534 // use min/max as reported by kernel driver.
1535 CreateIntSingle(priv,
1536 "Orientation Minimum",
1537 &props->orientation_minimum,
1538 Event_Get_Orientation_Minimum(dev));
1539 CreateIntSingle(priv,
1540 "Orientation Maximum",
1541 &props->orientation_maximum,
1542 Event_Get_Orientation_Maximum(dev));
1543
1544 // Log dump property. Will call Event_Dump_Debug_Log when its value is being
1545 // set.
1546 GesturesProp* dump_debug_log_prop =
1547 CreateBoolSingle(priv, "Dump Debug Log", &props->dump_debug_log, false);
1548 RegisterHandlers(priv, dump_debug_log_prop, dev, NULL, Event_Dump_Debug_Log);
1549
1550 // Whether to do the gesture recognition or just passing the multi-touch data
1551 // to upper layers.
1552 CreateBoolSingle(
1553 priv, "Raw Touch Passthrough", &props->raw_passthrough, false);
1554 return true;
1555 }
1556
1557 /* Global GesturesPropProvider
1558 *
1559 * Used by PropRegistry in GestureInterpreter to forward property value
1560 * creations from there.
1561 * */
1562 const GesturesPropProvider kGesturePropProvider = {
1563 GesturesPropFunctionsWrapper::CreateInt,
1564 GesturesPropFunctionsWrapper::CreateShort,
1565 GesturesPropFunctionsWrapper::CreateBool,
1566 GesturesPropFunctionsWrapper::CreateString,
1567 GesturesPropFunctionsWrapper::CreateReal,
1568 GesturesPropFunctionsWrapper::RegisterHandlers,
1569 GesturesPropFunctionsWrapper::Free};
1570
1571 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698