mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-06-15 14:52:15 +03:00
hotkey: win32 flake8 linting
This commit is contained in:
parent
7dbf150846
commit
42cd2c501e
192
hotkey.py
192
hotkey.py
@ -122,6 +122,7 @@ if platform == 'darwin': # noqa: C901
|
|||||||
# replace empty characters with charactersIgnoringModifiers to avoid crash
|
# replace empty characters with charactersIgnoringModifiers to avoid crash
|
||||||
elif the_event.type() in (NSKeyDown, NSKeyUp) and not the_event.characters():
|
elif the_event.type() in (NSKeyDown, NSKeyUp) and not the_event.characters():
|
||||||
the_event = NSEvent.keyEventWithType_location_modifierFlags_timestamp_windowNumber_context_characters_charactersIgnoringModifiers_isARepeat_keyCode_( # noqa: E501
|
the_event = NSEvent.keyEventWithType_location_modifierFlags_timestamp_windowNumber_context_characters_charactersIgnoringModifiers_isARepeat_keyCode_( # noqa: E501
|
||||||
|
# noqa: E501
|
||||||
the_event.type(),
|
the_event.type(),
|
||||||
the_event.locationInWindow(),
|
the_event.locationInWindow(),
|
||||||
the_event.modifierFlags(),
|
the_event.modifierFlags(),
|
||||||
@ -254,7 +255,7 @@ if platform == 'darwin': # noqa: C901
|
|||||||
text += HotkeyMgr.DISPLAY[keycode]
|
text += HotkeyMgr.DISPLAY[keycode]
|
||||||
|
|
||||||
elif keycode < 0x20: # control keys
|
elif keycode < 0x20: # control keys
|
||||||
text += chr(keycode+0x40)
|
text += chr(keycode + 0x40)
|
||||||
|
|
||||||
elif keycode < 0xf700: # key char
|
elif keycode < 0xf700: # key char
|
||||||
text += chr(keycode).upper()
|
text += chr(keycode).upper()
|
||||||
@ -308,7 +309,7 @@ elif platform == 'win32':
|
|||||||
VK_CONTROL = 0x11
|
VK_CONTROL = 0x11
|
||||||
VK_MENU = 0x12
|
VK_MENU = 0x12
|
||||||
VK_CAPITAL = 0x14
|
VK_CAPITAL = 0x14
|
||||||
VK_MODECHANGE= 0x1f
|
VK_MODECHANGE = 0x1f
|
||||||
VK_ESCAPE = 0x1b
|
VK_ESCAPE = 0x1b
|
||||||
VK_SPACE = 0x20
|
VK_SPACE = 0x20
|
||||||
VK_DELETE = 0x2e
|
VK_DELETE = 0x2e
|
||||||
@ -321,38 +322,77 @@ elif platform == 'win32':
|
|||||||
VK_OEM_MINUS = 0xbd
|
VK_OEM_MINUS = 0xbd
|
||||||
VK_NUMLOCK = 0x90
|
VK_NUMLOCK = 0x90
|
||||||
VK_SCROLL = 0x91
|
VK_SCROLL = 0x91
|
||||||
VK_PROCESSKEY= 0xe5
|
VK_PROCESSKEY = 0xe5
|
||||||
VK_OEM_CLEAR = 0xfe
|
VK_OEM_CLEAR = 0xfe
|
||||||
|
|
||||||
|
|
||||||
GetForegroundWindow = ctypes.windll.user32.GetForegroundWindow
|
GetForegroundWindow = ctypes.windll.user32.GetForegroundWindow
|
||||||
GetWindowText = ctypes.windll.user32.GetWindowTextW
|
GetWindowText = ctypes.windll.user32.GetWindowTextW
|
||||||
GetWindowText.argtypes = [HWND, LPWSTR, ctypes.c_int]
|
GetWindowText.argtypes = [HWND, LPWSTR, ctypes.c_int]
|
||||||
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
|
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
|
||||||
|
|
||||||
def WindowTitle(h):
|
def window_title(h) -> str:
|
||||||
|
"""
|
||||||
|
Determine the title for a window.
|
||||||
|
|
||||||
|
:param h: Window handle.
|
||||||
|
:return: Window title.
|
||||||
|
"""
|
||||||
if h:
|
if h:
|
||||||
l = GetWindowTextLength(h) + 1
|
title_length = GetWindowTextLength(h) + 1
|
||||||
buf = ctypes.create_unicode_buffer(l)
|
buf = ctypes.create_unicode_buffer(title_length)
|
||||||
if GetWindowText(h, buf, l):
|
if GetWindowText(h, buf, title_length):
|
||||||
return buf.value
|
return buf.value
|
||||||
|
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
|
|
||||||
class MOUSEINPUT(ctypes.Structure):
|
class MOUSEINPUT(ctypes.Structure):
|
||||||
_fields_ = [('dx', LONG), ('dy', LONG), ('mouseData', DWORD), ('dwFlags', DWORD), ('time', DWORD), ('dwExtraInfo', ctypes.POINTER(ULONG))]
|
"""Mouse Input structure."""
|
||||||
|
|
||||||
|
_fields_ = [
|
||||||
|
('dx', LONG),
|
||||||
|
('dy', LONG),
|
||||||
|
('mouseData', DWORD),
|
||||||
|
('dwFlags', DWORD),
|
||||||
|
('time', DWORD),
|
||||||
|
('dwExtraInfo', ctypes.POINTER(ULONG))
|
||||||
|
]
|
||||||
|
|
||||||
class KEYBDINPUT(ctypes.Structure):
|
class KEYBDINPUT(ctypes.Structure):
|
||||||
_fields_ = [('wVk', WORD), ('wScan', WORD), ('dwFlags', DWORD), ('time', DWORD), ('dwExtraInfo', ctypes.POINTER(ULONG))]
|
"""Keyboard Input structure."""
|
||||||
|
|
||||||
|
_fields_ = [
|
||||||
|
('wVk', WORD),
|
||||||
|
('wScan', WORD),
|
||||||
|
('dwFlags', DWORD),
|
||||||
|
('time', DWORD),
|
||||||
|
('dwExtraInfo', ctypes.POINTER(ULONG))
|
||||||
|
]
|
||||||
|
|
||||||
class HARDWAREINPUT(ctypes.Structure):
|
class HARDWAREINPUT(ctypes.Structure):
|
||||||
_fields_ = [('uMsg', DWORD), ('wParamL', WORD), ('wParamH', WORD)]
|
"""Hardware Input structure."""
|
||||||
|
|
||||||
class INPUT_union(ctypes.Union):
|
_fields_ = [
|
||||||
_fields_ = [('mi', MOUSEINPUT), ('ki', KEYBDINPUT), ('hi', HARDWAREINPUT)]
|
('uMsg', DWORD),
|
||||||
|
('wParamL', WORD),
|
||||||
|
('wParamH', WORD)
|
||||||
|
]
|
||||||
|
|
||||||
|
class INPUTUNION(ctypes.Union):
|
||||||
|
"""Input union."""
|
||||||
|
|
||||||
|
_fields_ = [
|
||||||
|
('mi', MOUSEINPUT),
|
||||||
|
('ki', KEYBDINPUT),
|
||||||
|
('hi', HARDWAREINPUT)
|
||||||
|
]
|
||||||
|
|
||||||
class INPUT(ctypes.Structure):
|
class INPUT(ctypes.Structure):
|
||||||
_fields_ = [('type', DWORD), ('union', INPUT_union)]
|
"""Input structure."""
|
||||||
|
|
||||||
|
_fields_ = [
|
||||||
|
('type', DWORD),
|
||||||
|
('union', INPUTUNION)
|
||||||
|
]
|
||||||
|
|
||||||
SendInput = ctypes.windll.user32.SendInput
|
SendInput = ctypes.windll.user32.SendInput
|
||||||
SendInput.argtypes = [ctypes.c_uint, ctypes.POINTER(INPUT), ctypes.c_int]
|
SendInput.argtypes = [ctypes.c_uint, ctypes.POINTER(INPUT), ctypes.c_int]
|
||||||
@ -361,12 +401,13 @@ elif platform == 'win32':
|
|||||||
INPUT_KEYBOARD = 1
|
INPUT_KEYBOARD = 1
|
||||||
INPUT_HARDWARE = 2
|
INPUT_HARDWARE = 2
|
||||||
|
|
||||||
|
|
||||||
class HotkeyMgr:
|
class HotkeyMgr:
|
||||||
|
"""Hot key management."""
|
||||||
|
|
||||||
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
|
# https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx
|
||||||
# Limit ourselves to symbols in Windows 7 Segoe UI
|
# Limit ourselves to symbols in Windows 7 Segoe UI
|
||||||
DISPLAY = { 0x03: 'Break', 0x08: 'Bksp', 0x09: u'↹', 0x0c: 'Clear', 0x0d: u'↵', 0x13: 'Pause',
|
DISPLAY = {
|
||||||
|
0x03: 'Break', 0x08: 'Bksp', 0x09: u'↹', 0x0c: 'Clear', 0x0d: u'↵', 0x13: 'Pause',
|
||||||
0x14: u'Ⓐ', 0x1b: 'Esc',
|
0x14: u'Ⓐ', 0x1b: 'Esc',
|
||||||
0x20: u'⏘', 0x21: 'PgUp', 0x22: 'PgDn', 0x23: 'End', 0x24: 'Home',
|
0x20: u'⏘', 0x21: 'PgUp', 0x22: 'PgDn', 0x23: 'End', 0x24: 'Home',
|
||||||
0x25: u'←', 0x26: u'↑', 0x27: u'→', 0x28: u'↓',
|
0x25: u'←', 0x26: u'↑', 0x27: u'→', 0x28: u'↓',
|
||||||
@ -385,7 +426,7 @@ elif platform == 'win32':
|
|||||||
self.snd_bad = sb.read()
|
self.snd_bad = sb.read()
|
||||||
atexit.register(self.unregister)
|
atexit.register(self.unregister)
|
||||||
|
|
||||||
def register(self, root, keycode, modifiers):
|
def register(self, root: tk.Tk, keycode, modifiers) -> None:
|
||||||
"""Register the hotkey handler."""
|
"""Register the hotkey handler."""
|
||||||
self.root = root
|
self.root = root
|
||||||
|
|
||||||
@ -395,13 +436,17 @@ elif platform == 'win32':
|
|||||||
|
|
||||||
if keycode or modifiers:
|
if keycode or modifiers:
|
||||||
logger.debug('Creating thread worker...')
|
logger.debug('Creating thread worker...')
|
||||||
self.thread = threading.Thread(target=self.worker, name=f'Hotkey "{keycode}:{modifiers}"', args=(keycode, modifiers))
|
self.thread = threading.Thread(
|
||||||
|
target=self.worker,
|
||||||
|
name=f'Hotkey "{keycode}:{modifiers}"',
|
||||||
|
args=(keycode, modifiers)
|
||||||
|
)
|
||||||
self.thread.daemon = True
|
self.thread.daemon = True
|
||||||
logger.debug('Starting thread worker...')
|
logger.debug('Starting thread worker...')
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
logger.debug('Done.')
|
logger.debug('Done.')
|
||||||
|
|
||||||
def unregister(self):
|
def unregister(self) -> None:
|
||||||
"""Unregister the hotkey handling."""
|
"""Unregister the hotkey handling."""
|
||||||
thread = self.thread
|
thread = self.thread
|
||||||
|
|
||||||
@ -418,7 +463,7 @@ elif platform == 'win32':
|
|||||||
|
|
||||||
logger.debug('Done.')
|
logger.debug('Done.')
|
||||||
|
|
||||||
def worker(self, keycode, modifiers):
|
def worker(self, keycode, modifiers) -> None: # noqa: CCR001
|
||||||
"""Handle hotkeys."""
|
"""Handle hotkeys."""
|
||||||
logger.debug('Begin...')
|
logger.debug('Begin...')
|
||||||
# Hotkey must be registered by the thread that handles it
|
# Hotkey must be registered by the thread that handles it
|
||||||
@ -427,7 +472,7 @@ elif platform == 'win32':
|
|||||||
self.thread = None
|
self.thread = None
|
||||||
return
|
return
|
||||||
|
|
||||||
fake = INPUT(INPUT_KEYBOARD, INPUT_union(ki=KEYBDINPUT(keycode, keycode, 0, 0, None)))
|
fake = INPUT(INPUT_KEYBOARD, INPUTUNION(ki=KEYBDINPUT(keycode, keycode, 0, 0, None)))
|
||||||
|
|
||||||
msg = MSG()
|
msg = MSG()
|
||||||
logger.debug('Entering GetMessage() loop...')
|
logger.debug('Entering GetMessage() loop...')
|
||||||
@ -438,7 +483,7 @@ elif platform == 'win32':
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
config.get_int('hotkey_always')
|
config.get_int('hotkey_always')
|
||||||
or WindowTitle(GetForegroundWindow()).startswith('Elite - Dangerous')
|
or window_title(GetForegroundWindow()).startswith('Elite - Dangerous')
|
||||||
):
|
):
|
||||||
if not config.shutting_down:
|
if not config.shutting_down:
|
||||||
logger.debug('Sending event <<Invoke>>')
|
logger.debug('Sending event <<Invoke>>')
|
||||||
@ -470,86 +515,135 @@ elif platform == 'win32':
|
|||||||
self.thread = None
|
self.thread = None
|
||||||
logger.debug('Done.')
|
logger.debug('Done.')
|
||||||
|
|
||||||
def acquire_start(self):
|
def acquire_start(self) -> None:
|
||||||
|
"""Start acquiring hotkey state via polling."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def acquire_stop(self):
|
def acquire_stop(self) -> None:
|
||||||
|
"""Stop acquiring hotkey state."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def fromevent(self, event):
|
def fromevent(self, event) -> Optional[Union[bool, Tuple]]: # noqa: CCR001
|
||||||
# event.state is a pain - it shows the state of the modifiers *before* a modifier key was pressed.
|
"""
|
||||||
# event.state *does* differentiate between left and right Ctrl and Alt and between Return and Enter
|
Return configuration (keycode, modifiers) or None=clear or False=retain previous.
|
||||||
# by putting KF_EXTENDED in bit 18, but RegisterHotKey doesn't differentiate.
|
|
||||||
modifiers = ((GetKeyState(VK_MENU) & 0x8000) and MOD_ALT) | ((GetKeyState(VK_CONTROL) & 0x8000) and MOD_CONTROL) | ((GetKeyState(VK_SHIFT) & 0x8000) and MOD_SHIFT) | ((GetKeyState(VK_LWIN) & 0x8000) and MOD_WIN) | ((GetKeyState(VK_RWIN) & 0x8000) and MOD_WIN)
|
event.state is a pain - it shows the state of the modifiers *before* a modifier key was pressed.
|
||||||
|
event.state *does* differentiate between left and right Ctrl and Alt and between Return and Enter
|
||||||
|
by putting KF_EXTENDED in bit 18, but RegisterHotKey doesn't differentiate.
|
||||||
|
|
||||||
|
:param event: tk event ?
|
||||||
|
:return: False to retain previous, None to not use, else (keycode, modifiers)
|
||||||
|
"""
|
||||||
|
modifiers = ((GetKeyState(VK_MENU) & 0x8000) and MOD_ALT) \
|
||||||
|
| ((GetKeyState(VK_CONTROL) & 0x8000) and MOD_CONTROL) \
|
||||||
|
| ((GetKeyState(VK_SHIFT) & 0x8000) and MOD_SHIFT) \
|
||||||
|
| ((GetKeyState(VK_LWIN) & 0x8000) and MOD_WIN) \
|
||||||
|
| ((GetKeyState(VK_RWIN) & 0x8000) and MOD_WIN)
|
||||||
keycode = event.keycode
|
keycode = event.keycode
|
||||||
|
|
||||||
if keycode in [ VK_SHIFT, VK_CONTROL, VK_MENU, VK_LWIN, VK_RWIN ]:
|
if keycode in [VK_SHIFT, VK_CONTROL, VK_MENU, VK_LWIN, VK_RWIN]:
|
||||||
return (0, modifiers)
|
return (0, modifiers)
|
||||||
|
|
||||||
if not modifiers:
|
if not modifiers:
|
||||||
if keycode == VK_ESCAPE: # Esc = retain previous
|
if keycode == VK_ESCAPE: # Esc = retain previous
|
||||||
return False
|
return False
|
||||||
elif keycode in [ VK_BACK, VK_DELETE, VK_CLEAR, VK_OEM_CLEAR ]: # BkSp, Del, Clear = clear hotkey
|
|
||||||
|
elif keycode in [VK_BACK, VK_DELETE, VK_CLEAR, VK_OEM_CLEAR]: # BkSp, Del, Clear = clear hotkey
|
||||||
return None
|
return None
|
||||||
elif keycode in [ VK_RETURN, VK_SPACE, VK_OEM_MINUS] or ord('A') <= keycode <= ord('Z'): # don't allow keys needed for typing in System Map
|
|
||||||
|
elif keycode in [VK_RETURN, VK_SPACE, VK_OEM_MINUS] or ord('A') <= keycode <= ord(
|
||||||
|
'Z'): # don't allow keys needed for typing in System Map
|
||||||
winsound.MessageBeep()
|
winsound.MessageBeep()
|
||||||
return None
|
return None
|
||||||
elif keycode in [ VK_NUMLOCK, VK_SCROLL, VK_PROCESSKEY ] or VK_CAPITAL <= keycode <= VK_MODECHANGE: # ignore unmodified mode switch keys
|
|
||||||
|
elif (keycode in [VK_NUMLOCK, VK_SCROLL, VK_PROCESSKEY]
|
||||||
|
or VK_CAPITAL <= keycode <= VK_MODECHANGE): # ignore unmodified mode switch keys
|
||||||
return (0, modifiers)
|
return (0, modifiers)
|
||||||
|
|
||||||
# See if the keycode is usable and available
|
# See if the keycode is usable and available
|
||||||
if RegisterHotKey(None, 2, modifiers|MOD_NOREPEAT, keycode):
|
if RegisterHotKey(None, 2, modifiers | MOD_NOREPEAT, keycode):
|
||||||
UnregisterHotKey(None, 2)
|
UnregisterHotKey(None, 2)
|
||||||
return (keycode, modifiers)
|
return (keycode, modifiers)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
winsound.MessageBeep()
|
winsound.MessageBeep()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def display(self, keycode, modifiers):
|
def display(self, keycode, modifiers) -> str:
|
||||||
|
"""
|
||||||
|
Return displayable form of given hotkey + modifiers.
|
||||||
|
|
||||||
|
:param keycode:
|
||||||
|
:param modifiers:
|
||||||
|
:return: string form
|
||||||
|
"""
|
||||||
text = ''
|
text = ''
|
||||||
if modifiers & MOD_WIN: text += u'❖+'
|
if modifiers & MOD_WIN:
|
||||||
if modifiers & MOD_CONTROL: text += u'Ctrl+'
|
text += u'❖+'
|
||||||
if modifiers & MOD_ALT: text += u'Alt+'
|
|
||||||
if modifiers & MOD_SHIFT: text += u'⇧+'
|
if modifiers & MOD_CONTROL:
|
||||||
if VK_NUMPAD0 <= keycode <= VK_DIVIDE: text += u'№'
|
text += u'Ctrl+'
|
||||||
|
|
||||||
|
if modifiers & MOD_ALT:
|
||||||
|
text += u'Alt+'
|
||||||
|
|
||||||
|
if modifiers & MOD_SHIFT:
|
||||||
|
text += u'⇧+'
|
||||||
|
|
||||||
|
if VK_NUMPAD0 <= keycode <= VK_DIVIDE:
|
||||||
|
text += u'№'
|
||||||
|
|
||||||
if not keycode:
|
if not keycode:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif VK_F1 <= keycode <= VK_F24:
|
elif VK_F1 <= keycode <= VK_F24:
|
||||||
text += 'F%d' % (keycode + 1 - VK_F1)
|
text += f'F{keycode + 1 - VK_F1}'
|
||||||
|
|
||||||
elif keycode in HotkeyMgr.DISPLAY: # specials
|
elif keycode in HotkeyMgr.DISPLAY: # specials
|
||||||
text += HotkeyMgr.DISPLAY[keycode]
|
text += HotkeyMgr.DISPLAY[keycode]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
c = MapVirtualKey(keycode, 2) # printable ?
|
c = MapVirtualKey(keycode, 2) # printable ?
|
||||||
if not c: # oops not printable
|
if not c: # oops not printable
|
||||||
text += u'⁈'
|
text += u'⁈'
|
||||||
|
|
||||||
elif c < 0x20: # control keys
|
elif c < 0x20: # control keys
|
||||||
text += chr(c+0x40)
|
text += chr(c + 0x40)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
text += chr(c).upper()
|
text += chr(c).upper()
|
||||||
|
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def play_good(self):
|
def play_good(self) -> None:
|
||||||
|
"""Play the 'good' sound."""
|
||||||
if self.thread:
|
if self.thread:
|
||||||
PostThreadMessage(self.thread.ident, WM_SND_GOOD, 0, 0)
|
PostThreadMessage(self.thread.ident, WM_SND_GOOD, 0, 0)
|
||||||
|
|
||||||
def play_bad(self):
|
def play_bad(self) -> None:
|
||||||
|
"""Play the 'bad' sound."""
|
||||||
if self.thread:
|
if self.thread:
|
||||||
PostThreadMessage(self.thread.ident, WM_SND_BAD, 0, 0)
|
PostThreadMessage(self.thread.ident, WM_SND_BAD, 0, 0)
|
||||||
|
|
||||||
else: # Linux
|
else: # Linux
|
||||||
|
|
||||||
class HotkeyMgr:
|
class HotkeyMgr:
|
||||||
|
"""Hot key management."""
|
||||||
|
|
||||||
def register(self, root, keycode, modifiers):
|
def register(self, root, keycode, modifiers) -> None:
|
||||||
|
"""Register the hotkey handler."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def unregister(self):
|
def unregister(self) -> None:
|
||||||
|
"""Unregister the hotkey handling."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def play_good(self):
|
def play_good(self) -> None:
|
||||||
|
"""Play the 'good' sound."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def play_bad(self):
|
def play_bad(self) -> None:
|
||||||
|
"""Play the 'bad' sound."""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# singleton
|
# singleton
|
||||||
|
Loading…
x
Reference in New Issue
Block a user