Skip to content

Instantly share code, notes, and snippets.

@zezic
Last active November 28, 2020 11:15
Show Gist options
  • Save zezic/5e98f6fc8e6943ad923afc07c2af3af6 to your computer and use it in GitHub Desktop.
Save zezic/5e98f6fc8e6943ad923afc07c2af3af6 to your computer and use it in GitHub Desktop.
Mouse to Joystick for Linux Virtual Joystick https://github.com/zvxryb/Linux-Virtual-Joystick

Created for use with https://github.com/zvxryb/Linux-Virtual-Joystick

Add both files to ~/.config/vjoy/modules/

Edit mouse2joy.py and change paths accordingly to match your username (not "zezic").

Then run vjoy from its folder with ./vjoy mouse2joy

import sys
import json
paths = [
'',
'/usr/lib/python2.7',
'/usr/lib/python2.7/plat-x86_64-linux-gnu',
'/usr/lib/python2.7/lib-tk',
'/usr/lib/python2.7/lib-old',
'/usr/lib/python2.7/lib-dynload',
'/home/zezic/.local/lib/python2.7/site-packages',
'/usr/local/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages',
'/usr/lib/python2.7/dist-packages/gtk-2.0'
]
for path in paths:
sys.path.insert(0, path)
import vjoy
import pyautogui
from threading import Thread
from pymouse import PyMouseEvent
from pykeyboard import PyKeyboardEvent
from Xlib import X
from Xlib.protocol import rq
import zmq
def getVJoyInfo():
return {
'name': 'PSX DualShock',
'relaxis': [],
'absaxis': [vjoy.ABS_X, vjoy.ABS_Y, vjoy.ABS_RX, vjoy.ABS_RY],
'feedback': [],
'buttons': [vjoy.KEY_LEFT, vjoy.KEY_RIGHT, vjoy.KEY_UP,
vjoy.KEY_DOWN, vjoy.BTN_A, vjoy.BTN_B,
vjoy.BTN_X, vjoy.BTN_Y, vjoy.BTN_TL,
vjoy.BTN_TR, vjoy.BTN_TL2, vjoy.BTN_TR2,
vjoy.BTN_SELECT, vjoy.BTN_START, vjoy.BTN_THUMBL,
vjoy.BTN_THUMBR],
'maxeffects': 4
}
class Keyboard(PyKeyboardEvent):
def __init__(self):
PyKeyboardEvent.__init__(self)
self.KEY_1 = False
self.KEY_2 = False
self.KEY_3 = False
self.KEY_4 = False
def handler(self, reply):
data = reply.data
while len(data):
event, data = rq.EventField(None).parse_binary_value(data, self.display.display, None, None)
if event.detail == self.lookup_character_keycode('1'):
if event.type == X.KeyPress:
self.KEY_1 = True
if event.type == X.KeyRelease:
self.KEY_1 = False
if event.detail == self.lookup_character_keycode('2'):
if event.type == X.KeyPress:
self.KEY_2 = True
if event.type == X.KeyRelease:
self.KEY_2 = False
if event.detail == self.lookup_character_keycode('3'):
if event.type == X.KeyPress:
self.KEY_3 = True
if event.type == X.KeyRelease:
self.KEY_3 = False
if event.detail == self.lookup_character_keycode('4'):
if event.type == X.KeyPress:
self.KEY_4 = True
if event.type == X.KeyRelease:
self.KEY_4 = False
class Mouse(PyMouseEvent):
def __init__(self):
PyMouseEvent.__init__(self)
self.left = False
self.right = False
self.mid = False
def click(self, x, y, button, press):
'''Print Fibonacci numbers when the left click is pressed.'''
if button == 1:
self.left = press
if button == 2:
self.right = press
if button == 3:
self.mid = press
m = Mouse()
k = Keyboard()
width = pyautogui.size()[0]
mt = Thread(target=m.run)
mt.start()
kt = Thread(target=k.run)
kt.start()
left = 0
right = 0
context = zmq.Context()
socket = context.socket(zmq.PAIR)
socket.bind('tcp://*:5556')
def doVJoyThink():
global left
global right
speed = 2048
mouse_x = pyautogui.position()[0]
mul = (mouse_x - (width / 4)) / float(width / 2)
x = round(65536 * mul) - 32768
if m.left:
if left < 32768:
left += speed
else:
if left > 0:
left -= speed
if m.right:
if right < 32768:
right += speed
else:
if right > 0:
right -= speed
events = [
[vjoy.EV_ABS, vjoy.ABS_X, x],
[vjoy.EV_ABS, vjoy.ABS_RX, left],
[vjoy.EV_ABS, vjoy.ABS_RY, right],
[vjoy.EV_KEY, vjoy.BTN_A, k.KEY_1],
[vjoy.EV_KEY, vjoy.BTN_B, k.KEY_2],
[vjoy.EV_KEY, vjoy.BTN_X, k.KEY_3],
[vjoy.EV_KEY, vjoy.BTN_Y, k.KEY_4]
]
socket.send(json.dumps({
'x': mul
}))
return events
import gtk
import glib
import json
from time import sleep
from threading import Thread
import zmq
class Canvas(gtk.DrawingArea):
def __init__(self):
super(Canvas, self).__init__()
self.connect("expose_event", self.expose)
self.set_size_request(1600,32)
self.cr = None
self._x = 0
self.context = zmq.Context()
self.socket = self.context.socket(zmq.PAIR)
self.socket.connect('tcp://localhost:5556')
glib.timeout_add(16, self.on_timer)
def expose(self, widget, event):
self.cr = widget.window.cairo_create()
rect = self.get_allocation()
# you can use w and h to calculate relative positions which
# also change dynamically if window gets resized
self.w = rect.width
self.h = rect.height
self.draw()
def draw(self):
# here is the part where you actually draw
self.cr.set_source_rgb(0.1, 0.1, 0.1)
self.cr.rectangle(0, 0, self.w, self.h)
self.cr.fill()
self.cr.set_source_rgb(0.5, 0.5, 0.5)
self.cr.set_line_width(10)
self.cr.move_to(self.w / 2, 0)
self.cr.line_to(self.w / 2, self.h)
self.cr.stroke()
msg = self.socket.recv()
data = json.loads(msg)
mul = data.get('x')
# mul = mul * 0.95 + (mul * mul) * 0.05
x = self.w * mul
self.cr.set_source_rgb(1.0, 0.0, 0.0)
self.cr.set_line_width(10)
self.cr.move_to(x, 0)
self.cr.line_to(x, self.h)
self.cr.stroke()
def on_timer(self):
self.queue_draw()
return True
window = gtk.Window()
window.set_has_frame(False)
window.set_decorated(False)
window.set_keep_above(True)
window.stick()
canvas = Canvas()
window.add(canvas)
window.set_position(gtk.WIN_POS_CENTER)
window.show_all()
gtk.main()
# def gui_thread_func():
# gtk.main()
#
# thread = Thread(target=gui_thread_func)
# thread.start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment