Created
August 21, 2024 19:30
-
-
Save wheresjames/2f9b2c3d261d6a531f71e2786b59a89a to your computer and use it in GitHub Desktop.
Map touch screens to displays
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
#-------------------------------------------------- | |
# Set touchscreen to monitor mapping | |
declare -A mapping | |
mapping["ELAN9008:00 04F3:4063"]="eDP-1" | |
mapping["ELAN9009:00 04F3:4068"]="DP-1" | |
#-------------------------------------------------- | |
# Generic | |
fix_width() { | |
local input="$1" | |
local width="$2" | |
input=$(echo "$input" | sed 's/\.0*$//' | sed 's/\(\.[0-9]*[1-9]\)0*$/\1/') | |
if [ ${#input} -gt $width ]; then | |
input="${input:0:$width}" | |
else | |
while ((${#input} < $width)); do | |
input="$input " | |
done | |
fi | |
echo "$input" | |
} | |
#-------------------------------------------------- | |
# Show pointer devices | |
# Connected pointing devices | |
echo "--- Pointer devices ---" | |
xinput list | grep "slave pointer" | |
echo | |
#-------------------------------------------------- | |
# Get monitor information | |
# Get monitor information | |
monitor_info=$(xrandr --query | grep ' connected') | |
# Extract monitor names, resolutions, and positions | |
declare -A monitors | |
longest_name=0 | |
while IFS= read -r line; do | |
name=$(echo $line | awk '{print $1}') | |
resolution=$(echo $line | grep -oP '[0-9]+x[0-9]+\+[0-9]+\+[0-9]+') | |
width=$(echo $resolution | cut -d'x' -f1) | |
height=$(echo $resolution | cut -d'x' -f2 | cut -d'+' -f1) | |
x_pos=$(echo $resolution | cut -d'+' -f2) | |
y_pos=$(echo $resolution | cut -d'+' -f3) | |
if [ ${#name} -gt $longest_name ]; then | |
longest_name=${#name} | |
fi | |
monitors[$name]="$width $height $x_pos $y_pos" | |
done <<< "$monitor_info" | |
# Example output of monitor information | |
echo "--- Monitor information ---" | |
for name in "${!monitors[@]}"; do | |
echo "Monitor: $(fix_width "$name" $longest_name) -- ${monitors[$name]}" | |
done | |
echo | |
#-------------------------------------------------- | |
# Calculate total screen dimensions | |
min_x=0 | |
min_y=0 | |
max_x=0 | |
max_y=0 | |
for info in "${monitors[@]}"; do | |
width=$(echo $info | cut -d' ' -f1) | |
height=$(echo $info | cut -d' ' -f2) | |
x_pos=$(echo $info | cut -d' ' -f3) | |
y_pos=$(echo $info | cut -d' ' -f4) | |
# Calculate extents for x | |
if [ $x_pos -lt $min_x ]; then | |
min_x=$x_pos | |
fi | |
right_edge=$((x_pos + width)) | |
if [ $right_edge -gt $max_x ]; then | |
max_x=$right_edge | |
fi | |
# Calculate extents for y | |
if [ $y_pos -lt $min_y ]; then | |
min_y=$y_pos | |
fi | |
bottom_edge=$((y_pos + height)) | |
if [ $bottom_edge -gt $max_y ]; then | |
max_y=$bottom_edge | |
fi | |
done | |
# Calculate total width and height considering negative offsets | |
total_width=$((max_x - min_x)) | |
total_height=$((max_y - min_y)) | |
# Total dimensions | |
echo "Total Width : $total_width" | |
echo "Total Height: $total_height" | |
#-------------------------------------------------- | |
# Map touchscreen to monitor | |
map_touchscreen_to_monitor() { | |
touchscreen_name=$1 | |
monitor_name=$2 | |
if [ -z "${monitors[$monitor_name]}" ]; then | |
echo "Monitor $monitor_name not found." | |
exit 1 | |
fi | |
# Get monitor's width, height, x_pos, and y_pos | |
width=$(echo ${monitors[$monitor_name]} | cut -d' ' -f1) | |
height=$(echo ${monitors[$monitor_name]} | cut -d' ' -f2) | |
x_pos=$(echo ${monitors[$monitor_name]} | cut -d' ' -f3) | |
y_pos=$(echo ${monitors[$monitor_name]} | cut -d' ' -f4) | |
# Adjust x_pos and y_pos to be relative to the overall screen space | |
adjusted_x_pos=$((x_pos - min_x)) | |
adjusted_y_pos=$((y_pos - min_y)) | |
# Calculate the transformation matrix | |
x_scale=$(bc -l <<< "$width / $total_width") | |
y_scale=$(bc -l <<< "$height / $total_height") | |
x_trans=$(bc -l <<< "$adjusted_x_pos / $total_width") | |
y_trans=$(bc -l <<< "$adjusted_y_pos / $total_height") | |
# sw = touch_area_width / total_width | |
# sh = touch_area_height / total_height | |
# xo = touch_area_x_offset / total_width | |
# yo = touch_area_y_offset / total_height | |
# | |
# The matrix is | |
# [ sw 0 xo ] | |
# [ 0 sh yo ] | |
# [ 0 0 1 ] | |
# Apply the transformation matrix using xinput | |
xinput --map-to-output "$touchscreen_name" "$monitor_name" | |
xinput set-prop "$touchscreen_name" "Coordinate Transformation Matrix" $x_scale 0 $x_trans 0 $y_scale $y_trans 0 0 1 | |
echo | |
echo "Mapped $touchscreen_name to $monitor_name" | |
echo "[ $(fix_width $x_scale 6) 0 $(fix_width $x_trans 6) ]" | |
echo "[ 0 $(fix_width $y_scale 6) $(fix_width $y_trans 6) ]" | |
echo "[ 0 0 1 ]" | |
echo "X = ${x_trans:0:6} --> ${x_scale:0:6}" | |
echo "Y = ${y_trans:0:6} --> ${y_scale:0:6}" | |
} | |
for touchscreen in "${!mapping[@]}"; do | |
monitor=${mapping[$touchscreen]} | |
map_touchscreen_to_monitor "$touchscreen" "$monitor" | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment