def _getIOHubEventObject(self,native_event_data): try: if len(native_event_data) >2: # it is a KeyboardCharEvent return native_event_data # stime=getTime() notifiedTime, event=native_event_data etype = event.Type # # Start Tracking Modifiers that are pressed # keyID=event.KeyID modKeyName=Keyboard._win32_modifier_mapping.get(keyID,None) if modKeyName: if keyID == win32_vk.VK_CAPITAL and etype==EventConstants.KEYBOARD_PRESS: if self._keyboard_state[keyID] > 0: self._keyboard_state[keyID]=0 self._modifier_value-=KeyboardConstants._modifierCodes.getID(modKeyName) else: self._keyboard_state[keyID] = 0x01 self._modifier_value+=KeyboardConstants._modifierCodes.getID(modKeyName) elif etype==EventConstants.KEYBOARD_PRESS and self._keyboard_state[keyID]==0: self._keyboard_state[keyID] = 0x80 self._modifier_value+=KeyboardConstants._modifierCodes.getID(modKeyName) #print2err("SETTING MOD KEY ELEMENT: ",keyID,' state: ',pyHook.GetKeyState(keyID)) if keyID in [win32_vk.VK_LSHIFT,win32_vk.VK_RSHIFT] and self._keyboard_state[win32_vk.VK_SHIFT]==0: self._keyboard_state[win32_vk.VK_SHIFT] = 0x80 #print2err("SETTING shift ",keyID) elif keyID in [win32_vk.VK_LCONTROL,win32_vk.VK_RCONTROL] and self._keyboard_state[win32_vk.VK_CONTROL] ==0: self._keyboard_state[win32_vk.VK_CONTROL] = 0x80 #print2err("SETTING CTRL: ",keyID) elif keyID in [win32_vk.VK_LMENU,win32_vk.VK_RMENU] and self._keyboard_state[win32_vk.VK_MENU]==0: self._keyboard_state[win32_vk.VK_MENU] = 0x80 #print2err("SETTING VK_MENU: ",keyID) elif etype==EventConstants.KEYBOARD_RELEASE and keyID != win32_vk.VK_CAPITAL: if self._keyboard_state[keyID]!=0 and keyID != win32_vk.VK_CAPITAL: self._modifier_value-=KeyboardConstants._modifierCodes.getID(modKeyName) self._keyboard_state[keyID] = 0 #print2err("clearing MOD KEY ELEMENT: ",keyID,' state: ',pyHook.GetKeyState(keyID)) if modKeyName.find('SHIFT')>=0 and self._keyboard_state[win32_vk.VK_LSHIFT]==0 and self._keyboard_state[win32_vk.VK_RSHIFT]==0: self._keyboard_state[win32_vk.VK_SHIFT] = 0 # print2err("CLEAR VK_SHIFT: ",keyID) elif modKeyName.find('CONTROL')>=0 and self._keyboard_state[win32_vk.VK_LCONTROL]==0 and self._keyboard_state[win32_vk.VK_RCONTROL]==0: self._keyboard_state[win32_vk.VK_CONTROL] = 0 #print2err("CLEAR VK_CONTROL: ",keyID) elif modKeyName.find('ALT')>=0 and self._keyboard_state[win32_vk.VK_LMENU]==0 and self._keyboard_state[win32_vk.VK_RMENU]==0: self._keyboard_state[win32_vk.VK_MENU] = 0 #print2err("CLEAR VK_MENU: ",keyID) # # End Tracking Modifiers that are pressed # event.Modifiers=self._modifier_value # From MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644939(v=vs.85).aspx # The time is a long integer that specifies the elapsed time, in milliseconds, from the time the system was started to the time the message was # created (that is, placed in the thread's message queue).REMARKS: The return value from the GetMessageTime function does not necessarily increase # between subsequent messages, because the value wraps to zero if the timer count exceeds the maximum value for a long integer. To calculate time # delays between messages, verify that the time of the second message is greater than the time of the first message; then, subtract the time of the # first message from the time of the second message. device_time = event.Time/1000.0 # convert to sec time = notifiedTime #TODO correct kb times to factor in delay if possible. confidence_interval=0.0 # since this is a keyboard device using a callback method, confidence_interval is not applicable delay=0.0 # since this is a keyboard, we 'know' there is a delay, but until we support setting a delay in the device properties based on external testing for a given keyboard, we will leave at 0. # ## check for unicode char # # uchar holds the unicode ord() number for the unicode char. unichr(uchar) == u'x' unicode str uchar=0 # key holds the unicode char, in 8 bit string format encoded in UTF-8. # Safe to transmit and to store in pytables. Use key.decode('utf-8') to get the unicode sybol decoded into a unicode string. key=None # ucat holds the unicode character category. This can be used to tell what king of code point it is. # For a list of categories see http://www.unicode.org/reports/tr44/#General_Category_Values # examples: # u'v' -> category: Ll # u'<-' (ESCAPE) -> category: Cc # u' ' -> category: Zs ucat=None result=self._user32.ToUnicode(event.KeyID, event.ScanCode,ctypes.byref(self._keyboard_state),ctypes.byref(self._unichar),8,0) if result > 0: if result == 1: # print2err("self._unichar[0]: ",self._unichar[0], " ", type(self._unichar[0])) # print2err(u"á: ",u"á", " upper: ",u"á".upper()) # print2err(u"': ",u"'", " upper: ",u"'".upper()) key=self._unichar[0].encode('utf-8') uchar=ord(self._unichar[0]) ucat=ucategory(self._unichar[0]) else: key=u'' for c in range(result): uchar=ord(self._unichar[c]) ucat=ucategory(self._unichar[c]) key+=uchar key=key.encode('utf-8') elif result == -1: # The specified virtual key is a dead-key character (accent or diacritic). # This value is returned regardless of the keyboard layout, even if several # characters have been typed and are stored in the keyboard state. If possible, # even with Unicode keyboard layouts, the function has written a spacing version # of the dead-key character to the buffer specified by pwszBuff. For example, # the function writes the character SPACING ACUTE (0x00B4), # rather than the character NON_SPACING ACUTE (0x0301). key=self._unichar[0].encode('utf-8') uchar=ord(self._unichar[0]) ucat=ucategory(self._unichar[0]) if result==0 or ucat and ucat[0]=='C': # ## TODO , TO FIX: We should only bother looking in the hardcoded character label lookup tables if the key did not result in ## a unicode char being returned, or if the unicode char is in a Control char category, etc. ## However it seems that the ToUnice fucntion is not factoring in whether shift is pressed or not, so it always returns a lower case letter. ## So for now, look up all keys and if a result is found, replace the 'key' field with it; but leave the ucode field as is. ## I 'think' we should be getting upper case unicode chars if shift is pressed, so this needs to be looked into. # # also look in built in key mappings; if a key label is returned, use it instead of the unicode char (it could be a non visible key) lookupkey,_=KeyboardConstants._getKeyNameAndModsForEvent(event) if lookupkey and len(lookupkey)>0: key=lookupkey #import ctypes #_dll=ctypes.windll.user32 #kstatus=ctypes.c_short(_dll.GetAsyncKeyState(ctypes.c_int(k.key_id))) #print k.key, ' status is %x pressed=%d was_pressed=%d'%(kstatus.value,(kstatus.value&0x80)>0,(kstatus.value&0x01)>0) return [0, 0, 0, #device id (not currently used) Computer._getNextEventID(), etype, device_time, notifiedTime, time, confidence_interval, delay, 0, event.RepeatCount, event.ScanCode, event.KeyID, uchar, key, event.Modifiers, event.Window ] except: printExceptionDetailsToStdErr()
def _convertFields(cls,event_value_list): modifier_value_index=cls.CLASS_ATTRIBUTE_NAMES.index('modifiers') event_value_list[modifier_value_index]=KeyboardConstants._modifierCodes2Labels(event_value_list[modifier_value_index]) key_value_index=cls.CLASS_ATTRIBUTE_NAMES.index('key') event_value_list[key_value_index]=event_value_list[key_value_index].decode('utf-8')