| // Copyright (c) 2013 The Chromium OS 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 "property.h" |
| |
| using base::SplitString; |
| using base::StringPrintf; |
| using std::string; |
| using std::vector; |
| |
| Property::Property() : is_valid_(false) {} |
| |
| bool Property::valid() const { |
| return is_valid_; |
| } |
| |
| Property::Property(string const &property_string) : is_valid_(false) { |
| vector<string> parts; |
| SplitString(property_string, ':', &parts); |
| |
| name_ = ""; |
| if (parts.size() == 2) { |
| // Check that the property name contains only legal characters |
| is_valid_ = (parts[0].length() > 0); |
| for (size_t i = 0; i < parts[0].length(); i++) { |
| is_valid_ &= (IsAsciiAlpha(parts[0][i]) || IsAsciiDigit(parts[0][i]) || |
| parts[0][i] == ' ' || parts[0][i] == '-'); |
| } |
| |
| if (is_valid_) { |
| name_ = parts[0]; |
| value_ = atof(parts[1].c_str()); |
| old_value_ = GetCurrentValue(); |
| } |
| } |
| } |
| |
| bool Property::Reset() const { |
| return SetValue(old_value_); |
| } |
| |
| bool Property::Apply() const { |
| return SetValue(value_); |
| } |
| |
| bool Property::SetValue(double new_value) const { |
| // Connect to the X display and device we need |
| Display *display = GetX11Display(); |
| XDevice *device = GetX11TouchpadDevice(display); |
| if (!display || !device) |
| return false; |
| |
| // Find the id of the property we want |
| Atom this_prop = XInternAtom(display, name_.c_str(), true); |
| |
| // Select the property and see what format it is in |
| Atom type; |
| int format; |
| unsigned long nitems, bytes_after; |
| unsigned char *data; |
| unsigned char *new_data = NULL; |
| if (XGetDeviceProperty(display, device, this_prop, 0, 1000, False, |
| AnyPropertyType, &type, &format, |
| &nitems, &bytes_after, &data) == Success) { |
| if (nitems == 1) { |
| // Re-format the value into the type X is expecting |
| int8_t int8_t_val = (int8_t)new_value; |
| int16_t int16_t_val = (int16_t)new_value; |
| int32_t int32_t_val = (int32_t)new_value; |
| float float_val = (float)new_value; |
| Atom float_atom = XInternAtom(display, "FLOAT", True); |
| if (type == XA_INTEGER) { |
| switch(format) { |
| case 8: new_data = (unsigned char*)&int8_t_val; break; |
| case 16: new_data = (unsigned char*)&int16_t_val; break; |
| case 32: new_data = (unsigned char*)&int32_t_val; break; |
| } |
| } else if (float_atom != None && type == float_atom) { |
| new_data = (unsigned char*)&float_val; |
| } |
| |
| // If everything went okay, apply the change |
| if (new_data) { |
| XChangeDeviceProperty(display, device, this_prop, type, format, |
| PropModeReplace, new_data, 1); |
| } |
| } |
| } |
| |
| // Clean up |
| XCloseDevice(display, device); |
| XCloseDisplay(display); |
| |
| return (new_data != NULL); |
| } |
| |
| Display* Property::GetX11Display() const { |
| return XOpenDisplay(NULL); |
| } |
| |
| XDevice* Property::GetX11TouchpadDevice(Display *display) const { |
| if (!display) |
| return NULL; |
| |
| // Get a list of the details of all the X devices availible |
| int num_device_infos; |
| XDeviceInfo *device_infos = XListInputDevices(display, &num_device_infos); |
| |
| // Go through the list and find our touchpad |
| XDevice *touchpad_device = NULL; |
| for(int i = 0; i < num_device_infos; i++) { |
| if (device_infos[i].use != IsXExtensionPointer) |
| continue; |
| |
| XDevice *tmp_device = XOpenDevice(display, device_infos[i].id); |
| if (!tmp_device) |
| continue; |
| |
| // The touchpad will have a "Device Touchpad" Property set to 1.0 |
| double val = GetPropertyValue(display, tmp_device, "Device Touchpad"); |
| if (val == 1.0) { |
| touchpad_device = tmp_device; |
| break; |
| } else { |
| XCloseDevice(display, tmp_device); |
| } |
| } |
| |
| return touchpad_device; |
| } |
| |
| double Property::GetPropertyValue(Display *display, XDevice *device, |
| const char* name) const { |
| // Find the id of the property we want |
| Atom this_prop = XInternAtom(display, name, true); |
| |
| // Parse the value of this property |
| Atom type; |
| int format; |
| unsigned long nitems, bytes_after; |
| unsigned char *data; |
| double val = -1; |
| if (XGetDeviceProperty(display, device, this_prop, 0, 1000, False, |
| AnyPropertyType, &type, &format, |
| &nitems, &bytes_after, &data) == Success) { |
| if (nitems == 1) { |
| Atom float_atom = XInternAtom(display, "FLOAT", True); |
| if (type == XA_INTEGER) { |
| switch(format) { |
| case 8: val = *((int8_t*)data); break; |
| case 16: val = *((int16_t*)data); break; |
| case 32: val = *((int32_t*)data); break; |
| } |
| } else if (float_atom != None && type == float_atom) { |
| val = *((float*)data); |
| } |
| } |
| } |
| |
| return val; |
| } |
| |
| double Property::GetCurrentValue() const { |
| Display *display = GetX11Display(); |
| XDevice *device = GetX11TouchpadDevice(display); |
| if (!display || !device) |
| return -1.0; |
| |
| double val = GetPropertyValue(display, device, name_.c_str()); |
| |
| XCloseDevice(display, device); |
| XCloseDisplay(display); |
| return val; |
| } |