blob: cdee4541f6d1aa98d9d668cbc3b7fd882bec8dac [file] [log] [blame]
#!/bin/sh
# Copyright (c) 2014 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.
XINPUT=/usr/bin/xinput
export DISPLAY=:0
export XAUTHORITY=/home/chronos/.Xauthority
pref_folder="/home/chronos/user/cmt"
if ! [ -d $pref_folder ]; then
mkdir $pref_folder
fi
if [ "$(id -u)" -eq 0 ]; then
chown chronos:chronos $pref_folder
fi;
# Functions for storing preferences
# A preference requires the following global variables:
# pref_${pref}_type: device type this preference is appllied on
# pref_${pref}_validator: a batch match to validate the preference value
# pref_${pref}_default: default value
# apply_${pref}: function to apply the preference to a device
# Also a list of all preference names is stored in the variable: preferences
apply_preference() {
local pref="$1"
local type="$(eval echo \"\${pref_${pref}_type}\")"
local value="$3"
for device in $2; do
if device_is_${type} $device; then
log "Applying $pref=$value to device $device"
apply_${pref} "$device" "$value"
fi
done
}
apply_all_preferences() {
local devices="$1"
for pref in $preferences; do
local value="$(load_preference $pref)"
for device in $devices; do
apply_preference $pref $device "$value"
done
done
}
validate_preference() {
local pref="$1"
local value="$2"
local validator="$(eval echo \"\${pref_${pref}_validator}\")"
case $value in
$validator) true ;;
*)
echo "invalid value '${value}' for preference ${pref}" >&2
false
;;
esac
}
transition_legacy_pref_file() {
local pref=$1
local new_file="$pref_folder/$pref"
case $pref in
"mouse_sensitivity") filename="mouse_sensitivity" ;;
"touchpad_sensitivity") filename="touchpad_sensitivity" ;;
"mouse_swap_lr") filename="mouse_swap_lr_buttons" ;;
"tapclick") filename="touchpad_tap_enable" ;;
"tapdrag") filename="touchpad_tap_drag_enable" ;;
"t5r2_three_finger_click") filename="touchpad_t5r2_3f_click_enable" ;;
*) return ;;
esac
legacy_file="/home/chronos/user/$filename"
if [ -f $legacy_file ]; then
log "mv $legacy_file $new_file"
mv $legacy_file $new_file
chown chronos:chronos $new_file
fi
}
load_preference() {
assert_eq $# 1
local pref="$1"
local default="$(eval echo \"\${pref_${pref}_default}\")"
local file="$pref_folder/$pref"
# The new inputcontrol script uses a different file path to store preferences
# Make sure to copy the old setting over when the new file does not yet exist.
if [ ! -f $file ]; then
transition_legacy_pref_file $pref
fi
if [ ! -f $file ]; then
echo $default
return
fi
local file_size="$(stat -c %s $file)"
if [ "$file_size" -gt "1000" ]; then
# invalid file size
echo $default
return
fi
local value="$(cat ${file})"
if validate_preference $pref "$value"; then
echo $value
else
echo $default
fi
}
save_preference() {
assert_eq $# 2
local pref="$1"
local value="$2"
local pref_file="$pref_folder/$pref"
if validate_preference "$pref" "$value"; then
log "echo $value > $pref_file"
echo "$value" > $pref_file
fi
}
# Functions to access information about a device
device_get_name() {
assert_eq $# 1
xinput --list --name-only $1
}
device_get_canonical_name() {
assert_eq $# 1
device_get_name $device | sed 's/[^a-zA-Z0-9]/_/g'
}
device_set_prop() {
assert_eq $# 3
log "$XINPUT set-prop \"$1\" \"$2\" $3"
$XINPUT set-prop "$1" "$2" $3
}
device_get_prop() {
assert_eq $# 2
$XINPUT list-props $1 | awk "/$2/ { print \$4 }"
}
device_get_bool_prop() {
assert_eq $# 2
prop=$(device_get_prop $1 "$2")
[ "$prop" = "1" ]
}
device_get_string_prop() {
assert_eq $# 2
prop=$(device_get_prop $1 "$2")
# get rid of " around value via eval
eval echo $prop
}
device_is_mouse() {
assert_eq $# 1
device_get_bool_prop $1 "Device Mouse"
}
device_is_multitouch() {
assert_eq $# 1
device_get_bool_prop $1 "Device Touchpad"
}
device_is_touchpad() {
assert_eq $# 1
! device_is_mouse $1 && device_is_multitouch $1
}
device_is_multitouch_mouse() {
assert_eq $# 1
device_is_mouse $1 && device_is_multitouch $1
}
device_is_nontouch_mouse() {
assert_eq $# 1
device_is_mouse $1 && ! device_is_multitouch $1
}
device_is_touchscreen() {
assert_eq $# 1
device_get_name $1 | grep -q '[tT]ouch[sS]creen'
}
device_is_valid() {
assert_eq $# 1
device_is_mouse $1 || device_is_multitouch $1 || device_is_touchscreen $1
}
device_status() {
assert_eq $# 1
if device_is_valid $1; then
echo
echo "ID $1:"
$XINPUT list-props $1
fi;
}
# Functions to list devices
list_devices() {
# optional first argument is filter method
local filter=device_is_valid
if ! [ -z $1 ]; then
filter=$1
fi
# Search for an xinput entry that contains the "slave pointer"
# Then, find a field that matches "id=".
# Lastly, return the part of the field after the '='.
local devices="$($XINPUT list | \
awk '/.*slave.*/ { for (i=1; i<NF; i++) \
if ($i ~/id=/) print substr($i, 4) }')"
for device in $devices ; do
if $filter $device; then
echo -n " ${device}"
fi
done
}
list_mice() {
list_devices device_is_mouse
}
list_touchpads() {
list_devices device_is_touchpad
}
list_touchscreens() {
list_devices device_is_touchscreen
}
list_multitouch() {
list_devices device_is_multitouch
}
list_multitouch_mice() {
list_devices device_is_multitouch_mouse
}
# Returns the xinput ID of the newly attached mouse. If X hasn't loaded a driver
# for the new mouse, yet, this will not print anything. If found, it prints the
# xinput ID.
get_device_by_devname() {
# Get the list of xinput IDs:
local ids="$(list_devices)"
if [ -z "$ids" ]; then
return
fi
for id in $ids; do
local test_node=$(device_get_prop $id "Device Node")
if [ "$test_node" = "\"$1\"" ]; then
echo $id
return
fi
done
}
wait_and_get_added_device() {
tries=10
while [ "$tries" -ne "0" ]; do
tries=$((tries - 1))
newid=$(get_device_by_devname $1)
if [ -n "$newid" ]; then
echo $newid
return
fi
sleep 1
done
}
canonical_ids() {
# In case minus number is passed, truncate it to the last 4 hexdigits.
# e.g., -16360 -> ffffffffffffc018 -> c018
local id_strings id_str first
read id_strings
for id_str in $id_strings; do
if [ -n "$first" ]; then
printf ":"
fi
printf "%04x" "$id_str" | sed 's/.*\(.\{4\}\)$/\1/'
first="not"
done
}
device_get_vendor_product() {
local xinput_id="$1"
local vp="$(xinput list-props $xinput_id 2>/dev/null \
| fgrep "Device Product ID" | \
cut -d : -f 2 | sed 's/,//' | canonical_ids)"
if ! echo "${vp}" | grep -q ':'; then
vp="$(xinput list-props $xinput_id 2>/dev/null \
| fgrep "Device Vendor ID" | \
cut -d : -f 2 | canonical_ids)"
vp="${vp}:$(xinput list-props $xinput_id 2>/dev/null \
| fgrep "Device Product ID" | \
cut -d : -f 2 | canonical_ids)"
fi
echo "$vp"
}
# Helper for debugging in bash
log() {
if [ ${FLAGS_verbose} -eq ${FLAGS_TRUE} ] ; then
echo "$@" >&2
fi
}
assert_eq() {
if [ "$1" -ne "$2" ]; then
echo "${FUNCNAME[1]}: Assertion '$1' == '$2' failed" >&2
exit -1
fi
}
# FUNCNAME is only available in BASH. Disable assert_eq on all other shells.
if [ -z "$BASH_VERSION" ]; then
assert_eq() { true; }
fi