The following thread got me wondering if there could be a better fix to the Linux mouse wheel issue.
After some brainstorming/digging around I came up with the following workaround which is way better than what I've desribed in that thread.
As this is a workaround it will hopefully become obsolete with A20 (spring aka summer as per Madmole in "A20 dev diary 1"), as the thread I refer above mentions A20 to update Unity which should fix the bug - see this specific reply from @unholyjoe
However, the idea for the workaround is to remap the mouse wheel in the desktop before starting the game, and reset it back to normal after the game exits.
This is done using the tool xinput.
By doing this it means that the default mappings kan be kept inside 7 Days To Die, which will make everything work as it should inside the game (toolbar scrolling, inventory scrolling, scope zooming, map zooming).
The downside is that the desktop itself will also have the wheel inverted.
In my case it doesn't matter much, as I don't use the desktop while gaming, but if you e.g. use a browser while the game is running, you either have to accept scrolling the wrong way, or use pageup/pagedown instead.
Long story short, I created the script below, so that I start the game by executing the script instead of from inside the Steam client.
The script can be started either from a desktop menu, desktop icon or commandline.
If Steam was already running before starting this script, Steam keeps running after the game is exited.
If Steam was not running before starting this script, Steam will automatically be started in order to start the game, and after exiting the game Steam will be closed again. If you don't like that behavior, you can remove the "killall steam" command from the script to keep Steam running in this case as well.
To use the script, you need to modify two variables in the script: XINPUT_DEVICE and XINPUT_PROPERTY
To figure out what your device ID is, use the command "xinput list" and look for "slave pointer". On my system it's 8.
To figure out what the property ID that we need to invert, use the command "xinput list-props <device ID from previous command>".
Then find the ID of "Evdev Scrolling Distance". On my system it's 296.
With that in mind, use the following script to start 7 Days To Die, but update the two variables XINPUT_DEVICE and XINPUT_PROPERTY at the top of the script, with the values you find from the two commands described above.
After some brainstorming/digging around I came up with the following workaround which is way better than what I've desribed in that thread.
As this is a workaround it will hopefully become obsolete with A20 (spring aka summer as per Madmole in "A20 dev diary 1"), as the thread I refer above mentions A20 to update Unity which should fix the bug - see this specific reply from @unholyjoe
However, the idea for the workaround is to remap the mouse wheel in the desktop before starting the game, and reset it back to normal after the game exits.
This is done using the tool xinput.
By doing this it means that the default mappings kan be kept inside 7 Days To Die, which will make everything work as it should inside the game (toolbar scrolling, inventory scrolling, scope zooming, map zooming).
The downside is that the desktop itself will also have the wheel inverted.
In my case it doesn't matter much, as I don't use the desktop while gaming, but if you e.g. use a browser while the game is running, you either have to accept scrolling the wrong way, or use pageup/pagedown instead.
Long story short, I created the script below, so that I start the game by executing the script instead of from inside the Steam client.
The script can be started either from a desktop menu, desktop icon or commandline.
If Steam was already running before starting this script, Steam keeps running after the game is exited.
If Steam was not running before starting this script, Steam will automatically be started in order to start the game, and after exiting the game Steam will be closed again. If you don't like that behavior, you can remove the "killall steam" command from the script to keep Steam running in this case as well.
To use the script, you need to modify two variables in the script: XINPUT_DEVICE and XINPUT_PROPERTY
To figure out what your device ID is, use the command "xinput list" and look for "slave pointer". On my system it's 8.
Code:
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ Logitech G9 Laser Mouse id=8 [slave pointer (2)]
⎜ ↳ Logitech G9 Laser Mouse Consumer Control id=10 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ Power Button id=6 [slave keyboard (3)]
↳ Power Button id=7 [slave keyboard (3)]
↳ Logitech G9 Laser Mouse Keyboard id=9 [slave keyboard (3)]
↳ G15 Gaming Keyboard id=11 [slave keyboard (3)]
↳ G15 Gaming Keyboard Consumer Control id=12 [slave keyboard (3)]
↳ G15 GamePanel LCD Keypad id=13 [slave keyboard (3)]
↳ Burr-Brown from TI USB Audio DAC id=14 [slave keyboard (3)]
To figure out what the property ID that we need to invert, use the command "xinput list-props <device ID from previous command>".
Then find the ID of "Evdev Scrolling Distance". On my system it's 296.
Code:
Device 'Logitech G9 Laser Mouse':
Device Enabled (155): 1
Coordinate Transformation Matrix (157): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
Device Accel Profile (287): 0
Device Accel Constant Deceleration (288): 1.000000
Device Accel Adaptive Deceleration (289): 1.000000
Device Accel Velocity Scaling (290): 10.000000
Device Product ID (276): 1133, 49224
Device Node (277): "/dev/input/event14"
Evdev Axis Inversion (291): 0, 0
Evdev Axes Swap (293): 0
Axis Labels (294): "Rel X" (165), "Rel Y" (166), "Rel Horiz Wheel" (285), "Rel Vert Wheel" (286), "None" (0), "None" (0)
Button Labels (295): "Button Left" (158), "Button Middle" (159), "Button Right" (160), "Button Wheel Up" (161), "Button Wheel Down" (162), "Button Horiz Wheel Left" (163), "Button Horiz Wheel Right" (164), "Button Side" (280), "Button Extra" (281), "Button Forward" (282), "Button Back" (283), "Button Task" (284), "Button Unknown" (279), "Button Unknown" (279), "Button Unknown" (279), "Button Unknown" (279), "Button Unknown" (279), "Button Unknown" (279), "Button Unknown" (279), "Button Unknown" (279), "Button Unknown" (279), "Button Unknown" (279), "Button Unknown" (279), "Button Unknown" (279)
Evdev Scrolling Distance (296): 1, 1, 1
Evdev Middle Button Emulation (297): 0
Evdev Middle Button Timeout (298): 50
Evdev Middle Button Button (299): 2
Evdev Third Button Emulation (300): 0
Evdev Third Button Emulation Timeout (301): 1000
Evdev Third Button Emulation Button (302): 3
Evdev Third Button Emulation Threshold (303): 20
Evdev Wheel Emulation (304): 0
Evdev Wheel Emulation Axes (305): 0, 0, 4, 5
Evdev Wheel Emulation Inertia (306): 10
Evdev Wheel Emulation Timeout (307): 200
Evdev Wheel Emulation Button (308): 4
Evdev Drag Lock Buttons (309): 0
With that in mind, use the following script to start 7 Days To Die, but update the two variables XINPUT_DEVICE and XINPUT_PROPERTY at the top of the script, with the values you find from the two commands described above.
Code:
#!/bin/bash
#INFO: This script will fix the scrolling problem in 7 Days To Die by inverting desktop setup of mouse scroll wheel
# You must identify the XINPUT_DEVICE and XINPUT_PROPERTY.
# Use "xinput list" to find device (should be of type "slave pointer") (XINPUT_DEVICE parameter below)
# Use "xinput list-props <DEVICE ID>" to find ID of "Evdev Scrolling Distance" (XINPUT_PROPERTY parameter below)
#Change these two according to your system
XINPUT_DEVICE=8
XINPUT_PROPERTY=296
XINPUT_INVERTED="-1 1 1"
XINPUT_NONINVERTED="1 1 1"
GAME_NAME="7 Days To Die"
#7 Days To Die Steam AppID and game executable
APPID=251570
GAME_EXECUTABLE_NAME="7daystodie.x86_64"
function print_header {
LINE_LENGTH=70
INPUT_LENGTH=${#1}
PADDING_LENGTH=$(( $LINE_LENGTH - $INPUT_LENGTH - 6 ))
PADDING=""
CYAN_COLOR='\033[1;36m'
RESET_COLOR='\033[0m'
FRAME=""
#Build frame
for ((i=0;i<$LINE_LENGTH;i++))
do
FRAME+="*"
done
#Build padding
for ((i=0;i<$PADDING_LENGTH;i++))
do
PADDING+="*"
done
#Print header consiting of two newlines, a row of stars, a row with the text and a row of stars e.g.
#
#
#**********************************************************************
#*** Update system ****************************************************
#**********************************************************************
echo ""
echo ""
echo -e "${CYAN_COLOR}${FRAME}${RESET_COLOR}"
echo -e "${CYAN_COLOR}*** $1 $PADDING*${RESET_COLOR}"
echo -e "${CYAN_COLOR}${FRAME}${RESET_COLOR}"
}
##Invert mouse wheel
print_header "Inverting mouse wheel scrolling"
xinput set-prop $XINPUT_DEVICE $XINPUT_PROPERTY $XINPUT_INVERTED
##Determine if steam was already running
STEAM_ALREADY_RUNNING=$(ps ax|grep -i "steam"|wc -l)
if [ "$STEAM_ALREADY_RUNNING" -eq "1" ]
then
print_header "Starting Steam"
else
print_header "Steam is already running"
fi
##Execute 7 Days To Die - suppress all output and run command in background as steam could already be running
print_header "Starting ${GAME_NAME}"
steam steam://rungameid/$APPID &> /dev/null &
##Wait for the game to finish before proceeding
GAME_WAS_STARTED=0
CONTINUE=1
while [ $CONTINUE -eq 1 ]
do
#Wait for 1 second between each iteration
sleep 1s
#Check how many processes contain '7daystodie.x86_64'. If only one, it's our own command we find. Two means the game is still running
PROCESS_COUNT=$(ps ax|grep -i "${GAME_EXECUTABLE_NAME}"|wc -l)
#This part will set GAME_WAS_STARTED to 1 as soon as the game process starts
if [ $GAME_WAS_STARTED -eq 0 ]
then
if [ "$PROCESS_COUNT" -ne "1" ]
then
GAME_WAS_STARTED=1
print_header "Waiting for ${GAME_NAME} to be closed"
fi
continue
fi
#This part will only be reached after the game has actually been started
if [ "$PROCESS_COUNT" -eq "1" ]
then
#If only one line is returned by above command, 7 days to die is no longer running
CONTINUE=0
fi
done
##Now we do the cleanup activities
#Reset mouse wheel back to normal
print_header "Resetting mouse wheel scrolling to normal"
xinput set-prop $XINPUT_DEVICE $XINPUT_PROPERTY $XINPUT_NONINVERTED
##Stop Steam - hopefully gracefully
if [ "$STEAM_ALREADY_RUNNING" -eq "1" ]
then
print_header "Stopping Steam, as it was started by ${GAME_NAME}"
killall steam
else
print_header "Leaving Steam open. It was already running before ${GAME_NAME}"
fi
##All done
print_header "Done"