import gtk
import wnck
import gobject
import struct

screen = wnck.screen_get_default()

# Copied from <linux/joystick.h>
JS_EVENT_STRUCT = "@IhBB"
JS_EVENT_STRUCT_SIZE = struct.calcsize(JS_EVENT_STRUCT)

# Configuration
JS_DEVICE = "/dev/input/js0"
JS_DEVICE_INPUT = 0 # which input should we listen to?
JS_DEVICE_MIRROR = True # Does positive movement mean left?
MOVE_THRESHOLD = 300 # how far the joystick must twitch to trigger a move
DEBOUNCE_TIME = 500 # how long we ignore movement after a successful move

# Helpful globals
lastEventTime = 0 # for debouncing

def moveViewportHorizontallyBy(screens):
	screenWidth = screen.get_width()
	ws = screen.get_active_workspace()

	currPos = ws.get_viewport_x()
	maxPos = ws.get_width()
	newPos = (currPos + screens * screenWidth) % maxPos

	screen.move_viewport(newPos, ws.get_viewport_y())

def jsRead(source, condition):
	global lastEventTime
	data = source.read(JS_EVENT_STRUCT_SIZE)
	(timestamp, value, eventType, inputNum) = struct.unpack(
			JS_EVENT_STRUCT, data)

	# Ignore all other inputs
	if inputNum != JS_DEVICE_INPUT:
		return True

	print "At %sms, got a %d event from input %d whose value was %d" % (
			timestamp, eventType, inputNum, value)

	# Ignore the initial state event, and button events.
	if eventType & 0x80 or eventType & 0x01:
		return True

	# If we've processed an event recently, the joystick is probably settling
	# from the last event.
	if timestamp < lastEventTime + DEBOUNCE_TIME:
		return True

	if abs(value) > MOVE_THRESHOLD:
		# We got one!
		lastEventTime = timestamp

		if JS_DEVICE_MIRROR:
			value *= -1

		if value > 0:
			moveViewportHorizontallyBy(1)
		else:
			moveViewportHorizontallyBy(-1)

	return True

def jsProblem(source, condition):
	print "Got problem %r reading source %r" % (condition, source)
	gtk.main_quit()
	return False

if __name__ == "__main__":
	js = open("/dev/input/js0", "rb")
	gobject.io_add_watch(js, gobject.IO_IN, jsRead)
	gobject.io_add_watch(js, gobject.IO_ERR, jsProblem)
	gobject.io_add_watch(js, gobject.IO_HUP, jsProblem)

	gtk.main()
