#!/usr/bin/python

import gtk, gtk.glade, gtk.gdk
import egg.trayicon
import time, sys, math
from Xlib import display, X
from threading import Thread

class SteadyHamster:

	def __init__(self):
		self.mainGlade = gtk.glade.XML("steadyhamster.glade", "winMain", None)
		
		self.window = self.mainGlade.get_widget("winMain")
		
		signals = {
			"on_btnOK_clicked" : self.showHideWin,
			"on_btnQuit_clicked" : self.quit,
			"on_scaleSmoothing_change_value" : self.updateScale,
		}
		
		self.mainGlade.signal_autoconnect(signals)

		self.tray = egg.trayicon.TrayIcon("Steady Hamster")

		eventbox = gtk.EventBox()
		self.tray.add(eventbox)
		
		eventbox.connect("button_press_event", self.showHideWin)
		
		image = gtk.Image()
		image.set_from_file("hamster.svg")
		eventbox.add(image)
		self.tray.show_all()

		self.mousemonitor = MouseMonitor()
		self.mousemonitor.start()
		
	def showHideWin(self, widget = None, event = None):
		if self.window.get_property('visible'):
			self.window.hide()
		else:
			self.window.present()

	def updateScale(self, widget, *args):
		self.mousemonitor.setScale(widget.get_value())
		
	def quit(self, widget = None):
		self.mousemonitor.stop()
		sys.exit(0)

class MouseMonitor(Thread):

	def __init__(self):
		Thread.__init__(self)
		self.gdisplay = gtk.gdk.display_get_default()
		self.xdisplay = display.Display()
		self.running = False
		self.scale = 0.75
		
	def stop(self):
		self.running = False

	def setScale(self, value):
		value = 100 - value
		value /= 200
		value += 0.5
		self.scale = value

	def run(self):
		self.running = True
		#initial mouse state
		pointer = self.gdisplay.get_pointer()
		prev_x = pointer[1]
		prev_y = pointer[2]
		
		while self.running:
			gtk.threads_enter()
			pointer = self.gdisplay.get_pointer()
			gtk.threads_leave()
			x = pointer[1]
			y = pointer[2]
			diffx = (x - prev_x) / 2
			diffy = (y - prev_y) / 2
			self.xdisplay.warp_pointer(-diffx, -diffy)
			self.xdisplay.flush()
			diffx = self.filter(diffx)
			diffy = self.filter(diffy)
#			print "X:", x, "Y:", y, "diffx:", diffx, "diffy:", diffy
			self.xdisplay.warp_pointer(diffx, diffy)
			self.xdisplay.flush()
			prev_x += diffx
			prev_y += diffy
			time.sleep(0.0001)

	def filter(self, value):
		filtered = (1.0 / math.sqrt(1 + pow((value / self.scale), 2)))
		if filtered < 0.1:
			return 0
		else:
			return value * 2

if __name__ == "__main__":
	app = SteadyHamster()
	gtk.threads_init()
	gtk.main()

