Example #1
0
 def process_key_event(self, send_key_action_cb, wid, key_event):
     """ Caps_Lock and Num_Lock don't work properly: they get reported more than once,
         they are reported as not pressed when the key is down, etc
         So we just ignore those and rely on the list of "modifiers" passed
         with each keypress to let the server set them for us when needed.
     """
     if key_event.keyval == 2**24 - 1 and key_event.keyname == "VoidSymbol":
         log("process_key_event: ignoring %s", key_event)
         return
     #self.modifier_mappings = None       #{'control': [(37, 'Control_L'), (105, 'Control_R')], 'mod1':
     #self.modifier_keys = {}             #{"Control_L" : "control", ...}
     #self.modifier_keycodes = {}         #{"Control_R" : [105], ...}
     #self.modifier_keycodes = {"ISO_Level3_Shift": [108]}
     #we can only deal with 'Alt_R' and simulate AltGr (ISO_Level3_Shift)
     #if we have modifier_mappings
     if EMULATE_ALTGR and self.altgr_modifier and len(
             self.modifier_mappings) > 0:
         rmenu = GetKeyState(win32con.VK_RMENU)
         if key_event.keyname == "Control_L":
             log(
                 "process_key_event: %s pressed=%s, with GetKeyState(VK_RMENU)=%s",
                 key_event.keyname, key_event.pressed, rmenu)
             #AltGr is often preceded by a spurious "Control_L" event
             #delay this one a little bit so we can skip it if an "AltGr" does come through next:
             if key_event.pressed:
                 if rmenu in (0, 1):
                     self.delayed_event = (send_key_action_cb, wid,
                                           key_event)
                     #needed for altgr emulation timeouts:
                     from xpra.gtk_common.gobject_compat import import_glib
                     glib = import_glib()
                     glib.timeout_add(EMULATE_ALTGR_CONTROL_KEY_DELAY,
                                      self.send_delayed_key)
                 return
             if not key_event.pressed and rmenu not in (0, 1):
                 #unpressed: could just skip it?
                 #(but maybe the real one got pressed.. and this would get it stuck)
                 pass
         if key_event.keyname == "Alt_R":
             log(
                 "process_key_event: Alt_R pressed=%s, with GetKeyState(VK_RMENU)=%s",
                 key_event.pressed, rmenu)
             if rmenu in (0, 1) and key_event.pressed:
                 #cancel "Control_L" if one was due:
                 self.delayed_event = None
             #modify the key event so that it will only trigger the modifier update,
             #and not not the key event itself:
             key_event.string = ""
             key_event.keyname = ""
             key_event.group = -1
             key_event.keyval = -1
             key_event.keycode = -1
             self.AltGr_modifiers(key_event.modifiers)
     self.send_delayed_key()
     KeyboardBase.process_key_event(self, send_key_action_cb, wid,
                                    key_event)
Example #2
0
 def send_delayed_key(self):
     #timeout: this must be a real one, send it now
     dk = self.delayed_event
     log("send_delayed_key() delayed_event=%s", dk)
     if dk:
         self.delayed_event = None
         rmenu = GetKeyState(win32con.VK_RMENU)
         log("send_delayed_key() GetKeyState(VK_RMENU)=%s", rmenu)
         if rmenu not in (0, 1):
             KeyboardBase.process_key_event(self, *dk)
Example #3
0
 def mask_to_names(self, mask):
     """ Patch NUMLOCK and AltGr """
     names = KeyboardBase.mask_to_names(self, mask)
     if EMULATE_ALTGR:
         rmenu = GetKeyState(win32con.VK_RMENU)
         #log("GetKeyState(VK_RMENU)=%s", rmenu)
         if rmenu not in (0, 1):
             self.AltGr_modifiers(names)
     if self.num_lock_modifier:
         try:
             numlock = GetKeyState(win32con.VK_NUMLOCK)
             if numlock and self.num_lock_modifier not in names:
                 names.append(self.num_lock_modifier)
             elif not numlock and self.num_lock_modifier in names:
                 names.remove(self.num_lock_modifier)
             log("mask_to_names(%s) GetKeyState(VK_NUMLOCK)=%s, names=%s", mask, numlock, names)
         except:
             pass
     else:
         log("mask_to_names(%s)=%s", mask, names)
     return names
Example #4
0
 def low_level_keyboard_handler(nCode, wParam, lParam):
     log("WH_KEYBOARD_LL: %s", (nCode, wParam, lParam))
     try:
         scan_code = lParam.contents.scan_code
         vk_code = lParam.contents.vk_code
         focused = self.client._focused
         #the keys we intercept before the OS:
         keyname = {
             win32con.VK_LWIN: "Super_L",
             win32con.VK_RWIN: "Super_R",
             win32con.VK_TAB: "Tab",
         }.get(vk_code)
         modifiers = []
         kh = self.client.keyboard_helper
         key_event_type = ALL_KEY_EVENTS.get(wParam)
         #log("low_level_keyboard_handler(%s, %s, %s) vk_code=%i, scan_code=%i, keyname=%s, key_event_type=%s, focused=%s, keyboard_grabbed=%s", nCode, wParam, lParam, vk_code, scan_code, keyname, key_event_type, focused, self.client.keyboard_grabbed)
         if self.client.keyboard_grabbed and focused and keyname and kh and kh.keyboard and key_event_type:
             modifier_keycodes = kh.keyboard.modifier_keycodes
             modifier_keys = kh.keyboard.modifier_keys
             if keyname.startswith("Super"):
                 keycode = 0
                 #find the modifier keycode: (try the exact key we hit first)
                 for x in (keyname, "Super_L", "Super_R"):
                     keycodes = modifier_keycodes.get(x, [])
                     for k in keycodes:
                         #only interested in numeric keycodes:
                         try:
                             keycode = int(k)
                             break
                         except ValueError:
                             pass
                     if keycode > 0:
                         break
             else:
                 keycode = vk_code  #true for non-modifier keys only!
             for vk, modkeynames in {
                     win32con.VK_NUMLOCK: ["Num_Lock"],
                     win32con.VK_CAPITAL: ["Caps_Lock"],
                     win32con.VK_CONTROL: ["Control_L", "Control_R"],
                     win32con.VK_SHIFT: ["Shift_L", "Shift_R"],
             }.items():
                 if GetKeyState(vk):
                     for modkeyname in modkeynames:
                         mod = modifier_keys.get(modkeyname)
                         if mod:
                             modifiers.append(mod)
                             break
             #keylog.info("keyboard helper=%s, modifier keycodes=%s", kh, modifier_keycodes)
             grablog(
                 "vk_code=%s, scan_code=%s, event=%s, keyname=%s, keycode=%s, modifiers=%s, focused=%s",
                 vk_code, scan_code, ALL_KEY_EVENTS.get(wParam),
                 keyname, keycode, modifiers, focused)
             if keycode > 0:
                 key_event = KeyEvent()
                 key_event.keyname = keyname
                 key_event.pressed = wParam in DOWN
                 key_event.modifiers = modifiers
                 key_event.keyval = scan_code
                 key_event.keycode = keycode
                 key_event.string = ""
                 key_event.group = 0
                 grablog("detected '%s' key, sending %s", keyname,
                         key_event)
                 self.client.keyboard_helper.send_key_action(
                     focused, key_event)
                 #swallow this event:
                 return 1
     except Exception as e:
         keylog.error("Error: low level keyboard hook failed")
         keylog.error(" %s", e)
     return CallNextHookEx(0, nCode, wParam, lParam)