1 from pynput import mouse 2 import time 3 import threading 4 5 __DEBUG = False 6 7 def log(msg,debug=False): 8 if __DEBUG or debug: 9 print(msg) 10 11 class MouseMonitor(): 12 __press_time = 0 13 __press_double_state = False 14 __move = (0,0) 15 16 def __init__(self,on_selected=None): 17 if on_selected: 18 self.on_selected = on_selected 19 else: 20 self.on_selected = self.on_selected 21 22 self.listener = mouse.Listener(on_move=self.on_move,on_click=self.on_click) 23 self.listener.start() 24 self.listener.join() 25 26 def on_selected(msg): 27 print('selected "%s" has been copied.' % (msg,)) 28 29 def on_move(self,x,y): 30 if self.__press_time == 0: 31 self.__move = (x,y) 32 # log(self.__press_time,time.time()) 33 # log('Pointer moved to {0}'.format((x,y))) 34 35 def on_click(self,x,y,button,pressed): 36 if str(button) == 'Button.left': 37 if pressed: 38 self.on_pressed(x,y) 39 else: 40 self.on_released(x,y) 41 42 def on_pressed(self,x,y): 43 if self.__press_double_state: 44 # double click 45 # self.__press_double_state = False 46 if not self.check_not_time_out(self.__press_time, time.time(),0.4): # miss double click 47 log('double1 click timeout and reset then') 48 self.reset() 49 self.__press_time = time.time() 50 else: 51 # single click 52 self.__press_time = time.time() 53 # self.__press_double_state = False 54 55 def on_released(self,x,y): 56 if self.__press_double_state: 57 # double click 58 if self.check_not_time_out(self.__press_time, time.time(),0.8): 59 log('double click: %s' % (self.get_copy())) 60 self.on_selected(self.get_copy()) 61 self.__press_double_state = False 62 else: 63 log('double2 click timeout and reset then') 64 self.reset() 65 else: 66 if self.check_not_time_out(self.__press_time, time.time()): 67 log('double click maybe') 68 self.__press_double_state = True 69 threading.Timer(0.5, self.timeout_handler).start() # wait timeout to reset 70 elif not self.check_not_time_out(self.__press_time, time.time(),1): 71 if self.__move != (0,0): 72 self.on_selected(self.get_copy()) 73 log('selected: %s' % (self.get_copy(),)) 74 self.reset() 75 else: 76 log('reset state') 77 self.reset() 78 79 def get_copy(self): 80 import win32clipboard as wc 81 import win32con 82 83 def trigger_copy(): 84 from pynput.keyboard import Key,Controller 85 key = Controller() 86 with key.pressed(Key.ctrl): 87 key.press('c') 88 key.release('c') 89 time.sleep(0.1) # wait for ctrl+c valid 90 91 trigger_copy() 92 msg = '' 93 try: 94 wc.OpenClipboard() 95 msg = wc.GetClipboardData(win32con.CF_UNICODETEXT) 96 wc.CloseClipboard() 97 except TypeError: 98 log('Clipboard Content is TypeError.') 99 return msg 100 101 def reset(self): 102 self.__press_time = 0 103 self.__press_double_state = False 104 self.__move = (0,0) 105 106 def timeout_handler(self): 107 self.reset() 108 log('timeout reset state') 109 110 def check_not_time_out(self,old,new,delta=0.2): 111 if(new - old > delta): # time delta > 0.2s 112 return False 113 else: 114 return True 115 116 117 def printf(msg): 118 log('copy content:'+msg,True) 119 # log('x = {0} , y = {1}'.format(x,y)) 120 121 122 if __name__ == '__main__': 123 mm = MouseMonitor(printf)