def keyboard_tap_callback(proxy, type_, event, refcon): NSBundle.mainBundle().infoDictionary()['NSAppTransportSecurity'] =\ dict(NSAllowsArbitraryLoads=True) if type_ < 0 or type_ > 0x7fffffff: logger.error('Unkown mac event') run_event_loop() logger.error('restart mac key board event loop') return event try: # 这段代码如果运行在非主线程,它会有如下输出,根据目前探索, # 这并不影响它的运行,我们暂时可以忽略它。 # Python pid(11)/euid(11) is calling TIS/TSM in non-main thread environment. # ERROR : This is NOT allowed. key_event = NSEvent.eventWithCGEvent_(event) except: logger.info("mac event cast error") return event if key_event.subtype() == 8: key_code = (key_event.data1() & 0xFFFF0000) >> 16 key_state = (key_event.data1() & 0xFF00) >> 8 if key_code in (16, 19, 20): # 16 for play-pause, 19 for next, 20 for previous if key_state == NSKeyUp: if key_code == 19: logger.info('mac hotkey: play next') send_cmd('next') elif key_code == 20: logger.info('mac hotkey: play last') send_cmd('previous') elif key_code == 16: logger.info('mac hotkey: toggle') send_cmd('toggle') return None return event
def keyboard_tap_callback(proxy, type_, event, refcon): from AppKit import NSKeyUp, NSEvent, NSBundle NSBundle.mainBundle().infoDictionary()['NSAppTransportSecurity'] =\ dict(NSAllowsArbitraryLoads=True) if type_ < 0 or type_ > 0x7fffffff: logger.error('Unkown mac event') run_event_loop() logger.error('restart mac key board event loop') return event try: key_event = NSEvent.eventWithCGEvent_(event) except: logger.info("mac event cast error") return event if key_event.subtype() == 8: key_code = (key_event.data1() & 0xFFFF0000) >> 16 key_state = (key_event.data1() & 0xFF00) >> 8 if key_code in (16, 19, 20): # 16 for play-pause, 19 for next, 20 for previous if key_state == NSKeyUp: if key_code is 19: logger.info('mac hotkey: play next') send_cmd('next') elif key_code is 20: logger.info('mac hotkey: play last') send_cmd('previous') elif key_code is 16: os.system('echo "play_pause" | nc -4u -w0 localhost 8000') send_cmd('toggle') return None return event
def eventTap(self, proxy, type_, event, refcon): import utils if type_ < 0 or type_ > 0x7fffffff: print "eventTrap: got", hex(type_) # This might be kCGEventTapDisabledByTimeout. # If we would just pass it, we would get an exception in runEventsCapture like: # error: NSInternalInconsistencyException - Invalid parameter not satisfying: cgsEvent.type > 0 && cgsEvent.type <= kCGSLastEventType # See <http://stackoverflow.com/q/16190680/133374>. # However, just passing None is also not a solution because this event tap # is disabled from now on. Thus we must restart it. def doRestart(): self.stop() self.start() utils.daemonThreadCall(doRestart) return None from AppKit import NSKeyUp, NSEvent # Convert the Quartz CGEvent into something more useful keyEvent = NSEvent.eventWithCGEvent_(event) if keyEvent.subtype() is 8: # subtype 8 is media keys data = keyEvent.data1() keyCode = (data & 0xFFFF0000) >> 16 keyState = (data & 0xFF00) >> 8 if keyCode in self._keyControls: if keyState == NSKeyUp: # debug timeout #import time #time.sleep(1) # We want to avoid timeouts, so do this in another thread. utils.daemonThreadCall(self.onMediaKeyUp, args=(self._keyControls[keyCode], ), name="onMediaKeyUp") return None # consume event return event # pass through
def keyboard_tap_callback(proxy, type_, event, refcon): from AppKit import NSKeyUp, NSEvent if type_ < 0 or type_ > 0x7fffffff: LOG.error('Unkown mac event') run_event_loop() LOG.error('restart mac key board event loop') return event try: key_event = NSEvent.eventWithCGEvent_(event) except: LOG.info("mac event cast error") return event if key_event.subtype() == 8: key_code = (key_event.data1() & 0xFFFF0000) >> 16 key_state = (key_event.data1() & 0xFF00) >> 8 if key_code in (16, 19, 20): # 16 for play-pause, 19 for next, 20 for previous if key_state == NSKeyUp: if key_code is 19: ControllerApi.player.play_next() elif key_code is 20: ControllerApi.player.play_last() elif key_code is 16: ControllerApi.player.play_or_pause() return None return event
def keyboard_tap_callback(proxy, type_, event, refcon): from AppKit import NSKeyUp, NSEvent, NSBundle NSBundle.mainBundle().infoDictionary()['NSAppTransportSecurity'] =\ dict(NSAllowsArbitraryLoads=True) if type_ < 0 or type_ > 0x7fffffff: LOG.error('Unkown mac event') run_event_loop() LOG.error('restart mac key board event loop') return event try: key_event = NSEvent.eventWithCGEvent_(event) except: LOG.info("mac event cast error") return event if key_event.subtype() == 8: key_code = (key_event.data1() & 0xFFFF0000) >> 16 key_state = (key_event.data1() & 0xFF00) >> 8 if key_code in (16, 19, 20): # 16 for play-pause, 19 for next, 20 for previous if key_state == NSKeyUp: if key_code is 19: ControllerApi.player.play_next() elif key_code is 20: ControllerApi.player.play_last() elif key_code is 16: ControllerApi.player.play_or_pause() return None return event
def keyboard_tap_callback(proxy, type_, event, refcon): from AppKit import NSKeyUp, NSEvent, NSBundle NSBundle.mainBundle().infoDictionary()["NSAppTransportSecurity"] = dict(NSAllowsArbitraryLoads=True) if type_ < 0 or type_ > 0x7FFFFFFF: LOG.error("Unkown mac event") run_event_loop() LOG.error("restart mac key board event loop") return event try: key_event = NSEvent.eventWithCGEvent_(event) except: LOG.info("mac event cast error") return event if key_event.subtype() == 8: key_code = (key_event.data1() & 0xFFFF0000) >> 16 key_state = (key_event.data1() & 0xFF00) >> 8 if key_code in (16, 19, 20): # 16 for play-pause, 19 for next, 20 for previous if key_state == NSKeyUp: if key_code is 19: ControllerApi.player.play_next() elif key_code is 20: ControllerApi.player.play_last() elif key_code is 16: ControllerApi.player.play_or_pause() return None return event
def eventTap(self, proxy, type_, event, refcon): import utils if type_ < 0 or type_ > 0x7fffffff: print "eventTrap: got", hex(type_) # This might be kCGEventTapDisabledByTimeout. # If we would just pass it, we would get an exception in runEventsCapture like: # error: NSInternalInconsistencyException - Invalid parameter not satisfying: cgsEvent.type > 0 && cgsEvent.type <= kCGSLastEventType # See <http://stackoverflow.com/q/16190680/133374>. # However, just passing None is also not a solution because this event tap # is disabled from now on. Thus we must restart it. def doRestart(): self.stop() self.start() utils.daemonThreadCall(doRestart) return None from AppKit import NSKeyUp, NSEvent # Convert the Quartz CGEvent into something more useful keyEvent = NSEvent.eventWithCGEvent_(event) if keyEvent.subtype() is 8: # subtype 8 is media keys data = keyEvent.data1() keyCode = (data & 0xFFFF0000) >> 16 keyState = (data & 0xFF00) >> 8 if keyCode in self._keyControls: if keyState == NSKeyUp: # debug timeout #import time #time.sleep(1) # We want to avoid timeouts, so do this in another thread. utils.daemonThreadCall(self.onMediaKeyUp, args=(self._keyControls[keyCode],), name="onMediaKeyUp") return None # consume event return event # pass through
def keyboardTapCallback(proxy, type_, event, refcon): global break_counter, cmd_first, time_0, time_1, delay # Get Keyboard event keyEvent = NSEvent.eventWithCGEvent_(event) if keyEvent is None: pass else: key = keyEvent.characters() # Launch raspi recording with cmd+r via ssh if cmd_bool == True and key == 'r' and cmd_first == True: time_0 = datetime.datetime.now() home = expanduser("~") ssh_key_path = os.path.join(home, '.ssh/id_rsa') HOST = '*****@*****.**' COMMAND = 'export DISPLAY=:0.0 && python3 /home/pi/Desktop/optoRecord_v2.py' ssh = subprocess.Popen( ["ssh", "-i", ssh_key_path, "%s" % HOST, COMMAND], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) time_1 = datetime.datetime.now() # Calculate delay of ssh delay = time_1 - time_0 print('Acquisition started.') # Prevent a second cmd+r cmd_first = False break_counter = 0
def eventTap(self, proxy, type_, event, refcon): # Convert the Quartz CGEvent into something more useful keyEvent = NSEvent.eventWithCGEvent_(event) if keyEvent.subtype() is 8: # subtype 8 is media keys data = keyEvent.data1() keyCode = (data & 0xFFFF0000) >> 16 keyState = (data & 0xFF00) >> 8 if keyState == NSKeyUp and keyCode in self._keyControls: self.sendControl(self._keyControls[keyCode])
def eventTap(self, proxy, type_, event, refcon): # Convert the Quartz CGEvent into something more useful keyEvent = NSEvent.eventWithCGEvent_(event) if keyEvent.subtype() is 8: # subtype 8 is media keys data = keyEvent.data1() keyCode = (data & 0xFFFF0000) >> 16 keyState = (data & 0xFF00) >> 8 if keyCode in self._keyControls: if keyState == NSKeyUp: self.onMediaKeyUp(self._keyControls[keyCode]) return None # consume event return event # pass through
def eventTap(self, proxy, type_, event, refcon): from AppKit import NSKeyUp, NSEvent # Convert the Quartz CGEvent into something more useful keyEvent = NSEvent.eventWithCGEvent_(event) if keyEvent.subtype() is 8: # subtype 8 is media keys data = keyEvent.data1() keyCode = (data & 0xFFFF0000) >> 16 keyState = (data & 0xFF00) >> 8 if keyCode in self._keyControls: if keyState == NSKeyUp: self.onMediaKeyUp(self._keyControls[keyCode]) return None # consume event return event # pass through
def _event_tap(self, proxy, type_, event, refcon): # evenTrap disabled by timeout or user input, reenable if type_ == Quartz.kCGEventTapDisabledByUserInput or \ type_ == Quartz.kCGEventTapDisabledByTimeout: Quartz.CGEventTapEnable(self._tap, True) return event # Convert the Quartz CGEvent into something more useful keyEvent = NSEvent.eventWithCGEvent_(event) if keyEvent.subtype() is 8: # subtype 8 is media keys data = keyEvent.data1() keyCode = (data & 0xFFFF0000) >> 16 keyState = (data & 0xFF00) >> 8 if keyCode in self._EVENTS: if keyState == NSKeyUp: self._push_callback(self._EVENTS[keyCode]) return None # swallow the event, so iTunes doesn't launch return event
def keyboard_tap_callback(proxy, type_, event, refcon): try: key_event = NSEvent.eventWithCGEvent_(event) except: LOG.info("mac event cast error") return event if key_event.subtype() == 8: key_code = (key_event.data1() & 0xFFFF0000) >> 16 key_state = (key_event.data1() & 0xFF00) >> 8 if key_code is 16 or key_code is 19 or key_code is 20: # 16 for play-pause, 19 for next, 20 for previous if key_state == NSKeyUp: if key_code is 19: player.play_next() elif key_code is 20: player.play_last() elif key_code is 16: player.play_or_pause() return None return event
def keyboardTapCallback(proxy, type_, event, refcon): if type_ == Quartz.kCGEventTapDisabledByTimeout & 0xffffffff: # event tap timed out, re-enable. Quartz.CGEventTapEnable(self.tap, True) NSLog('event tap timed out, re-enabling') return None # Convert the Quartz CGEvent into something more useful keyEvent = NSEvent.eventWithCGEvent_(event) try: selector = objc.selector(self.runner.call_, signature='v@:@') self.runner.performSelectorOnMainThread_withObject_waitUntilDone_( selector, (callback, keyEvent), False) if should_block(keyEvent): return None except Exception, e: tb = sys.exc_info() print ''.join(traceback.format_exception(*tb)) print 'Exception: ' + e.message
def modifierTapCallback(proxy, type_, event, refcon): global break_counter, cmd_bool # Get special keyboard event (modifiers) modifierEvent = NSEvent.eventWithCGEvent_(event) if modifierEvent is None: pass else: flag = modifierEvent.modifierFlags() # On press the flag is different from zero if flag != 0: # Stop the acquisition when ctrl is pressed 'break_th' times if flag == 262145: #ctrl break_counter = break_counter + 1 if break_counter >= break_th: raise Exception('BRUT FORCE STOP') else: break_counter = 0 if flag == 1048584: #cmd cmd_bool = True else: # On release, the flag is equal to zero cmd_bool = False
def keyboard_tap_callback(proxy, type_, event, refcon): if type_ < 0 or type_ > 0x7fffffff: LOG.error('Unkown mac event') Quartz.CFRunLoopRun() return run_event_loop(ControllerApi.player) try: key_event = NSEvent.eventWithCGEvent_(event) except: LOG.info("mac event cast error") return event if key_event.subtype() == 8: key_code = (key_event.data1() & 0xFFFF0000) >> 16 key_state = (key_event.data1() & 0xFF00) >> 8 if key_code is 16 or key_code is 19 or key_code is 20: # 16 for play-pause, 19 for next, 20 for previous if key_state == NSKeyUp: if key_code is 19: player.play_next() elif key_code is 20: player.play_last() elif key_code is 16: player.play_or_pause() return None return event
def _nativeEventCallback(self,*args): try: proxy, etype, event, refcon = args if self.isReportingEvents(): logged_time=getTime() if etype == Qz.kCGEventTapDisabledByTimeout: print2err("** WARNING: Keyboard Tap Disabled due to timeout. Re-enabling....: ", etype) Qz.CGEventTapEnable(self._tap, True) return event confidence_interval=logged_time-self._last_poll_time delay=0.0 # No point trying to guess for the keyboard or mouse. # May add a 'default_delay' prefernce to the device config settings, # so if a person knows the average delay for something like the kb or mouse # they are using, then they could specify it in the config file and it could be used here. iohub_time = logged_time-delay device_time=Qz.CGEventGetTimestamp(event)*self.DEVICE_TIME_TO_SECONDS key_code = Qz.CGEventGetIntegerValueField(event, Qz.kCGKeyboardEventKeycode) key_name=None window_number=0 ioe_type=None ucode=0 # the int version of the unicode utf-8 ichar is_auto_repeat= Qz.CGEventGetIntegerValueField(event, Qz.kCGKeyboardEventAutorepeat) #np_key=keyFromNumpad(flags) # This is a modifier state change event, so we need to manually determine # which mod key was either pressed or released that resulted in the state change.... if etype == Qz.kCGEventFlagsChanged: try: ioe_type, key_name=self._handleModifierChangeEvent(event) # print2err('_handleModifierChangeEvent: ',ioe_type, ' ',key_name) except Exception, e: print2err("kCGEventFlagsChanged failed: ",e) printExceptionDetailsToStdErr() else: # This is an actual button press / release event, so handle it.... try: keyEvent = NSEvent.eventWithCGEvent_(event) key_name,ucode,key_code=self._getKeyNameForEvent(keyEvent) window_number=keyEvent.windowNumber() if etype == Qz.kCGEventKeyUp: ioe_type=EventConstants.KEYBOARD_RELEASE elif etype == Qz.kCGEventKeyDown: ioe_type=EventConstants.KEYBOARD_PRESS except Exception,e: print2err("Create NSEvent failed: ",e) printExceptionDetailsToStdErr() if ioe_type: # The above logic resulted in finding a key press or release event # from the expected events OR from modifier state changes. So, # send the iohub event version to ioHub. # # FILL IN AND CREATE EVENT # index 0 and 1 are session and exp. ID's # index 3 is device id (not yet supported) #key_name='£' if ioe_type == EventConstants.KEYBOARD_PRESS: if is_auto_repeat > 0 and self._report_auto_repeats is False: return event if key_name is None or len(key_name)==0: # TO DO: dead char we need to deal with?? key_name=u'DEAD_KEY?' print2err("DEAD KEY HIT?") else: ioe=self._EVENT_TEMPLATE_LIST ioe[3]=Computer._getNextEventID() ioe[4]=ioe_type #event type code ioe[5]=device_time ioe[6]=logged_time ioe[7]=iohub_time ioe[8]=confidence_interval ioe[9]=delay # index 10 is filter id, not used at this time ioe[11]=is_auto_repeat ioe[12]=key_code # Quartz does not give the scancode, so fill this with keycode ioe[13]=key_code #key_code ioe[14]=ucode ioe[15]=key_name.encode('utf-8') ioe[16]=self._mods_sum ioe[17]=window_number self._addNativeEventToBuffer(copy(ioe)) #print2err("**Final values:key_name [",key_name,"] ucode: ",ucode, ' key_code: ',key_code) else: print2err("\nWARNING: KEYBOARD RECEIVED A [ {0} ] KB EVENT, BUT COULD NOT GENERATE AN IOHUB EVENT FROM IT !!".format(etype)," [",key_name,"] ucode: ",ucode, ' key_code: ',key_code) self._last_callback_time=logged_time
def _nativeEventCallback(self,*args): try: proxy, etype, event, refcon = args if self.isReportingEvents(): logged_time=currentSec() if etype == Qz.kCGEventTapDisabledByTimeout: print2err("** WARNING: Mouse Tap Disabled due to timeout. Re-enabling....: ", etype) Qz.CGEventTapEnable(self._tap, True) return event else: confidence_interval=0.0 delay=0.0 iohub_time = logged_time device_time=Qz.CGEventGetTimestamp(event)*self.DEVICE_TIME_TO_SECONDS ioe_type=EventConstants.UNDEFINED px,py = Qz.CGEventGetLocation(event) multi_click_count=Qz.CGEventGetIntegerValueField(event,Qz.kCGMouseEventClickState) mouse_event = NSEvent.eventWithCGEvent_(event) window_handle=mouse_event.windowNumber() # TO DO: Implement multimonitor location based on mouse location support. # Currently always uses monitor index 0 display_index=self.getDisplayIndexForMousePosition((px,py)) if display_index == -1: if self._last_display_index is not None: display_index=self._last_display_index else: #print2err("!!! _nativeEventCallback error: mouse event pos {0} not in any display bounds!!!".format(event.Position)) #print2err("!!! -> SKIPPING EVENT") #print2err("===============") return event # result=self._validateMousePosition((px,py),display_index) # if result != True: # #print2err("!!! _validateMousePosition made ajustment: {0} to {1}".format((px,py),result)) # nx,ny=result # display_index=self.getDisplayIndexForMousePosition((nx,ny)) # #print2err("Going to Update mousePosition: {0} => {1} on D {2}".format((px,py),(ny,ny),display_index)) # px,py=nx,ny # self._nativeSetMousePos(px,py) px,py=self._display_device._pixel2DisplayCoord(px,py,display_index) self._lastPosition=self._position self._position=px,py self._last_display_index=self._display_index self._display_index=display_index # TO DO: Supported reporting scroll x info for OSX. # This also suggests not having scoll up and down events and # just having the one scroll event type, regardless of direction / dimension scroll_dx=0 scroll_dy=0 button_state=0 if etype in pressID: button_state=MouseConstants.MOUSE_BUTTON_STATE_PRESSED if multi_click_count>1: ioe_type=EventConstants.MOUSE_MULTI_CLICK else: ioe_type=EventConstants.MOUSE_BUTTON_PRESS elif etype in releaseID: button_state=MouseConstants.MOUSE_BUTTON_STATE_RELEASED ioe_type=EventConstants.MOUSE_BUTTON_RELEASE elif etype in dragID: ioe_type=EventConstants.MOUSE_DRAG elif etype == Qz.kCGEventMouseMoved: ioe_type=EventConstants.MOUSE_MOVE elif etype == Qz.kCGEventScrollWheel: ioe_type=EventConstants.MOUSE_SCROLL scroll_dy= Qz.CGEventGetIntegerValueField(event,Qz.kCGScrollWheelEventPointDeltaAxis1) scroll_dx= Qz.CGEventGetIntegerValueField(event,Qz.kCGScrollWheelEventPointDeltaAxis2) self._scrollPositionX+= scroll_dx self._scrollPositionY+= scroll_dy iohub_button_id=self._IOHUB_BUTTON_ID_MAPPINGS.get(etype,0) if iohub_button_id in self.activeButtons: self.activeButtons[iohub_button_id]= int(button_state==MouseConstants.MOUSE_BUTTON_STATE_PRESSED) pressed_buttons=0 for k,v in self.activeButtons.iteritems(): pressed_buttons+=k*v # Create Event List # index 0 and 1 are session and exp. ID's # index 2 is (yet to be used) device_id ioe=self._EVENT_TEMPLATE_LIST ioe[3]=Computer._getNextEventID() ioe[4]=ioe_type #event type code ioe[5]=device_time ioe[6]=logged_time ioe[7]=iohub_time ioe[8]=confidence_interval ioe[9]=delay # index 10 is filter id, not used at this time ioe[11]=display_index ioe[12]=button_state ioe[13]=iohub_button_id ioe[14]=pressed_buttons ioe[15]=px ioe[16]=py ioe[17]=int(scroll_dx) ioe[18]=int(self._scrollPositionX) ioe[19]=int(scroll_dy) ioe[20]=int(self._scrollPositionY) ioe[21]=Keyboard._modifier_value ioe[22]=window_handle self._addNativeEventToBuffer(copy(ioe)) self._last_callback_time=logged_time except Exception: printExceptionDetailsToStdErr() Qz.CGEventTapEnable(self._tap, False) # Must return original event or no mouse events will get to OSX! return event
def _nativeEventCallback(self, *args): event = None try: proxy, etype, event, refcon = args if self.isReportingEvents(): logged_time = getTime() if etype == Qz.kCGEventTapDisabledByTimeout: print2err( '** WARNING: Keyboard Tap Disabled due to timeout. Re-enabling....: ', etype) Qz.CGEventTapEnable(self._tap, True) return event confidence_interval = logged_time - self._last_poll_time delay = 0.0 iohub_time = logged_time - delay char_value = None key_value = None ioe_type = None device_time = Qz.CGEventGetTimestamp( event) * self.DEVICE_TIME_TO_SECONDS key_code = Qz.CGEventGetIntegerValueField( event, Qz.kCGKeyboardEventKeycode) # Check Auto repeats if etype == Qz.kCGEventKeyDown and self._report_auto_repeats is False and self._key_states.get( key_code, None): return event nsEvent = NSEvent.eventWithCGEvent_(event) # should NSFunctionKeyMask, NSNumericPadKeyMask be used?? window_number = nsEvent.windowNumber() if etype in [ Qz.kCGEventKeyDown, Qz.kCGEventKeyUp, Qz.kCGEventFlagsChanged ]: key_mods = Qz.CGEventGetFlags(event) ioHubKeyboardDevice._modifier_value, mod_names = self._checkForLeftRightModifiers( key_mods) if fnModifierActive(key_mods) and keyFromNumpad(key_mods): # Atleast on mac mini wireless kb, arrow keys have # fnModifierActive at all times, even when fn key is not pressed. # When fn key 'is' pressed, and arrow key is pressed, # then keyFromNumpad becomes false. mod_names.remove('function') ioHubKeyboardDevice._modifier_value -= KeyboardConstants._modifierCodes.getID( 'function') if etype != Qz.kCGEventFlagsChanged: char_value = nsEvent.characters() if etype == Qz.kCGEventKeyUp: ioe_type = EventConstants.KEYBOARD_RELEASE elif etype == Qz.kCGEventKeyDown: ioe_type = EventConstants.KEYBOARD_PRESS else: if len(mod_names) > len(self._last_mod_names): ioe_type = EventConstants.KEYBOARD_PRESS else: ioe_type = EventConstants.KEYBOARD_RELEASE Keyboard._last_mod_names = mod_names if char_value is None or fnModifierActive(key_mods): char_value = self._createStringForKey( key_code, key_mods) if len(char_value) != 1 or unicodedata.category( char_value).lower() == 'cc': char_value = '' key_value = self._createStringForKey(key_code, 0) if len(key_value) == 0 or unicodedata.category( key_value).lower() == 'cc': key_value = code2label.get(key_code, '') if key_value == 'tab': char_value = '\t' elif key_value == 'return': char_value = '\n' is_auto_repeat = Qz.CGEventGetIntegerValueField( event, Qz.kCGKeyboardEventAutorepeat) # TODO: CHeck WINDOW BOUNDS # report_system_wide_events=self.getConfiguration().get('report_system_wide_events',True) # Can not seem to figure out how to get window handle id from evt to match with pyget in darwin, so # Comparing event target process ID to the psychopy windows process ID, # yglet_window_hnds=self._iohub_server._pyglet_window_hnds #print2err("pyglet_window_hnds: ",window_number, " , ",pyglet_window_hnds) #targ_proc = Qz.CGEventGetIntegerValueField(event,Qz.kCGEventTargetUnixProcessID) #psych_proc = Computer.psychopy_process.pid # if targ_proc == psych_proc: # pass # elif report_system_wide_events is False: # For keyboard, when report_system_wide_events is false # do not record kb events that are not targeted for # a PsychoPy window, still allow them to pass to the desktop # apps. # return event if ioe_type: ioe = self._EVENT_TEMPLATE_LIST ioe[3] = Device._getNextEventID() ioe[4] = ioe_type ioe[5] = device_time ioe[6] = logged_time ioe[7] = iohub_time ioe[8] = confidence_interval ioe[9] = delay # index 10 is filter id, not used at this time ioe[11] = is_auto_repeat # Quartz does not give the scancode, so fill this with # keycode ioe[12] = key_code ioe[13] = key_code # key_code ioe[14] = 0 # unicode number field no longer used. ioe[15] = key_value ioe[16] = ioHubKeyboardDevice._modifier_value ioe[17] = window_number ioe[18] = char_value.encode('utf-8') ioe = copy(ioe) ioHubKeyboardDevice._updateKeyboardEventState( self, ioe, ioe_type == EventConstants.KEYBOARD_PRESS) self._addNativeEventToBuffer(ioe) else: print2err( '\nWARNING: KEYBOARD RECEIVED A [ {0} ] KB EVENT, BUT COULD NOT GENERATE AN IOHUB EVENT FROM IT !!' .format(etype), ' [', key_value, '] ucode: ', char_value.encode('utf-8'), ' key_code: ', key_code) self._last_callback_time = logged_time return event except Exception: printExceptionDetailsToStdErr() Qz.CGEventTapEnable(self._tap, False) return event
def _nativeEventCallback(self, *args): try: proxy, etype, event, refcon = args if self.isReportingEvents(): logged_time = currentSec() if etype == Qz.kCGEventTapDisabledByTimeout: print2err( '** WARNING: Mouse Tap Disabled due to timeout. Re-enabling....: ', etype) Qz.CGEventTapEnable(self._tap, True) return event else: confidence_interval = 0.0 delay = 0.0 iohub_time = logged_time device_time = Qz.CGEventGetTimestamp( event) * self.DEVICE_TIME_TO_SECONDS ioe_type = EventConstants.UNDEFINED px, py = Qz.CGEventGetLocation(event) multi_click_count = Qz.CGEventGetIntegerValueField( event, Qz.kCGMouseEventClickState) mouse_event = NSEvent.eventWithCGEvent_(event) # TODO: window_handle seems to always be 0. window_handle = mouse_event.windowNumber() display_index = self.getDisplayIndexForMousePosition( (px, py)) if display_index == -1: if self._last_display_index is not None: display_index = self._last_display_index else: # Do not report event to iohub if it does not map to a display # ?? Can this ever actually happen ?? return event enable_multi_window = self.getConfiguration().get( 'enable_multi_window', False) if enable_multi_window is False: px, py = self._display_device._pixel2DisplayCoord( px, py, display_index) else: wid, wx, wy = self._desktopToWindowPos((px, py)) if wid: px, py = self._pix2windowUnits(wid, (wx, wy)) window_handle = wid else: window_handle = 0 self._lastPosition = self._position self._position = px, py self._last_display_index = self._display_index self._display_index = display_index # TO DO: Supported reporting scroll x info for OSX. # This also suggests not having scroll up and down events and # just having the one scroll event type, regardless of # direction / dimension scroll_dx = 0 scroll_dy = 0 button_state = 0 if etype in pressID: button_state = MouseConstants.MOUSE_BUTTON_STATE_PRESSED if multi_click_count > 1: ioe_type = EventConstants.MOUSE_MULTI_CLICK else: ioe_type = EventConstants.MOUSE_BUTTON_PRESS elif etype in releaseID: button_state = MouseConstants.MOUSE_BUTTON_STATE_RELEASED ioe_type = EventConstants.MOUSE_BUTTON_RELEASE elif etype in dragID: ioe_type = EventConstants.MOUSE_DRAG elif etype == Qz.kCGEventMouseMoved: ioe_type = EventConstants.MOUSE_MOVE elif etype == Qz.kCGEventScrollWheel: ioe_type = EventConstants.MOUSE_SCROLL scroll_dy = Qz.CGEventGetIntegerValueField( event, Qz.kCGScrollWheelEventPointDeltaAxis1) scroll_dx = Qz.CGEventGetIntegerValueField( event, Qz.kCGScrollWheelEventPointDeltaAxis2) self._scrollPositionX += scroll_dx self._scrollPositionY += scroll_dy iohub_button_id = self._IOHUB_BUTTON_ID_MAPPINGS.get( etype, 0) if iohub_button_id in self.activeButtons: abuttons = int(button_state == MouseConstants. MOUSE_BUTTON_STATE_PRESSED) self.activeButtons[iohub_button_id] = abuttons pressed_buttons = 0 for k, v in self.activeButtons.items(): pressed_buttons += k * v # Create Event List # index 0 and 1 are session and exp. ID's # index 2 is (yet to be used) device_id ioe = self._EVENT_TEMPLATE_LIST ioe[3] = Device._getNextEventID() ioe[4] = ioe_type # event type code ioe[5] = device_time ioe[6] = logged_time ioe[7] = iohub_time ioe[8] = confidence_interval ioe[9] = delay # index 10 is filter id, not used at this time ioe[11] = display_index ioe[12] = button_state ioe[13] = iohub_button_id ioe[14] = pressed_buttons ioe[15] = px ioe[16] = py ioe[17] = int(scroll_dx) ioe[18] = int(self._scrollPositionX) ioe[19] = int(scroll_dy) ioe[20] = int(self._scrollPositionY) ioe[21] = Keyboard._modifier_value ioe[22] = window_handle self._addNativeEventToBuffer(copy(ioe)) self._last_callback_time = logged_time except Exception: printExceptionDetailsToStdErr() Qz.CGEventTapEnable(self._tap, False) # Must return original event or no mouse events will get to OSX! return event
def _nativeEventCallback(self,*args): event = None try: proxy, etype, event, refcon = args if self.isReportingEvents(): logged_time=getTime() if etype == Qz.kCGEventTapDisabledByTimeout: print2err("** WARNING: Keyboard Tap Disabled due to timeout. Re-enabling....: ", etype) Qz.CGEventTapEnable(self._tap, True) return event confidence_interval=logged_time-self._last_poll_time delay=0.0 iohub_time = logged_time-delay char_value = None key_value = None ioe_type = None device_time=Qz.CGEventGetTimestamp(event)*self.DEVICE_TIME_TO_SECONDS key_code = Qz.CGEventGetIntegerValueField(event, Qz.kCGKeyboardEventKeycode) # Check Auto repeats if etype == Qz.kCGEventKeyDown and self._report_auto_repeats is False and self._key_states.get(key_code, None): return event nsEvent = NSEvent.eventWithCGEvent_(event) # should NSFunctionKeyMask, NSNumericPadKeyMask be used?? window_number=nsEvent.windowNumber() if etype in [Qz.kCGEventKeyDown, Qz.kCGEventKeyUp, Qz.kCGEventFlagsChanged]: key_mods = Qz.CGEventGetFlags(event) ioHubKeyboardDevice._modifier_value, mod_names = self._checkForLeftRightModifiers(key_mods) if fnModifierActive(key_mods) and keyFromNumpad(key_mods): # Atleast on mac mini wireless kb, arrow keys have # fnModifierActive at all times, even when fn key is not pressed. # When fn key 'is' pressed, and arrow key is pressed, then keyFromNumpad becomes false. mod_names.remove('function') ioHubKeyboardDevice._modifier_value-=KeyboardConstants._modifierCodes.getID('function') if etype != Qz.kCGEventFlagsChanged: char_value = nsEvent.characters() if etype == Qz.kCGEventKeyUp: ioe_type=EventConstants.KEYBOARD_RELEASE elif etype == Qz.kCGEventKeyDown: ioe_type=EventConstants.KEYBOARD_PRESS else: if len(mod_names) > len(self._last_mod_names): ioe_type=EventConstants.KEYBOARD_PRESS else: ioe_type=EventConstants.KEYBOARD_RELEASE Keyboard._last_mod_names = mod_names if char_value is None or fnModifierActive(key_mods): char_value = self._createStringForKey(key_code,key_mods) if len(char_value) != 1 or unicodedata.category(char_value).lower() == 'cc': char_value = '' key_value=self._createStringForKey(key_code,0) if len(key_value)==0 or unicodedata.category(key_value).lower() == 'cc': key_value=code2label.get(key_code, '') if key_value == 'tab': char_value = '\t' elif key_value == 'return': char_value = '\n' is_auto_repeat= Qz.CGEventGetIntegerValueField(event, Qz.kCGKeyboardEventAutorepeat) # TODO: CHeck WINDOW BOUNDS #report_system_wide_events=self.getConfiguration().get('report_system_wide_events',True) # Can not seem to figure out how to get window handle id from evt to match with pyget in darwin, so # Comparing event target process ID to the psychopy windows process ID, #yglet_window_hnds=self._iohub_server._pyglet_window_hnds #print2err("pyglet_window_hnds: ",window_number, " , ",pyglet_window_hnds) #targ_proc = Qz.CGEventGetIntegerValueField(event,Qz.kCGEventTargetUnixProcessID) #psych_proc = Computer.psychopy_process.pid #if targ_proc == psych_proc: # pass #elif report_system_wide_events is False: # For keyboard, when report_system_wide_events is false # do not record kb events that are not targeted for # a PsychoPy window, still allow them to pass to the desktop # apps. # return event if ioe_type: ioe=self._EVENT_TEMPLATE_LIST ioe[3]=Computer._getNextEventID() ioe[4]=ioe_type ioe[5]=device_time ioe[6]=logged_time ioe[7]=iohub_time ioe[8]=confidence_interval ioe[9]=delay # index 10 is filter id, not used at this time ioe[11]=is_auto_repeat ioe[12]=key_code # Quartz does not give the scancode, so fill this with keycode ioe[13]=key_code #key_code ioe[14] = 0 #unicode number field no longer used. ioe[15]=key_value ioe[16]=ioHubKeyboardDevice._modifier_value ioe[17]=window_number ioe[18]=char_value.encode('utf-8') ioe = copy(ioe) ioHubKeyboardDevice._updateKeyboardEventState(self, ioe, ioe_type == EventConstants.KEYBOARD_PRESS) self._addNativeEventToBuffer(ioe) else: print2err("\nWARNING: KEYBOARD RECEIVED A [ {0} ] KB EVENT, BUT COULD NOT GENERATE AN IOHUB EVENT FROM IT !!".format(etype)," [",key_name,"] ucode: ",ucode, ' key_code: ',key_code) self._last_callback_time=logged_time return event except Exception: printExceptionDetailsToStdErr() Qz.CGEventTapEnable(self._tap, False) return event
def _tap_callback_inner(self, proxy, type_, event, refcon): """ Event tap callback :paramref:`_tap_callback`'s inner function. :param proxy: Event tap proxy. :param type_: Event type. :param event: CGEvent object. :param refcon: User-defined data. :return: Given event object to propagate the event, or None to \ discard the event. """ # Convert given CGEvent into NSEvent ns_event = NSEvent.eventWithCGEvent_(event) # Get event type event_type = ns_event.type() # Whether propagate the event propagate = True # If is modifier key event if event_type == Quartz.kCGEventFlagsChanged: # Handle the event propagate = self._handle_modifier_key_event( event=event, ns_event=ns_event, propagate=propagate, ) # If is key event elif (event_type == Quartz.kCGEventKeyDown or event_type == Quartz.kCGEventKeyUp): # Handle the event propagate = self._handle_key_event( event=event, ns_event=ns_event, propagate=propagate, ) # If is mouse button event elif event_type in self._MOUSE_BUTTON_EVENTS: # Handle the event propagate = self._handle_mouse_button_event( event=event, ns_event=ns_event, propagate=propagate, ) # If is mouse move or wheel event elif event_type in self._MOUSE_MOVE_WHEEL_EVENTS: # Handle the event propagate = self._handle_mouse_move_wheel_event( event=event, ns_event=ns_event, propagate=propagate, ) # If is none of above else: # Ignore pass # If need propagate the event if propagate: # Return the event object return event # If not need propagate the event else: # Return None return None
def _nativeEventCallback(self, *args): try: proxy, etype, event, refcon = args if self.isReportingEvents(): logged_time = getTime() if etype == Qz.kCGEventTapDisabledByTimeout: print2err( "** WARNING: Keyboard Tap Disabled due to timeout. Re-enabling....: ", etype) Qz.CGEventTapEnable(self._tap, True) return event confidence_interval = logged_time - self._last_poll_time delay = 0.0 # No point trying to guess for the keyboard or mouse. # May add a 'default_delay' prefernce to the device config settings, # so if a person knows the average delay for something like the kb or mouse # they are using, then they could specify it in the config file and it could be used here. iohub_time = logged_time - delay device_time = Qz.CGEventGetTimestamp( event) * self.DEVICE_TIME_TO_SECONDS key_code = Qz.CGEventGetIntegerValueField( event, Qz.kCGKeyboardEventKeycode) key_name = None window_number = 0 ioe_type = None ucode = 0 # the int version of the unicode utf-8 ichar is_auto_repeat = Qz.CGEventGetIntegerValueField( event, Qz.kCGKeyboardEventAutorepeat) #np_key=keyFromNumpad(flags) # This is a modifier state change event, so we need to manually determine # which mod key was either pressed or released that resulted in the state change.... if etype == Qz.kCGEventFlagsChanged: try: ioe_type, key_name = self._handleModifierChangeEvent( event) # print2err('_handleModifierChangeEvent: ',ioe_type, ' ',key_name) except Exception, e: print2err("kCGEventFlagsChanged failed: ", e) printExceptionDetailsToStdErr() else: # This is an actual button press / release event, so handle it.... try: keyEvent = NSEvent.eventWithCGEvent_(event) key_name, ucode, key_code = self._getKeyNameForEvent( keyEvent) window_number = keyEvent.windowNumber() if etype == Qz.kCGEventKeyUp: ioe_type = EventConstants.KEYBOARD_RELEASE elif etype == Qz.kCGEventKeyDown: ioe_type = EventConstants.KEYBOARD_PRESS except Exception, e: print2err("Create NSEvent failed: ", e) printExceptionDetailsToStdErr() if ioe_type: # The above logic resulted in finding a key press or release event # from the expected events OR from modifier state changes. So, # send the iohub event version to ioHub. # # FILL IN AND CREATE EVENT # index 0 and 1 are session and exp. ID's # index 3 is device id (not yet supported) #key_name='£' if ioe_type == EventConstants.KEYBOARD_PRESS: if is_auto_repeat > 0 and self._report_auto_repeats is False: return event if key_name is None or len(key_name) == 0: # TO DO: dead char we need to deal with?? key_name = u'DEAD_KEY?' print2err("DEAD KEY HIT?") else: ioe = self._EVENT_TEMPLATE_LIST ioe[3] = Computer._getNextEventID() ioe[4] = ioe_type #event type code ioe[5] = device_time ioe[6] = logged_time ioe[7] = iohub_time ioe[8] = confidence_interval ioe[9] = delay # index 10 is filter id, not used at this time ioe[11] = is_auto_repeat ioe[12] = key_code # Quartz does not give the scancode, so fill this with keycode ioe[13] = key_code #key_code ioe[14] = ucode ioe[15] = key_name.encode('utf-8') ioe[16] = self._mods_sum ioe[17] = window_number self._addNativeEventToBuffer(copy(ioe)) #print2err("**Final values:key_name [",key_name,"] ucode: ",ucode, ' key_code: ',key_code) else: print2err( "\nWARNING: KEYBOARD RECEIVED A [ {0} ] KB EVENT, BUT COULD NOT GENERATE AN IOHUB EVENT FROM IT !!" .format(etype), " [", key_name, "] ucode: ", ucode, ' key_code: ', key_code) self._last_callback_time = logged_time